diff --git a/.dockerignore b/.dockerignore index 93fc854..531f60f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -78,4 +78,11 @@ telemetry_test_lxmf/ .coverage .hypothesis -.hypothesis/ \ No newline at end of file +.hypothesis/ + +# Arch Linux packaging artifacts +/packaging/arch/src/ +/packaging/arch/pkg/ +/packaging/arch/*.pkg.tar.zst +/packaging/arch/MeshChatX/ +/packaging/arch/reticulum-meshchatx/ diff --git a/.gitea/workflows/android-build.yml b/.gitea/workflows/android-build.yml index 3657a5b..deb8435 100644 --- a/.gitea/workflows/android-build.yml +++ b/.gitea/workflows/android-build.yml @@ -57,7 +57,7 @@ jobs: - name: Install pnpm uses: https://git.quad4.io/actions/setup-pnpm@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 with: - version: 10.0.0 + version: 10.27.0 - name: Install system dependencies run: | diff --git a/.gitea/workflows/arch-package.yml b/.gitea/workflows/arch-package.yml new file mode 100644 index 0000000..7f7bc69 --- /dev/null +++ b/.gitea/workflows/arch-package.yml @@ -0,0 +1,27 @@ +name: Arch Linux Package + +on: + push: + tags: + - "*" + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://git.quad4.io/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + fetch-depth: 0 + + - name: Build Arch Package + run: | + docker build -t arch-builder -f Dockerfile.arch-builder . + docker run --rm -v $(pwd):/home/build/project arch-builder + + - name: Upload Artifact + uses: https://git.quad4.io/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 + with: + name: arch-package + path: packaging/arch/*.pkg.tar.zst diff --git a/.gitea/workflows/bench.yml b/.gitea/workflows/bench.yml new file mode 100644 index 0000000..5a54026 --- /dev/null +++ b/.gitea/workflows/bench.yml @@ -0,0 +1,45 @@ +name: Benchmarks + +on: + workflow_dispatch: + +jobs: + benchmark: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://git.quad4.io/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: Setup Node.js + uses: https://git.quad4.io/actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 + with: + node-version: 22 + cache: pnpm + + - name: Setup Python + uses: https://git.quad4.io/actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + with: + python-version: "3.13" + + - name: Setup Task + uses: https://git.quad4.io/actions/setup-task@0ab1b2a65bc55236a3bc64cde78f80e20e8885c2 # v1 + with: + version: "3.46.3" + + - name: Setup Poetry + run: pip install poetry + + - name: Install dependencies + run: task install + + - name: Run Benchmarks + id: bench + run: | + set -o pipefail + task bench 2>&1 | tee bench_results.txt + + - name: Run Integrity Tests + id: integrity + run: | + set -o pipefail + task test-integrity 2>&1 | tee -a bench_results.txt diff --git a/.gitea/workflows/build-test.yml b/.gitea/workflows/build-test.yml new file mode 100644 index 0000000..15a8f63 --- /dev/null +++ b/.gitea/workflows/build-test.yml @@ -0,0 +1,107 @@ +name: Build Test + +on: + push: + branches: + - "*" + pull_request: + branches: + - "*" + +jobs: + build-test: + name: Build and Test + runs-on: ubuntu-latest + steps: + - name: Clone Repo + uses: https://git.quad4.io/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + fetch-depth: 0 + + - name: Install NodeJS + uses: https://git.quad4.io/actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 + with: + node-version: 22 + + - name: Install Python + uses: https://git.quad4.io/actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + with: + python-version: "3.13" + + - name: Install Poetry + run: python -m pip install --upgrade pip poetry>=2.0.0 + + - name: Install pnpm + uses: https://git.quad4.io/actions/setup-pnpm@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + with: + version: 10.27.0 + + - name: Install system dependencies + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install -y wine32:i386 wine64 patchelf libopusfile0 ffmpeg espeak-ng nsis zip rpm flatpak flatpak-builder elfutils appstream appstream-util + flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo + # Install runtimes required for Flatpak build + flatpak install --user -y flathub org.freedesktop.Platform//24.08 org.freedesktop.Sdk//24.08 org.electronjs.Electron2.BaseApp//24.08 + + - name: Setup Task + uses: https://git.quad4.io/actions/setup-task@0ab1b2a65bc55236a3bc64cde78f80e20e8885c2 # v1 + with: + version: "3.46.3" + + - name: Install dependencies + run: task install + + - name: Build Frontend + run: task build-frontend + + - name: Build Backend (Wheel) + run: task wheel + + - name: Build Electron App (Linux) + run: pnpm run dist:linux + + - name: Build Electron App (RPM - Experimental) + continue-on-error: true + run: task build-rpm + + - name: Build Electron App (Flatpak - Experimental) + continue-on-error: true + run: task build-flatpak + + - name: Build Electron App (Windows EXE and NSIS) + env: + WINEDEBUG: -all + run: pnpm run dist:windows + + - name: Build Electron App (ZIP) + run: task build-zip + + - name: Prepare release assets + run: | + mkdir -p release-assets + # Collect Linux artifacts + find dist -maxdepth 1 -type f \( -name "*-linux*.AppImage" -o -name "*-linux*.deb" -o -name "*-linux*.rpm" -o -name "*-linux*.flatpak" \) -exec cp {} release-assets/ \; + # Collect Windows artifacts + find dist -maxdepth 1 -type f \( -name "*-win*.exe" \) -exec cp {} release-assets/ \; + # Collect ZIP artifacts from Electron Forge + find out/make -type f -name "*.zip" -exec cp {} release-assets/ \; + # Collect Python artifacts + find python-dist -maxdepth 1 -type f -name "*.whl" -exec cp {} release-assets/ \; + # Create frontend zip + (cd meshchatx/public && zip -r ../../release-assets/meshchatx-frontend.zip .) + + # Generate checksums + cd release-assets + for file in *; do + if [ -f "$file" ] && [[ "$file" != *.sha256 ]]; then + sha256sum "$file" | tee "${file}.sha256" + fi + done + + - name: Upload artifacts + uses: https://git.quad4.io/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 + with: + name: meshchatx-artifacts + path: release-assets/* diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 35dad2b..cc6eb76 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -41,7 +41,7 @@ jobs: if [ -z "${VERSION}" ]; then VERSION="${{ github.ref_name }}" fi - if [ "${VERSION}" = "master" ] || [ "${VERSION}" = "main" ]; then + if [ "${VERSION}" = "master" ]; then echo "Error: Invalid tag name '${VERSION}'. Tag name cannot be a branch name." >&2 exit 1 fi @@ -67,12 +67,14 @@ jobs: - name: Install pnpm uses: https://git.quad4.io/actions/setup-pnpm@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 with: - version: 10.0.0 + version: 10.27.0 - name: Install system dependencies run: | + sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install -y patchelf libopusfile0 ffmpeg espeak-ng wine nsis + sudo apt-get install -y wine32:i386 wine64 patchelf libopusfile0 ffmpeg espeak-ng nsis zip rpm flatpak flatpak-builder elfutils + flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo - name: Setup Task uses: https://git.quad4.io/actions/setup-task@0ab1b2a65bc55236a3bc64cde78f80e20e8885c2 # v1 @@ -88,23 +90,46 @@ jobs: - name: Build Python wheel run: task wheel - - name: Build Electron App (Linux) + - name: Build Electron App (Appimage) run: pnpm run dist:linux - - name: Build Electron App (Windows) + - name: Build Electron App (RPM) + continue-on-error: true + run: task build-rpm + + - name: Build Electron App (Flatpak) + continue-on-error: true + run: task build-flatpak + + - name: Build Electron App (Windows EXE and NSIS) + env: + WINEDEBUG: -all run: pnpm run dist:windows + - name: Build Electron App (ZIP) + run: task build-zip + - name: Prepare release assets run: | mkdir -p release-assets # Collect artifacts from dist/ # Linux artifacts - find dist -maxdepth 1 -type f \( -name "*-linux*.AppImage" -o -name "*-linux*.deb" \) -exec cp {} release-assets/ \; + find dist -maxdepth 1 -type f \( -name "*-linux*.AppImage" -o -name "*-linux*.deb" -o -name "*-linux*.rpm" -o -name "*-linux*.flatpak" \) -exec cp {} release-assets/ \; # Windows artifacts find dist -maxdepth 1 -type f \( -name "*-win*.exe" \) -exec cp {} release-assets/ \; + # ZIP artifacts from Electron Forge + find out/make -type f -name "*.zip" -exec cp {} release-assets/ \; # Python artifacts find python-dist -maxdepth 1 -type f -name "*.whl" -exec cp {} release-assets/ \; + # Create frontend zip + (cd meshchatx/public && zip -r ../../release-assets/meshchatx-frontend.zip .) + + # Generate SBOM (CycloneDX) + curl -L -o /tmp/trivy.deb https://git.quad4.io/Quad4-Extra/assets/raw/commit/90fdcea1bb71d91df2de6ff2e3897f278413f300/bin/trivy_0.68.2_Linux-64bit.deb + sudo dpkg -i /tmp/trivy.deb || sudo apt-get install -f -y + trivy fs --format cyclonedx --include-dev-deps --output release-assets/sbom.cyclonedx.json . + # Generate checksums cd release-assets for file in *; do @@ -134,7 +159,7 @@ jobs: echo "Error: Version is empty" >&2 exit 1 fi - if [ "${VERSION}" = "master" ] || [ "${VERSION}" = "main" ]; then + if [ "${VERSION}" = "master" ]; then echo "Error: Invalid version '${VERSION}'. Version cannot be a branch name." >&2 exit 1 fi @@ -151,9 +176,13 @@ jobs: files: | release-assets/*.AppImage release-assets/*.deb + release-assets/*.rpm + release-assets/*.flatpak release-assets/*.exe release-assets/*.whl release-assets/*.sha256 + release-assets/*.zip + release-assets/sbom.cyclonedx.json body_path: "release-body.md" draft: false prerelease: false diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index f32086e..5b40e00 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -33,7 +33,9 @@ jobs: - name: Install Node dependencies run: task node_modules - name: Lint - run: task lint + run: | + set -o pipefail + task lint 2>&1 | tee lint_results.txt build-frontend: runs-on: ubuntu-latest @@ -57,7 +59,9 @@ jobs: SHORT_SHA=$(git rev-parse --short HEAD) echo "version=${SHORT_SHA}" >> $GITHUB_OUTPUT - name: Build frontend - run: task build-frontend + run: | + set -o pipefail + task build-frontend 2>&1 | tee build_results.txt env: VITE_APP_VERSION: ${{ steps.version.outputs.version }} @@ -75,4 +79,33 @@ jobs: with: version: "3.46.3" - name: Compile backend - run: task compile + run: | + set -o pipefail + task compile 2>&1 | tee compile_results.txt + + test-lang: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://git.quad4.io/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - name: Setup Node.js + uses: https://git.quad4.io/actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 + with: + node-version: 22 + cache: pnpm + - name: Setup Python + uses: https://git.quad4.io/actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + with: + python-version: "3.13" + - name: Setup Task + uses: https://git.quad4.io/actions/setup-task@0ab1b2a65bc55236a3bc64cde78f80e20e8885c2 # v1 + with: + version: "3.46.3" + - name: Setup Poetry + run: pip install poetry + - name: Install dependencies + run: task install + - name: Run language tests + run: | + set -o pipefail + task test-lang 2>&1 | tee lang_results.txt diff --git a/.gitea/workflows/docker.yml b/.gitea/workflows/docker.yml index 8234e2b..3956972 100644 --- a/.gitea/workflows/docker.yml +++ b/.gitea/workflows/docker.yml @@ -67,6 +67,17 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + - name: Download Trivy + run: | + curl -L -o /tmp/trivy.deb https://git.quad4.io/Quad4-Extra/assets/raw/commit/90fdcea1bb71d91df2de6ff2e3897f278413f300/bin/trivy_0.68.2_Linux-64bit.deb + sudo dpkg -i /tmp/trivy.deb || sudo apt-get install -f -y + + - name: Scan Docker image + run: | + # Extract the first tag from the multi-line tags output + IMAGE_TAG=$(echo "${{ steps.meta.outputs.tags }}" | head -n 1) + trivy image --exit-code 1 "$IMAGE_TAG" + build-dev: if: github.event_name == 'pull_request' runs-on: ubuntu-latest @@ -114,3 +125,14 @@ jobs: push: true tags: ${{ steps.meta-dev.outputs.tags }} labels: ${{ steps.meta-dev.outputs.labels }} + + - name: Download Trivy + run: | + curl -L -o /tmp/trivy.deb https://git.quad4.io/Quad4-Extra/assets/raw/commit/90fdcea1bb71d91df2de6ff2e3897f278413f300/bin/trivy_0.68.2_Linux-64bit.deb + sudo dpkg -i /tmp/trivy.deb || sudo apt-get install -f -y + + - name: Scan Docker image (dev) + run: | + # Extract the first tag from the multi-line tags output + IMAGE_TAG=$(echo "${{ steps.meta-dev.outputs.tags }}" | head -n 1) + trivy image --exit-code 1 "$IMAGE_TAG" diff --git a/.gitea/workflows/osv-pr.yml b/.gitea/workflows/osv-pr.yml new file mode 100644 index 0000000..14113a0 --- /dev/null +++ b/.gitea/workflows/osv-pr.yml @@ -0,0 +1,20 @@ +name: OSV-Scanner PR Scan + +on: + pull_request: + branches: [master] + merge_group: + branches: [master] + +permissions: + contents: read + +jobs: + scan-pr: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://git.quad4.io/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: OSV scan + run: bash scripts/osv_scan.sh diff --git a/.gitea/workflows/osv-scheduled.yml b/.gitea/workflows/osv-scheduled.yml new file mode 100644 index 0000000..a3ea11f --- /dev/null +++ b/.gitea/workflows/osv-scheduled.yml @@ -0,0 +1,20 @@ +name: OSV-Scanner Scheduled Scan + +on: + schedule: + - cron: "30 12 * * 1" + push: + branches: [master] + +permissions: + contents: read + +jobs: + scan-scheduled: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: https://git.quad4.io/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: OSV scan + run: bash scripts/osv_scan.sh diff --git a/.gitea/workflows/tests.yml b/.gitea/workflows/tests.yml index 6bf307a..9970e17 100644 --- a/.gitea/workflows/tests.yml +++ b/.gitea/workflows/tests.yml @@ -37,4 +37,6 @@ jobs: run: task install - name: Run tests - run: task test + run: | + set -o pipefail + task test 2>&1 | tee test_results.txt diff --git a/.gitignore b/.gitignore index 3f9b5f0..fc89eb1 100644 --- a/.gitignore +++ b/.gitignore @@ -76,4 +76,18 @@ Thumbs.db meshchat-config/ .hypothesis -.hypothesis/ \ No newline at end of file +.hypothesis/ + +MagicMock/ +out/ + +# Arch Linux packaging artifacts +/packaging/arch/src/ +/packaging/arch/pkg/ +/packaging/arch/*.pkg.tar.zst +/packaging/arch/MeshChatX/ +/packaging/arch/reticulum-meshchatx/ + +electron/backend-manifest.json + +scripts/private/ \ No newline at end of file diff --git a/.npmrc b/.npmrc index d1a2a0f..d67f374 100644 --- a/.npmrc +++ b/.npmrc @@ -1,6 +1 @@ -registry=https://registry.npmjs.org/ -fetch-retries=5 -fetch-retry-mintimeout=20000 -fetch-retry-maxtimeout=120000 -fetch-timeout=300000 - +node-linker=hoisted diff --git a/.prettierignore b/.prettierignore index 048274e..5ab4ab5 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,9 +1,31 @@ -dist -node_modules -build -electron/assets -meshchatx/public -pnpm-lock.yaml -poetry.lock -*.log +# Prettier ignore file +# Dependencies +node_modules/ +pnpm-lock.yaml + +# Build output +dist/ +build/ +linux-unpacked/ +win-unpacked/ +mac-unpacked/ + +# Public assets and libraries +meshchatx/public/ +meshchatx/src/frontend/public/ +meshchatx/src/frontend/style.css + +# Other +storage/ +__pycache__/ +.venv/ +MagicMock/ +*.min.js +*.wasm +*.proto + +# Documentation and misc +misc/README.md +android/README.md +CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d767d73 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,120 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [4.0.0] - 2026-01-03 + +Season 1 Episode 1 - A MASSIVE REFACTOR + +### New Features + +- **Banishment System (formerly Blocked):** + - Renamed all instances of "Blocked" to **"Banished"**, you can now banish really annoying people to the shadow realm. + - **Blackhole Integration:** Automatically blackholes identities at the RNS transport layer when they are banished in MeshChatX. This prevents their traffic from being relayed through your node and publishes the update to your interfaces (trusted interfaces will pull and enforce the banishment). + - Integrated RNS 1.1.0 Blackhole to display publishing status, sources, and current blackhole counts in the RNStatus page. +- **RNPath Management Tool:** New UI tool to manage the Reticulum path table, monitor announce rates (with rate-limit detection), and perform manual path requests or purges directly from the app. +- **Maps:** You can now draw and doodle directly on the map to mark locations or plan routes. +- **Calls & Audio:** + - Added support for custom ringtones and a brand-new ringtone editor. + - New **Audio Waveform Visualization** for voice messages, providing interactive playback with a visual waveform representation. +- **Paper Messages:** Introduced a tool for generating and scanning paper-based messages with built-in QR code generation for easy sharing. +- **LXMF Telemetry & Live Tracking**: + - Full implementation of Sideband-compatible (Still need to test Columba) telemetry (FIELD_TELEMETRY & FIELD_TELEMETRY_STREAM). + - Live tracking with real-time map updates, distinct blue pulsing animations, and historical path tracing (breadcrumb trails). + - Mini-chat integrated into map markers for quick communication with telemetry peers. + - Privacy controls with global telemetry toggle and per-peer "Trust for Telemetry" settings. + - Detailed telemetry history timeline with interactive battery voltage/percentage sparkline charts. +- **Documentation:** You can now read all the project guides and help docs directly inside the app. +- **Reliability:** + - If the app ever crashes, it's now much better at picking up right where it left off without losing your data. + - Added **Identity Switch Recovery**: mechanism to restore previous identities or create emergency failsafes if a switch fails. + - Multi-Identity "Keep-Alive": Identities can now be kept active in the background when switching, ensuring you still receive messages and calls across all your personas. + - Added **Database Snapshotting & Auto-Backups**: You can now create named snapshots of your database and the app will perform automatic backups every 12 hours. + - Added **Emergency Comms Mode**: A lightweight mode that bypasses database storage and non-essential managers, useful for recovering from corrupted data or running in restricted environments. Can be engaged via UI, CLI flag (`--emergency`), or environment variable (`MESHCHAT_EMERGENCY=1`). + - Added **Snapshot Restoration**: Ability to restore from a specific snapshot on startup via `--restore-from-snapshot` or `MESHCHAT_RESTORE_SNAPSHOT` environment variable. +- **Diagnostics:** + - New **Debug Logs Screen**: View and export internal system logs directly from the UI for easier troubleshooting. +- **Community:** Better support for community-run network interfaces and checking TCP ping status of suggested interfaces. +- **UI Tweaks:** Added a new confirmation box for important actions and a better sidebar for browsing your archived messages. +- **Micron Editor:** Added multi-tab support with IndexedDB persistence, tab renaming, and a full editor reset button. +- **Desktop Enhancements (Electron):** + * **Multi-Window Calls:** Optional support for popping active calls into a focused 2nd window. + * **System Tray Integration:** The app now minimizes to the system tray, keeping you connected to the mesh in the background. + * **Native Notifications:** Switched to system-native notifications with deep-linking (click to focus conversation). + * **Protocol Handling:** Register as default handler for `lxmf://` and `rns://` links for seamless cross-app navigation. + * **Hardware Acceleration Toggle:** Power-user setting to disable GPU acceleration if flickering or glitches occur. + * **Power Management:** Automatically prevents system sleep during active audio calls to maintain RNS path stability. +- **Added Web Audio Bridge** which allows web/electron to hook into LXST backend for passing microphone and audio streams to active telephone calls. +- **Added LXMFy** for running bots. +- **Added RNS Discoverable Interfaces** https://markqvist.github.io/Reticulum/manual/interfaces.html#discoverable-interfaces and ability to map them (ones with a location). + +### Improvements + +- **Blazingly Fast Performance:** + - **Network Rendering:** The Network Visualizer now uses intelligent batching to handle hundreds of nodes without freezing your screen. + - **Memory Optimization:** Added a smart icon cache that automatically clears itself to keep the app's memory footprint low. + - **Parallel Loading:** The app now fetches network data in parallel, cutting down startup and refresh times significantly. + - **Lazy Loading:** Documentation and other heavy components now load only when you need them, making the initial app launch much faster. + - **Smoother Settings:** Changing settings now uses "smart saving" (debouncing) to prevent unnecessary disk work and keep the interface responsive. + - **Backend Efficiency:** A massive core refactor and new database optimizations make message handling and search nearly instantaneous. Added pagination to announce and discovery lists to improve performance in large networks. +- **Calling:** The call screen and overlays have been completely redesigned to look better and work more smoothly. +- **Messaging:** + - Polished the message lists and archive views to make them easier to navigate. + - Added "Retry All" functionality for failed or cancelled messages in conversation views. + - Improved handling of `lxm.ingest_uri.result` with detailed notifications for success/error/warning states. +- **Maintenance Tools:** Added new maintenance utilities to clear LXMF user icon caches and manage backup configurations. +- **Network View:** The visualizer that shows your network connections is now much clearer and easier to understand. +- **Languages:** Updated translations for English, German, and Russian. Added **Italian (it-IT)** localization. Added a toggle to easily enable or disable translation services. +- **Search:** The command palette (quick search) and notification bell are now more useful. +- **CartoDB Tiles** - some more styles if OSM is not enough for you, MBtiles will export tiles from the selected one. +- **Basic Markdown in Messages** - Support for basic markdown in messages + +### Bug Fixes + +- Fixed issues where switching between different identities could sometimes cause glitches. +- Fixed several small bugs that could cause messages to get stuck or out of order. +- Lots of small UI fixes to make buttons and menus look right on different screens. +- Fixed glitchy message page + +### Technical + + - **Backend Architecture:** + - Decoupled logic into new specialized managers: `community_interfaces.py`, `docs_manager.py`, `identity_manager.py`, `voicemail_manager.py`, and `nomadnet_utils.py`. + - Added specialized utility modules: `meshchat_utils.py`, `lxmf_utils.py`, `async_utils.py`, and `identity_context.py`. + - Implemented a robust state-based crash recovery system in `src/backend/recovery/`. + - **Self-Healing Database Schema**: Enhanced `DatabaseSchema` with automatic column synchronization to prevent crashes when upgrading from older versions with missing columns. + - Enhanced database layer with `map_drawings.py` and improved `telephone.py` schema for call logging. + - Standardized markdown processing with a new `markdown_renderer.py`. + - Added pagination support for announce queries in `AnnounceManager`. + - **Performance Engineering & Memory Profiling:** + - Integrated a comprehensive backend benchmarking suite (`tests/backend/run_comprehensive_benchmarks.py`) with high-precision timing and memory delta tracking. + - Added an **EXTREME Stress Mode** to simulate ultra-high load scenarios (100,000+ messages and 50,000+ announces). + - Implemented automated memory leak detection and profiling tests using `psutil` and custom `MemoryTracker` utilities. + - **Full-Stack Integrity & Anti-Tampering:** + - Implemented **Backend Binary Verification**: The app now generates a SHA-256 manifest of the unpacked Python backend during build and verifies it on every startup in Electron. + - Added **Data-at-Rest Integrity Monitoring**: The backend now snapshots the state of identities and database files on clean shutdown and warns if they were modified while the app was closed. + - New **Security Integrity Modal**: Notifies the user via a persistent modal if any tampering is detected, with a version-specific "do not show again" option. +- **Frontend Refactor:** + - Migrated complex call logic into `CallOverlay.vue` and `CallPage.vue` with improved state management. + - Implemented modular UI components: `ArchiveSidebar.vue`, `RingtoneEditor.vue`, `ConfirmDialog.vue`, and `AudioWaveformPlayer.vue`. + - Integrated a new documentation browsing system in `src/frontend/components/docs/`. + - Added custom Leaflet integration for map drawing persistence in `MapPage.vue`. +- **Infrastructure:** + - Added `Dockerfile.build` for multi-stage container builds. + - Introduced `gen_checksums.sh` for release artifact integrity. + - **Comprehensive Testing Suite:** + - Added 80+ new unit, integration, and fuzz tests across `tests/backend/` and `tests/frontend/`. + - Implemented property-based fuzzing for LXMF message parsing and telemetry packing using `hypothesis`. + - Updated CI coverage for telemetry and network interface logic. + - Updated core dependencies: `rns`, `lxmf`, `aiohttp`, and `websockets`. + - **Developer Tools & CI:** + - New `task` commands: `bench-backend` (Standard suite), `bench-extreme` (Breaking Time and Space), `profile-memory` (Leak testing), and `bench` (Full run). + - Added Gitea Actions workflow (`bench.yml`) for automated performance regression tracking on every push. +- **Utilize Electron 39 features:** + - Enabled **ASAR Integrity Validation** (Stable in E39) to protect the application against tampering. + - Hardened security by disabling `runAsNode` and `nodeOptions` environment variables via Electron Fuses. + - Implemented **3-Layer CSP Hardening**: Multi-layered Content Security Policy protection across the entire application stack: + 1. **Backend Server CSP** (`meshchatx/meshchat.py`): Applied via `security_middleware` to all HTTP responses, allowing localhost connections, websockets, and required external resources (OpenStreetMap tiles, etc.). + 2. **Electron Session CSP** (`electron/main.js`): Shell-level fallback CSP applied via `webRequest.onHeadersReceived` handler to ensure coverage before the backend starts and for all Electron-rendered content. + 3. **Loading Screen CSP** (`electron/loading.html`): Bootloader CSP defined in HTML meta tag to protect the initial loading screen while waiting for the backend API to come online. + - Added hardware acceleration monitoring to ensure the Network Visualiser and UI are performing optimally. diff --git a/Dockerfile b/Dockerfile index 914607d..f7fc59b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,37 +1,57 @@ -FROM node:22-alpine@sha256:0340fa682d72068edf603c305bfbc10e23219fb0e40df58d9ea4d6f33a9798bf AS build-frontend +ARG NODE_IMAGE=node:22-alpine +ARG NODE_HASH=sha256:0340fa682d72068edf603c305bfbc10e23219fb0e40df58d9ea4d6f33a9798bf +ARG PYTHON_IMAGE=python:3.12.12-alpine3.23 +ARG PYTHON_HASH=sha256:68d81cd281ee785f48cdadecb6130d05ec6957f1249814570dc90e5100d3b146 +# Stage 1: Build Frontend +FROM ${NODE_IMAGE}@${NODE_HASH} AS build-frontend WORKDIR /src - -COPY package.json vite.config.js tailwind.config.js postcss.config.js ./ -COPY pnpm-lock.yaml ./ +COPY package.json pnpm-lock.yaml vite.config.js tailwind.config.js postcss.config.js ./ COPY meshchatx/src/frontend ./meshchatx/src/frontend - -RUN corepack enable && corepack prepare pnpm@latest --activate - -RUN pnpm install --frozen-lockfile && \ +RUN corepack enable && corepack prepare pnpm@latest --activate && \ + pnpm install --frozen-lockfile && \ pnpm run build-frontend -FROM python:3.13-alpine@sha256:e7e041128ffc3e3600509f508e44d34ab08ff432bdb62ec508d01dfc5ca459f7 - -WORKDIR /app - -RUN apk add --no-cache ffmpeg espeak-ng opusfile libffi-dev - +# Stage 2: Build Backend & Virtual Environment +FROM ${PYTHON_IMAGE}@${PYTHON_HASH} AS builder +WORKDIR /build +# Install build dependencies for C-extensions +RUN apk add --no-cache gcc musl-dev linux-headers python3-dev libffi-dev openssl-dev git +# Setup venv and install dependencies +RUN python -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" COPY pyproject.toml poetry.lock ./ -RUN apk add --no-cache --virtual .build-deps \ - gcc \ - musl-dev \ - linux-headers \ - python3-dev && \ - pip install --no-cache-dir poetry && \ +RUN pip install --no-cache-dir "pip>=25.3" poetry setuptools wheel && \ poetry config virtualenvs.create false && \ - poetry install --no-root --only main && \ - apk del .build-deps + poetry install --no-root --only main +# Copy source code and built frontend COPY meshchatx ./meshchatx - COPY --from=build-frontend /src/meshchatx/public ./meshchatx/public -ENV PYTHONUNBUFFERED=1 +# Install the package itself into the venv +RUN pip install . && \ + # Trigger LXST filter compilation while build tools are still present + python -c "import LXST.Filters; print('LXST Filters compiled successfully')" && \ + python -m compileall /opt/venv/lib/python3.12/site-packages -CMD ["python", "-m", "meshchatx.meshchat", "--host=0.0.0.0", "--reticulum-config-dir=/config/.reticulum", "--storage-dir=/config/.meshchat", "--headless"] +# Stage 3: Final Runtime Image +FROM ${PYTHON_IMAGE}@${PYTHON_HASH} +WORKDIR /app +# Install runtime dependencies only +# We keep py3-setuptools because CFFI/LXST might need it at runtime on Python 3.12+ +RUN apk add --no-cache ffmpeg opusfile libffi su-exec py3-setuptools espeak-ng && \ + python -m pip install --no-cache-dir --upgrade "pip>=25.3" && \ + addgroup -g 1000 meshchat && adduser -u 1000 -G meshchat -S meshchat && \ + mkdir -p /config && chown meshchat:meshchat /config + +# Copy the virtual environment from the build stage +COPY --from=builder --chown=meshchat:meshchat /opt/venv /opt/venv + +# Set up environment +ENV PATH="/opt/venv/bin:$PATH" +ENV PYTHONUNBUFFERED=1 +ENV PYTHONDONTWRITEBYTECODE=1 + +# Run the app using the installed 'meshchat' entrypoint +CMD ["sh", "-c", "chown -R meshchat:meshchat /config && exec su-exec meshchat meshchat --host=0.0.0.0 --reticulum-config-dir=/config/.reticulum --storage-dir=/config/.meshchat --headless"] diff --git a/Dockerfile.arch-builder b/Dockerfile.arch-builder new file mode 100644 index 0000000..adaacf0 --- /dev/null +++ b/Dockerfile.arch-builder @@ -0,0 +1,39 @@ +FROM archlinux:latest + +# Install build dependencies +RUN pacman -Syu --noconfirm --needed \ + base-devel \ + git \ + sudo \ + nodejs \ + pnpm \ + python \ + python-poetry \ + opus \ + opusfile \ + portaudio \ + espeak-ng \ + nss \ + atk \ + at-spi2-core \ + libxcomposite \ + libxrandr \ + libxdamage \ + mesa \ + alsa-lib \ + libx11 + +# Create a non-root user for makepkg +RUN useradd -m build && \ + echo "build ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/build + +# Set up build directory +USER build +WORKDIR /home/build/project + +# Copy packaging files +COPY --chown=build:build packaging/arch /home/build/project/packaging/arch + +# Default command to build the package +CMD ["/bin/bash", "-c", "cd packaging/arch && makepkg -s --noconfirm"] + diff --git a/MANIFEST.in b/MANIFEST.in index 1957682..3d74903 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,12 @@ recursive-include meshchatx/public * -recursive-include meshchatx/src * +recursive-include meshchatx/src/backend * +include meshchatx/src/version.py +include meshchatx/src/__init__.py +include meshchatx/meshchat.py +include meshchatx/__init__.py + +exclude meshchatx/src/frontend +recursive-exclude meshchatx/src/frontend * +recursive-exclude * __pycache__ +recursive-exclude * *.py[co] diff --git a/README.md b/README.md index 29f39ca..2275320 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ To provide everything you need for Reticulum, LXMF, and LXST in one beautiful an - Mobile app (one can dream) - Reliable, secure, fast and easy to use. -Note on macOS: You will need to manually build or use containers since I do not have a macOS machine or runner. +Note on macOS: You will need to manually build or use containers since I do not have a macOS machine or runner. ## Quick Start (Docker - Recommended) @@ -192,41 +192,39 @@ MeshChatX can be configured via command-line arguments or environment variables. | `--storage-dir` | `MESHCHAT_STORAGE_DIR` | `./storage` | Data directory | | `--public-dir` | `MESHCHAT_PUBLIC_DIR` | - | Frontend files path | - ## Development We use [Task](https://taskfile.dev/) for automation. -| Task | Description | -| :---------------------- | :--------------------------------------------- | -| `task install` | Install all dependencies | -| `task run` | Run the application | -| `task dev` | Run the application in development mode | -| `task lint` | Run all linters (Python & Frontend) | -| `task lint-python` | Lint Python code only | -| `task lint-frontend` | Lint frontend code only | -| `task format` | Format all code (Python & Frontend) | -| `task format-python` | Format Python code only | -| `task format-frontend` | Format frontend code only | -| `task test` | Run all tests | -| `task test:cov` | Run tests with coverage reports | -| `task test-python` | Run Python tests only | -| `task test-frontend` | Run frontend tests only | -| `task build` | Build frontend and backend | -| `task build-frontend` | Build only the frontend | -| `task wheel` | Build Python wheel package | -| `task compile` | Compile Python code to check for syntax errors | -| `task build-docker` | Build Docker image using buildx | -| `task run-docker` | Run Docker container using docker-compose | -| `task build-appimage` | Build Linux AppImage | -| `task build-exe` | Build Windows portable executable | -| `task build-electron-linux` | Build Linux Electron app | -| `task build-electron-windows` | Build Windows Electron apps | -| `task android-prepare` | Prepare Android build | -| `task android-build` | Build Android APK | -| `task build-flatpak` | Build Flatpak package | -| `task clean` | Clean build artifacts and dependencies | - +| Task | Description | +| :---------------------------- | :--------------------------------------------- | +| `task install` | Install all dependencies | +| `task run` | Run the application | +| `task dev` | Run the application in development mode | +| `task lint` | Run all linters (Python & Frontend) | +| `task lint-python` | Lint Python code only | +| `task lint-frontend` | Lint frontend code only | +| `task format` | Format all code (Python & Frontend) | +| `task format-python` | Format Python code only | +| `task format-frontend` | Format frontend code only | +| `task test` | Run all tests | +| `task test:cov` | Run tests with coverage reports | +| `task test-python` | Run Python tests only | +| `task test-frontend` | Run frontend tests only | +| `task build` | Build frontend and backend | +| `task build-frontend` | Build only the frontend | +| `task wheel` | Build Python wheel package | +| `task compile` | Compile Python code to check for syntax errors | +| `task build-docker` | Build Docker image using buildx | +| `task run-docker` | Run Docker container using docker-compose | +| `task build-appimage` | Build Linux AppImage | +| `task build-exe` | Build Windows portable executable | +| `task build-electron-linux` | Build Linux Electron app | +| `task build-electron-windows` | Build Windows Electron apps | +| `task android-prepare` | Prepare Android build | +| `task android-build` | Build Android APK | +| `task build-flatpak` | Build Flatpak package | +| `task clean` | Clean build artifacts and dependencies | ## Security @@ -237,7 +235,7 @@ We use [Task](https://taskfile.dev/) for automation. - Updated dependencies and daily scanning (OSV) - Container image scanning (Trivy) - SBOM for dependency observability and tracking -- Extensive testing and fuzzing. +- Extensive testing and fuzzing. - Rootless docker images - Pinned actions and container images (supply chain security and deterministic builds) @@ -246,4 +244,3 @@ We use [Task](https://taskfile.dev/) for automation. - [Liam Cottle](https://github.com/liamcottle) - Original Reticulum MeshChat - [RFnexus](https://github.com/RFnexus) - [micron-parser-js](https://github.com/RFnexus/micron-parser-js) - [Marqvist](https://github.com/markqvist) - Reticulum, LXMF, LXST - diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..4a996ec --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,32 @@ +# Security Policy + +## Contact Information + +If you discover a security vulnerability or have concerns about the security of Reticulum MeshChatX, please contact the lead developer using the following methods in order of preference: + +1. **LXMF**: `7cc8d66b4f6a0e0e49d34af7f6077b5a` + +## Security Overview + +Reticulum MeshChatX is designed with a high degree of security in mind, leveraging multiple layers of protection and modern security practices. Detailed security enhancements are documented in the [CHANGELOG.md](CHANGELOG.md) and [README.md](README.md). + +### Core Security Features + +- **ASAR Integrity Validation**: Utilizes Electron 39 features to protect the application against tampering. +- **Backend Binary Verification**: Generates a SHA-256 manifest of the unpacked Python backend during build and verifies it on every startup. +- **Data-at-Rest Integrity Monitoring**: Snapshots the state of identities and database files on clean shutdown and warns if they were modified while the app was closed. +- **Redundant CSP Hardening**: Multi-layered Content Security Policy protection across the entire application stack: + 1. **Backend Server CSP**: Applied via security middleware to all HTTP responses. + 2. **Electron Session CSP**: Shell-level fallback CSP applied via `webRequest.onHeadersReceived`. + 3. **Loading Screen CSP**: Bootloader CSP defined in HTML meta tags. +- **Hardened Electron Environment**: Hardened security by disabling `runAsNode` and `nodeOptions` environment variables via Electron Fuses. +- **Rootless Docker Images**: Support for running in restricted environments with rootless container images. + +### Automated Security Measures + +The project employs continuous security monitoring and testing: + +- **Security Scanning**: Automated daily scans using OSV-Scanner and Trivy for container image vulnerabilities. +- **Pinned Actions**: All CI/CD workflows use pinned actions with full URLs to forked, vetted actions hosted on our Gitea instance (`git.quad4.io`) to prevent supply chain attacks. +- **Extensive Testing & Fuzzing**: Comprehensive backend benchmarking suite with high-precision timing, memory delta tracking, and extreme stress modes to ensure stability and prevent resource exhaustion. +- **Linting & Code Quality**: Strict linting rules and static analysis are enforced on every push. diff --git a/TODO.md b/TODO.md index c567502..ad51138 100644 --- a/TODO.md +++ b/TODO.md @@ -2,8 +2,5 @@ - [ ] Spam filter (based on keywords) - partially done - [ ] RNS Tunnel - tunnel regular internet services over RNS - [ ] RNS Filesync - P2P file sync over RNS -- [ ] Rootless docker images - [ ] SBOM action - -## Maybe -- [ ] TAK tool/integration (maybe) +- [ ] Sideband plugins support diff --git a/Taskfile.yml b/Taskfile.yml index dff6ba6..6f6ccee 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -63,8 +63,8 @@ tasks: lint-python: desc: Lint Python code using ruff cmds: - - poetry run ruff check . --exclude tests - - poetry run ruff format --check . --exclude tests + - poetry run ruff check . + - poetry run ruff format --check . lint-frontend: desc: Lint frontend code @@ -104,16 +104,60 @@ tasks: test-frontend: desc: Run frontend tests using vitest cmds: - - "{{.NPM}} run test" + - "{{.NPM}} run test -- --exclude tests/frontend/i18n.test.js" + + test-lang: + desc: Run language and localization tests + cmds: + - "{{.NPM}} run test tests/frontend/i18n.test.js" + - "poetry run pytest tests/backend/test_translator_handler.py" + + gen-locale-template: + desc: Generate a locales.json template with empty values from en.json + cmds: + - "{{.PYTHON}} scripts/generate_locale_template.py" test: desc: Run all tests - deps: [test-python, test-frontend] + deps: [test-python, test-frontend, test-lang] test:cov: desc: Run all tests with coverage reports deps: [test-python-cov, test-frontend] + check: + desc: Run format, lint and test + cmds: + - task: format + - task: lint + - task: test + + bench-backend: + desc: Run comprehensive backend benchmarks + cmds: + - poetry run python tests/backend/run_comprehensive_benchmarks.py + + bench-extreme: + desc: Run extreme backend stress benchmarks (Breaking Space Mode) + cmds: + - poetry run python tests/backend/run_comprehensive_benchmarks.py --extreme + + profile-memory: + desc: Run backend memory profiling tests + cmds: + - poetry run pytest tests/backend/test_memory_profiling.py + + test-integrity: + desc: Run backend and data integrity tests + cmds: + - poetry run pytest tests/backend/test_integrity.py tests/backend/test_backend_integrity.py + + bench: + desc: Run all backend benchmarks and memory profiling + cmds: + - task: bench-backend + - task: profile-memory + compile: desc: Compile Python code to check for syntax errors cmds: @@ -166,16 +210,18 @@ tasks: build-appimage: desc: Build Linux AppImage - deps: [build] + deps: [build-frontend] cmds: - "{{.NPM}} run electron-postinstall" + - "PLATFORM=linux {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --linux AppImage" build-exe: desc: Build Windows portable executable - deps: [build] + deps: [build-frontend] cmds: - "{{.NPM}} run electron-postinstall" + - "PLATFORM=win32 {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --win portable" build-electron-linux: @@ -184,18 +230,38 @@ tasks: cmds: - "{{.NPM}} run dist:linux" + build-rpm: + desc: Build Linux RPM package + deps: [build-frontend] + cmds: + - "{{.NPM}} run dist:rpm" + + build-flatpak: + desc: Build Linux Flatpak package + deps: [build-frontend] + cmds: + - "{{.NPM}} run dist:flatpak" + build-electron-windows: desc: Build Windows Electron apps (portable and installer) deps: [build-frontend] cmds: - "{{.NPM}} run dist:windows" + build-zip: + desc: Build Electron ZIP archive using Electron Forge + deps: [build-frontend] + cmds: + - "PLATFORM=linux {{.NPM}} run build-backend" + - "{{.NPM}} run dist:zip" + build-electron-all: desc: Build all Electron apps (Linux and Windows) deps: [build-frontend] cmds: - "{{.NPM}} run electron-postinstall" - - "{{.NPM}} run build-backend" + - "PLATFORM=linux {{.NPM}} run build-backend" + - "PLATFORM=win32 {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --linux AppImage deb --win portable nsis" dist: @@ -210,20 +276,37 @@ tasks: build-appimage-legacy: desc: Build Linux AppImage with legacy Electron version - deps: [build, electron-legacy] + deps: [build-frontend, electron-legacy] cmds: - "{{.NPM}} run electron-postinstall" - - "{{.NPM}} run dist -- --linux AppImage" + - "PLATFORM=linux {{.NPM}} run build-backend" + - "{{.NPM}} run dist -- --linux AppImage -c.extraMetadata.main=electron/main-legacy.js" - "./scripts/rename_legacy_artifacts.sh" build-exe-legacy: desc: Build Windows portable executable with legacy Electron version - deps: [build, electron-legacy] + deps: [build-frontend, electron-legacy] cmds: - "{{.NPM}} run electron-postinstall" - - "{{.NPM}} run dist -- --win portable" + - "PLATFORM=win32 {{.NPM}} run build-backend" + - "{{.NPM}} run dist -- --win portable -c.extraMetadata.main=electron/main-legacy.js" - "./scripts/rename_legacy_artifacts.sh" + forge-start: + desc: Run the application with Electron Forge + cmds: + - "{{.NPM}} run start" + + forge-package: + desc: Package the application with Electron Forge + cmds: + - "{{.NPM}} run package" + + forge-make: + desc: Generate distributables with Electron Forge + cmds: + - "{{.NPM}} run make" + clean: desc: Clean build artifacts and dependencies cmds: @@ -233,6 +316,7 @@ tasks: - rm -rf python-dist - rm -rf meshchatx/public - rm -rf build-dir + - rm -rf out - task: android-clean build-docker: @@ -257,6 +341,11 @@ tasks: cmds: - 'MESHCHAT_IMAGE="{{.DOCKER_IMAGE}}" {{.DOCKER_COMPOSE_CMD}} -f {{.DOCKER_COMPOSE_FILE}} up --remove-orphans --pull never reticulum-meshchatx' + run-docker-dev: + desc: Run Docker container in development mode using docker-compose.dev.yml + cmds: + - 'MESHCHAT_IMAGE="{{.DOCKER_IMAGE}}" {{.DOCKER_COMPOSE_CMD}} -f docker-compose.dev.yml up --build --remove-orphans reticulum-meshchatx' + docker-build-env: desc: Build the Docker image for containerized builds cmds: @@ -345,41 +434,3 @@ tasks: cmds: - cd "{{.ANDROID_DIR}}" && ./gradlew clean - rm -rf "{{.PYTHON_SRC_DIR}}/meshchatx" - - flatpak-check-sdk: - desc: Check if required Flatpak SDK is installed - cmds: - - | - if ! flatpak info org.freedesktop.Sdk//24.08 >/dev/null 2>&1; then - echo "Flatpak SDK 24.08 is not installed." - echo "Install it with: flatpak install org.freedesktop.Sdk//24.08" - exit 1 - fi - if ! flatpak info org.freedesktop.Platform//24.08 >/dev/null 2>&1; then - echo "Flatpak Platform runtime 24.08 is not installed." - echo "Install it with: flatpak install org.freedesktop.Platform//24.08" - exit 1 - fi - if ! flatpak info org.freedesktop.Sdk.Extension.node20//24.08 >/dev/null 2>&1; then - echo "Flatpak Node.js 20 extension is not installed." - echo "Install it with: flatpak install org.freedesktop.Sdk.Extension.node20//24.08" - exit 1 - fi - echo "Required Flatpak SDK, Platform runtime, and Node.js extension are installed." - - build-flatpak: - desc: Build Flatpak package - deps: [flatpak-check-sdk] - cmds: - - flatpak-builder --force-clean build-dir flatpak.json - - install-flatpak: - desc: Install Flatpak package locally - deps: [build-flatpak] - cmds: - - flatpak-builder --install --user --force-clean build-dir flatpak.json - - run-flatpak: - desc: Run Flatpak application - cmds: - - flatpak run com.sudoivan.reticulummeshchatx diff --git a/cx_setup.py b/cx_setup.py index 00fa221..e0160c7 100644 --- a/cx_setup.py +++ b/cx_setup.py @@ -1,3 +1,4 @@ +import os import sys from pathlib import Path @@ -8,6 +9,9 @@ from meshchatx.src.version import __version__ ROOT = Path(__file__).resolve().parent PUBLIC_DIR = ROOT / "meshchatx" / "public" +target_name = os.environ.get("CX_FREEZE_TARGET_NAME", "ReticulumMeshChatX") +build_exe_dir = os.environ.get("CX_FREEZE_BUILD_EXE", "build/exe") + include_files = [] if PUBLIC_DIR.exists() and PUBLIC_DIR.is_dir(): @@ -42,7 +46,7 @@ setup( Executable( script="meshchatx/meshchat.py", base=None, - target_name="ReticulumMeshChatX", + target_name=target_name, shortcut_name="ReticulumMeshChatX", shortcut_dir="ProgramMenuFolder", icon="logo/icon.ico", @@ -56,7 +60,7 @@ setup( "PIL", ], "optimize": 1, - "build_exe": "build/exe", + "build_exe": build_exe_dir, "replace_paths": [ ("*", ""), ], diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..b7e46ee --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,38 @@ +services: + reticulum-meshchatx: + build: + context: . + dockerfile: Dockerfile + container_name: reticulum-meshchatx + image: reticulum-meshchatx:local + restart: unless-stopped + # Permission handling is now automated in the Dockerfile via su-exec + # reticulum-meshchatx will run as user 'meshchat' (UID 1000) + security_opt: + - no-new-privileges:true + # Make the meshchat web interface accessible from the host on port 8000 + ports: + - 127.0.0.1:8000:8000 + volumes: + - ./meshchat-config:/config + # Uncomment if you have a USB device connected, such as an RNode + # devices: + # - /dev/ttyUSB0:/dev/ttyUSB0 + # + # Host network for autointerface: + # network_mode: host + +# LibreTranslate - optional + +# libretranslate: +# container_name: libretranslate +# image: libretranslate/libretranslate:latest +# ports: +# - 127.0.0.1:5000:5000 +# restart: unless-stopped +# healthcheck: +# test: ["CMD", "curl", "-f", "http://localhost:5000/health"] +# interval: 10s +# timeout: 4s +# retries: 4 +# start_period: 5s diff --git a/docker-compose.yml b/docker-compose.yml index 61e0674..0d9026a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ services: reticulum-meshchatx: container_name: reticulum-meshchatx - image: git.quad4.io/rns-things/meshchatx:latest + image: ${MESHCHAT_IMAGE:-git.quad4.io/rns-things/meshchatx:latest} restart: unless-stopped security_opt: - no-new-privileges:true diff --git a/docs/meshchat_on_docker.md b/docs/meshchat_on_docker.md deleted file mode 100644 index d82ddee..0000000 --- a/docs/meshchat_on_docker.md +++ /dev/null @@ -1,11 +0,0 @@ -# MeshChat on Docker - -A docker image is automatically built by GitHub actions, and can be downloaded from the GitHub container registry. - -``` -docker pull ghcr.io/liamcottle/reticulum-meshchat:latest -``` - -Additionally, an example [docker-compose.yml](../docker-compose.yml) is available. - -The example automatically generates a new reticulum config file in the `meshchat-config` volume. The MeshChat database is also stored in this volume. diff --git a/docs/meshchatx.md b/docs/meshchatx.md new file mode 100644 index 0000000..1c94887 --- /dev/null +++ b/docs/meshchatx.md @@ -0,0 +1,3 @@ +# Welcome to MeshChatX + +A fork of Reticulum Meshchat, with many more features, new UI/UX, better security and integrity. diff --git a/docs/meshchat_on_android_with_termux.md b/docs/meshchatx_on_android_with_termux.md similarity index 100% rename from docs/meshchat_on_android_with_termux.md rename to docs/meshchatx_on_android_with_termux.md diff --git a/docs/meshchat_on_raspberry_pi.md b/docs/meshchatx_on_raspberry_pi.md similarity index 100% rename from docs/meshchat_on_raspberry_pi.md rename to docs/meshchatx_on_raspberry_pi.md diff --git a/electron/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js b/electron/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js index 8369aad..5f8bd4a 100644 --- a/electron/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js +++ b/electron/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js @@ -1,44 +1,18907 @@ -(()=>{var Rb=Object.create;var ci=Object.defineProperty;var Mb=Object.getOwnPropertyDescriptor;var Bb=Object.getOwnPropertyNames;var Fb=Object.getPrototypeOf,Lb=Object.prototype.hasOwnProperty;var gu=r=>ci(r,"__esModule",{value:!0});var yu=r=>{if(typeof require!="undefined")return require(r);throw new Error('Dynamic require of "'+r+'" is not supported')};var C=(r,e)=>()=>(r&&(e=r(r=0)),e);var v=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Ae=(r,e)=>{gu(r);for(var t in e)ci(r,t,{get:e[t],enumerable:!0})},Nb=(r,e,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Bb(e))!Lb.call(r,i)&&i!=="default"&&ci(r,i,{get:()=>e[i],enumerable:!(t=Mb(e,i))||t.enumerable});return r},X=r=>Nb(gu(ci(r!=null?Rb(Fb(r)):{},"default",r&&r.__esModule&&"default"in r?{get:()=>r.default,enumerable:!0}:{value:r,enumerable:!0})),r);var h,l=C(()=>{h={platform:"",env:{},versions:{node:"14.17.6"}}});var $b,te,ze=C(()=>{l();$b=0,te={readFileSync:r=>self[r]||"",statSync:()=>({mtimeMs:$b++}),promises:{readFile:r=>Promise.resolve(self[r]||"")}}});var rs=v((eE,bu)=>{l();"use strict";var wu=class{constructor(e={}){if(!(e.maxSize&&e.maxSize>0))throw new TypeError("`maxSize` must be a number greater than 0");if(typeof e.maxAge=="number"&&e.maxAge===0)throw new TypeError("`maxAge` must be a number greater than 0");this.maxSize=e.maxSize,this.maxAge=e.maxAge||1/0,this.onEviction=e.onEviction,this.cache=new Map,this.oldCache=new Map,this._size=0}_emitEvictions(e){if(typeof this.onEviction=="function")for(let[t,i]of e)this.onEviction(t,i.value)}_deleteIfExpired(e,t){return typeof t.expiry=="number"&&t.expiry<=Date.now()?(typeof this.onEviction=="function"&&this.onEviction(e,t.value),this.delete(e)):!1}_getOrDeleteIfExpired(e,t){if(this._deleteIfExpired(e,t)===!1)return t.value}_getItemValue(e,t){return t.expiry?this._getOrDeleteIfExpired(e,t):t.value}_peek(e,t){let i=t.get(e);return this._getItemValue(e,i)}_set(e,t){this.cache.set(e,t),this._size++,this._size>=this.maxSize&&(this._size=0,this._emitEvictions(this.oldCache),this.oldCache=this.cache,this.cache=new Map)}_moveToRecent(e,t){this.oldCache.delete(e),this._set(e,t)}*_entriesAscending(){for(let e of this.oldCache){let[t,i]=e;this.cache.has(t)||this._deleteIfExpired(t,i)===!1&&(yield e)}for(let e of this.cache){let[t,i]=e;this._deleteIfExpired(t,i)===!1&&(yield e)}}get(e){if(this.cache.has(e)){let t=this.cache.get(e);return this._getItemValue(e,t)}if(this.oldCache.has(e)){let t=this.oldCache.get(e);if(this._deleteIfExpired(e,t)===!1)return this._moveToRecent(e,t),t.value}}set(e,t,{maxAge:i=this.maxAge===1/0?void 0:Date.now()+this.maxAge}={}){this.cache.has(e)?this.cache.set(e,{value:t,maxAge:i}):this._set(e,{value:t,expiry:i})}has(e){return this.cache.has(e)?!this._deleteIfExpired(e,this.cache.get(e)):this.oldCache.has(e)?!this._deleteIfExpired(e,this.oldCache.get(e)):!1}peek(e){if(this.cache.has(e))return this._peek(e,this.cache);if(this.oldCache.has(e))return this._peek(e,this.oldCache)}delete(e){let t=this.cache.delete(e);return t&&this._size--,this.oldCache.delete(e)||t}clear(){this.cache.clear(),this.oldCache.clear(),this._size=0}resize(e){if(!(e&&e>0))throw new TypeError("`maxSize` must be a number greater than 0");let t=[...this._entriesAscending()],i=t.length-e;i<0?(this.cache=new Map(t),this.oldCache=new Map,this._size=t.length):(i>0&&this._emitEvictions(t.slice(0,i)),this.oldCache=new Map(t.slice(i)),this.cache=new Map,this._size=0),this.maxSize=e}*keys(){for(let[e]of this)yield e}*values(){for(let[,e]of this)yield e}*[Symbol.iterator](){for(let e of this.cache){let[t,i]=e;this._deleteIfExpired(t,i)===!1&&(yield[t,i.value])}for(let e of this.oldCache){let[t,i]=e;this.cache.has(t)||this._deleteIfExpired(t,i)===!1&&(yield[t,i.value])}}*entriesDescending(){let e=[...this.cache];for(let t=e.length-1;t>=0;--t){let i=e[t],[n,a]=i;this._deleteIfExpired(n,a)===!1&&(yield[n,a.value])}e=[...this.oldCache];for(let t=e.length-1;t>=0;--t){let i=e[t],[n,a]=i;this.cache.has(n)||this._deleteIfExpired(n,a)===!1&&(yield[n,a.value])}}*entriesAscending(){for(let[e,t]of this._entriesAscending())yield[e,t.value]}get size(){if(!this._size)return this.oldCache.size;let e=0;for(let t of this.oldCache.keys())this.cache.has(t)||e++;return Math.min(this._size+e,this.maxSize)}};bu.exports=wu});var vu,xu=C(()=>{l();vu=r=>r&&r._hash});function pi(r){return vu(r,{ignoreUnknown:!0})}var ku=C(()=>{l();xu()});function Ke(r){if(r=`${r}`,r==="0")return"0";if(/^[+-]?(\d+|\d*\.\d+)(e[+-]?\d+)?(%|\w+)?$/.test(r))return r.replace(/^[+-]?/,t=>t==="-"?"":"-");let e=["var","calc","min","max","clamp"];for(let t of e)if(r.includes(`${t}(`))return`calc(${r} * -1)`}var di=C(()=>{l()});var Su,Cu=C(()=>{l();Su=["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","lineClamp","display","aspectRatio","size","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","captionSide","borderCollapse","borderSpacing","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","listStyleImage","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","hyphens","whitespace","textWrap","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","textDecorationStyle","textDecorationThickness","textUnderlineOffset","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","contain","content","forcedColorAdjust"]});function Au(r,e){return r===void 0?e:Array.isArray(r)?r:[...new Set(e.filter(i=>r!==!1&&r[i]!==!1).concat(Object.keys(r).filter(i=>r[i]!==!1)))]}var _u=C(()=>{l()});var Ou={};Ae(Ou,{default:()=>_e});var _e,hi=C(()=>{l();_e=new Proxy({},{get:()=>String})});function is(r,e,t){typeof h!="undefined"&&h.env.JEST_WORKER_ID||t&&Eu.has(t)||(t&&Eu.add(t),console.warn(""),e.forEach(i=>console.warn(r,"-",i)))}function ns(r){return _e.dim(r)}var Eu,F,Oe=C(()=>{l();hi();Eu=new Set;F={info(r,e){is(_e.bold(_e.cyan("info")),...Array.isArray(r)?[r]:[e,r])},warn(r,e){["content-problems"].includes(r)||is(_e.bold(_e.yellow("warn")),...Array.isArray(r)?[r]:[e,r])},risk(r,e){is(_e.bold(_e.magenta("risk")),...Array.isArray(r)?[r]:[e,r])}}});var as={};Ae(as,{default:()=>ss});function lr({version:r,from:e,to:t}){F.warn(`${e}-color-renamed`,[`As of Tailwind CSS ${r}, \`${e}\` has been renamed to \`${t}\`.`,"Update your configuration file to silence this warning."])}var ss,mi=C(()=>{l();Oe();ss={inherit:"inherit",current:"currentColor",transparent:"transparent",black:"#000",white:"#fff",slate:{50:"#f8fafc",100:"#f1f5f9",200:"#e2e8f0",300:"#cbd5e1",400:"#94a3b8",500:"#64748b",600:"#475569",700:"#334155",800:"#1e293b",900:"#0f172a",950:"#020617"},gray:{50:"#f9fafb",100:"#f3f4f6",200:"#e5e7eb",300:"#d1d5db",400:"#9ca3af",500:"#6b7280",600:"#4b5563",700:"#374151",800:"#1f2937",900:"#111827",950:"#030712"},zinc:{50:"#fafafa",100:"#f4f4f5",200:"#e4e4e7",300:"#d4d4d8",400:"#a1a1aa",500:"#71717a",600:"#52525b",700:"#3f3f46",800:"#27272a",900:"#18181b",950:"#09090b"},neutral:{50:"#fafafa",100:"#f5f5f5",200:"#e5e5e5",300:"#d4d4d4",400:"#a3a3a3",500:"#737373",600:"#525252",700:"#404040",800:"#262626",900:"#171717",950:"#0a0a0a"},stone:{50:"#fafaf9",100:"#f5f5f4",200:"#e7e5e4",300:"#d6d3d1",400:"#a8a29e",500:"#78716c",600:"#57534e",700:"#44403c",800:"#292524",900:"#1c1917",950:"#0c0a09"},red:{50:"#fef2f2",100:"#fee2e2",200:"#fecaca",300:"#fca5a5",400:"#f87171",500:"#ef4444",600:"#dc2626",700:"#b91c1c",800:"#991b1b",900:"#7f1d1d",950:"#450a0a"},orange:{50:"#fff7ed",100:"#ffedd5",200:"#fed7aa",300:"#fdba74",400:"#fb923c",500:"#f97316",600:"#ea580c",700:"#c2410c",800:"#9a3412",900:"#7c2d12",950:"#431407"},amber:{50:"#fffbeb",100:"#fef3c7",200:"#fde68a",300:"#fcd34d",400:"#fbbf24",500:"#f59e0b",600:"#d97706",700:"#b45309",800:"#92400e",900:"#78350f",950:"#451a03"},yellow:{50:"#fefce8",100:"#fef9c3",200:"#fef08a",300:"#fde047",400:"#facc15",500:"#eab308",600:"#ca8a04",700:"#a16207",800:"#854d0e",900:"#713f12",950:"#422006"},lime:{50:"#f7fee7",100:"#ecfccb",200:"#d9f99d",300:"#bef264",400:"#a3e635",500:"#84cc16",600:"#65a30d",700:"#4d7c0f",800:"#3f6212",900:"#365314",950:"#1a2e05"},green:{50:"#f0fdf4",100:"#dcfce7",200:"#bbf7d0",300:"#86efac",400:"#4ade80",500:"#22c55e",600:"#16a34a",700:"#15803d",800:"#166534",900:"#14532d",950:"#052e16"},emerald:{50:"#ecfdf5",100:"#d1fae5",200:"#a7f3d0",300:"#6ee7b7",400:"#34d399",500:"#10b981",600:"#059669",700:"#047857",800:"#065f46",900:"#064e3b",950:"#022c22"},teal:{50:"#f0fdfa",100:"#ccfbf1",200:"#99f6e4",300:"#5eead4",400:"#2dd4bf",500:"#14b8a6",600:"#0d9488",700:"#0f766e",800:"#115e59",900:"#134e4a",950:"#042f2e"},cyan:{50:"#ecfeff",100:"#cffafe",200:"#a5f3fc",300:"#67e8f9",400:"#22d3ee",500:"#06b6d4",600:"#0891b2",700:"#0e7490",800:"#155e75",900:"#164e63",950:"#083344"},sky:{50:"#f0f9ff",100:"#e0f2fe",200:"#bae6fd",300:"#7dd3fc",400:"#38bdf8",500:"#0ea5e9",600:"#0284c7",700:"#0369a1",800:"#075985",900:"#0c4a6e",950:"#082f49"},blue:{50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",300:"#93c5fd",400:"#60a5fa",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af",900:"#1e3a8a",950:"#172554"},indigo:{50:"#eef2ff",100:"#e0e7ff",200:"#c7d2fe",300:"#a5b4fc",400:"#818cf8",500:"#6366f1",600:"#4f46e5",700:"#4338ca",800:"#3730a3",900:"#312e81",950:"#1e1b4b"},violet:{50:"#f5f3ff",100:"#ede9fe",200:"#ddd6fe",300:"#c4b5fd",400:"#a78bfa",500:"#8b5cf6",600:"#7c3aed",700:"#6d28d9",800:"#5b21b6",900:"#4c1d95",950:"#2e1065"},purple:{50:"#faf5ff",100:"#f3e8ff",200:"#e9d5ff",300:"#d8b4fe",400:"#c084fc",500:"#a855f7",600:"#9333ea",700:"#7e22ce",800:"#6b21a8",900:"#581c87",950:"#3b0764"},fuchsia:{50:"#fdf4ff",100:"#fae8ff",200:"#f5d0fe",300:"#f0abfc",400:"#e879f9",500:"#d946ef",600:"#c026d3",700:"#a21caf",800:"#86198f",900:"#701a75",950:"#4a044e"},pink:{50:"#fdf2f8",100:"#fce7f3",200:"#fbcfe8",300:"#f9a8d4",400:"#f472b6",500:"#ec4899",600:"#db2777",700:"#be185d",800:"#9d174d",900:"#831843",950:"#500724"},rose:{50:"#fff1f2",100:"#ffe4e6",200:"#fecdd3",300:"#fda4af",400:"#fb7185",500:"#f43f5e",600:"#e11d48",700:"#be123c",800:"#9f1239",900:"#881337",950:"#4c0519"},get lightBlue(){return lr({version:"v2.2",from:"lightBlue",to:"sky"}),this.sky},get warmGray(){return lr({version:"v3.0",from:"warmGray",to:"stone"}),this.stone},get trueGray(){return lr({version:"v3.0",from:"trueGray",to:"neutral"}),this.neutral},get coolGray(){return lr({version:"v3.0",from:"coolGray",to:"gray"}),this.gray},get blueGray(){return lr({version:"v3.0",from:"blueGray",to:"slate"}),this.slate}}});function os(r,...e){for(let t of e){for(let i in t)r?.hasOwnProperty?.(i)||(r[i]=t[i]);for(let i of Object.getOwnPropertySymbols(t))r?.hasOwnProperty?.(i)||(r[i]=t[i])}return r}var Tu=C(()=>{l()});function Ze(r){if(Array.isArray(r))return r;let e=r.split("[").length-1,t=r.split("]").length-1;if(e!==t)throw new Error(`Path is invalid. Has unbalanced brackets: ${r}`);return r.split(/\.(?![^\[]*\])|[\[\]]/g).filter(Boolean)}var gi=C(()=>{l()});function K(r,e){return yi.future.includes(e)?r.future==="all"||(r?.future?.[e]??Pu[e]??!1):yi.experimental.includes(e)?r.experimental==="all"||(r?.experimental?.[e]??Pu[e]??!1):!1}function Du(r){return r.experimental==="all"?yi.experimental:Object.keys(r?.experimental??{}).filter(e=>yi.experimental.includes(e)&&r.experimental[e])}function Iu(r){if(h.env.JEST_WORKER_ID===void 0&&Du(r).length>0){let e=Du(r).map(t=>_e.yellow(t)).join(", ");F.warn("experimental-flags-enabled",[`You have enabled experimental features: ${e}`,"Experimental features in Tailwind CSS are not covered by semver, may introduce breaking changes, and can change at any time."])}}var Pu,yi,je=C(()=>{l();hi();Oe();Pu={optimizeUniversalDefaults:!1,generalizedModifiers:!0,disableColorOpacityUtilitiesByDefault:!1,relativeContentPathsByDefault:!1},yi={future:["hoverOnlyWhenSupported","respectDefaultRingColorOpacity","disableColorOpacityUtilitiesByDefault","relativeContentPathsByDefault"],experimental:["optimizeUniversalDefaults","generalizedModifiers"]}});function qu(r){(()=>{if(r.purge||!r.content||!Array.isArray(r.content)&&!(typeof r.content=="object"&&r.content!==null))return!1;if(Array.isArray(r.content))return r.content.every(t=>typeof t=="string"?!0:!(typeof t?.raw!="string"||t?.extension&&typeof t?.extension!="string"));if(typeof r.content=="object"&&r.content!==null){if(Object.keys(r.content).some(t=>!["files","relative","extract","transform"].includes(t)))return!1;if(Array.isArray(r.content.files)){if(!r.content.files.every(t=>typeof t=="string"?!0:!(typeof t?.raw!="string"||t?.extension&&typeof t?.extension!="string")))return!1;if(typeof r.content.extract=="object"){for(let t of Object.values(r.content.extract))if(typeof t!="function")return!1}else if(!(r.content.extract===void 0||typeof r.content.extract=="function"))return!1;if(typeof r.content.transform=="object"){for(let t of Object.values(r.content.transform))if(typeof t!="function")return!1}else if(!(r.content.transform===void 0||typeof r.content.transform=="function"))return!1;if(typeof r.content.relative!="boolean"&&typeof r.content.relative!="undefined")return!1}return!0}return!1})()||F.warn("purge-deprecation",["The `purge`/`content` options have changed in Tailwind CSS v3.0.","Update your configuration file to eliminate this warning.","https://tailwindcss.com/docs/upgrade-guide#configure-content-sources"]),r.safelist=(()=>{let{content:t,purge:i,safelist:n}=r;return Array.isArray(n)?n:Array.isArray(t?.safelist)?t.safelist:Array.isArray(i?.safelist)?i.safelist:Array.isArray(i?.options?.safelist)?i.options.safelist:[]})(),r.blocklist=(()=>{let{blocklist:t}=r;if(Array.isArray(t)){if(t.every(i=>typeof i=="string"))return t;F.warn("blocklist-invalid",["The `blocklist` option must be an array of strings.","https://tailwindcss.com/docs/content-configuration#discarding-classes"])}return[]})(),typeof r.prefix=="function"?(F.warn("prefix-function",["As of Tailwind CSS v3.0, `prefix` cannot be a function.","Update `prefix` in your configuration to be a string to eliminate this warning.","https://tailwindcss.com/docs/upgrade-guide#prefix-cannot-be-a-function"]),r.prefix=""):r.prefix=r.prefix??"",r.content={relative:(()=>{let{content:t}=r;return t?.relative?t.relative:K(r,"relativeContentPathsByDefault")})(),files:(()=>{let{content:t,purge:i}=r;return Array.isArray(i)?i:Array.isArray(i?.content)?i.content:Array.isArray(t)?t:Array.isArray(t?.content)?t.content:Array.isArray(t?.files)?t.files:[]})(),extract:(()=>{let t=(()=>r.purge?.extract?r.purge.extract:r.content?.extract?r.content.extract:r.purge?.extract?.DEFAULT?r.purge.extract.DEFAULT:r.content?.extract?.DEFAULT?r.content.extract.DEFAULT:r.purge?.options?.extractors?r.purge.options.extractors:r.content?.options?.extractors?r.content.options.extractors:{})(),i={},n=(()=>{if(r.purge?.options?.defaultExtractor)return r.purge.options.defaultExtractor;if(r.content?.options?.defaultExtractor)return r.content.options.defaultExtractor})();if(n!==void 0&&(i.DEFAULT=n),typeof t=="function")i.DEFAULT=t;else if(Array.isArray(t))for(let{extensions:a,extractor:s}of t??[])for(let o of a)i[o]=s;else typeof t=="object"&&t!==null&&Object.assign(i,t);return i})(),transform:(()=>{let t=(()=>r.purge?.transform?r.purge.transform:r.content?.transform?r.content.transform:r.purge?.transform?.DEFAULT?r.purge.transform.DEFAULT:r.content?.transform?.DEFAULT?r.content.transform.DEFAULT:{})(),i={};return typeof t=="function"&&(i.DEFAULT=t),typeof t=="object"&&t!==null&&Object.assign(i,t),i})()};for(let t of r.content.files)if(typeof t=="string"&&/{([^,]*?)}/g.test(t)){F.warn("invalid-glob-braces",[`The glob pattern ${ns(t)} in your Tailwind CSS configuration is invalid.`,`Update it to ${ns(t.replace(/{([^,]*?)}/g,"$1"))} to silence this warning.`]);break}return r}var Ru=C(()=>{l();je();Oe()});function ie(r){if(Object.prototype.toString.call(r)!=="[object Object]")return!1;let e=Object.getPrototypeOf(r);return e===null||Object.getPrototypeOf(e)===null}var At=C(()=>{l()});function et(r){return Array.isArray(r)?r.map(e=>et(e)):typeof r=="object"&&r!==null?Object.fromEntries(Object.entries(r).map(([e,t])=>[e,et(t)])):r}var wi=C(()=>{l()});function wt(r){return r.replace(/\\,/g,"\\2c ")}var bi=C(()=>{l()});var ls,Mu=C(()=>{l();ls={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});function ur(r,{loose:e=!1}={}){if(typeof r!="string")return null;if(r=r.trim(),r==="transparent")return{mode:"rgb",color:["0","0","0"],alpha:"0"};if(r in ls)return{mode:"rgb",color:ls[r].map(a=>a.toString())};let t=r.replace(jb,(a,s,o,u,c)=>["#",s,s,o,o,u,u,c?c+c:""].join("")).match(zb);if(t!==null)return{mode:"rgb",color:[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)].map(a=>a.toString()),alpha:t[4]?(parseInt(t[4],16)/255).toString():void 0};let i=r.match(Vb)??r.match(Ub);if(i===null)return null;let n=[i[2],i[3],i[4]].filter(Boolean).map(a=>a.toString());return n.length===2&&n[0].startsWith("var(")?{mode:i[1],color:[n[0]],alpha:n[1]}:!e&&n.length!==3||n.length<3&&!n.some(a=>/^var\(.*?\)$/.test(a))?null:{mode:i[1],color:n,alpha:i[5]?.toString?.()}}function us({mode:r,color:e,alpha:t}){let i=t!==void 0;return r==="rgba"||r==="hsla"?`${r}(${e.join(", ")}${i?`, ${t}`:""})`:`${r}(${e.join(" ")}${i?` / ${t}`:""})`}var zb,jb,tt,vi,Bu,rt,Vb,Ub,fs=C(()=>{l();Mu();zb=/^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i,jb=/^#([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i,tt=/(?:\d+|\d*\.\d+)%?/,vi=/(?:\s*,\s*|\s+)/,Bu=/\s*[,/]\s*/,rt=/var\(--(?:[^ )]*?)(?:,(?:[^ )]*?|var\(--[^ )]*?\)))?\)/,Vb=new RegExp(`^(rgba?)\\(\\s*(${tt.source}|${rt.source})(?:${vi.source}(${tt.source}|${rt.source}))?(?:${vi.source}(${tt.source}|${rt.source}))?(?:${Bu.source}(${tt.source}|${rt.source}))?\\s*\\)$`),Ub=new RegExp(`^(hsla?)\\(\\s*((?:${tt.source})(?:deg|rad|grad|turn)?|${rt.source})(?:${vi.source}(${tt.source}|${rt.source}))?(?:${vi.source}(${tt.source}|${rt.source}))?(?:${Bu.source}(${tt.source}|${rt.source}))?\\s*\\)$`)});function Ie(r,e,t){if(typeof r=="function")return r({opacityValue:e});let i=ur(r,{loose:!0});return i===null?t:us({...i,alpha:e})}function se({color:r,property:e,variable:t}){let i=[].concat(e);if(typeof r=="function")return{[t]:"1",...Object.fromEntries(i.map(a=>[a,r({opacityVariable:t,opacityValue:`var(${t})`})]))};let n=ur(r);return n===null?Object.fromEntries(i.map(a=>[a,r])):n.alpha!==void 0?Object.fromEntries(i.map(a=>[a,r])):{[t]:"1",...Object.fromEntries(i.map(a=>[a,us({...n,alpha:`var(${t})`})]))}}var fr=C(()=>{l();fs()});function ae(r,e){let t=[],i=[],n=0,a=!1;for(let s=0;s{l()});function xi(r){return ae(r,",").map(t=>{let i=t.trim(),n={raw:i},a=i.split(Gb),s=new Set;for(let o of a)Fu.lastIndex=0,!s.has("KEYWORD")&&Wb.has(o)?(n.keyword=o,s.add("KEYWORD")):Fu.test(o)?s.has("X")?s.has("Y")?s.has("BLUR")?s.has("SPREAD")||(n.spread=o,s.add("SPREAD")):(n.blur=o,s.add("BLUR")):(n.y=o,s.add("Y")):(n.x=o,s.add("X")):n.color?(n.unknown||(n.unknown=[]),n.unknown.push(o)):n.color=o;return n.valid=n.x!==void 0&&n.y!==void 0,n})}function Lu(r){return r.map(e=>e.valid?[e.keyword,e.x,e.y,e.blur,e.spread,e.color].filter(Boolean).join(" "):e.raw).join(", ")}var Wb,Gb,Fu,cs=C(()=>{l();_t();Wb=new Set(["inset","inherit","initial","revert","unset"]),Gb=/\ +(?![^(]*\))/g,Fu=/^-?(\d+|\.\d+)(.*?)$/g});function ps(r){return Hb.some(e=>new RegExp(`^${e}\\(.*\\)`).test(r))}function L(r,e=null,t=!0){let i=e&&Yb.has(e.property);return r.startsWith("--")&&!i?`var(${r})`:r.includes("url(")?r.split(/(url\(.*?\))/g).filter(Boolean).map(n=>/^url\(.*?\)$/.test(n)?n:L(n,e,!1)).join(""):(r=r.replace(/([^\\])_+/g,(n,a)=>a+" ".repeat(n.length-1)).replace(/^_/g," ").replace(/\\_/g,"_"),t&&(r=r.trim()),r=Qb(r),r)}function Qb(r){let e=["theme"],t=["min-content","max-content","fit-content","safe-area-inset-top","safe-area-inset-right","safe-area-inset-bottom","safe-area-inset-left","titlebar-area-x","titlebar-area-y","titlebar-area-width","titlebar-area-height","keyboard-inset-top","keyboard-inset-right","keyboard-inset-bottom","keyboard-inset-left","keyboard-inset-width","keyboard-inset-height","radial-gradient","linear-gradient","conic-gradient","repeating-radial-gradient","repeating-linear-gradient","repeating-conic-gradient"];return r.replace(/(calc|min|max|clamp)\(.+\)/g,i=>{let n="";function a(){let s=n.trimEnd();return s[s.length-1]}for(let s=0;si[s+p]===d)},u=function(f){let d=1/0;for(let m of f){let b=i.indexOf(m,s);b!==-1&&bo(f))){let f=t.find(d=>o(d));n+=f,s+=f.length-1}else e.some(f=>o(f))?n+=u([")"]):o("[")?n+=u(["]"]):["+","-","*","/"].includes(c)&&!["(","+","-","*","/",","].includes(a())?n+=` ${c} `:n+=c}return n.replace(/\s+/g," ")})}function ds(r){return r.startsWith("url(")}function hs(r){return!isNaN(Number(r))||ps(r)}function cr(r){return r.endsWith("%")&&hs(r.slice(0,-1))||ps(r)}function pr(r){return r==="0"||new RegExp(`^[+-]?[0-9]*.?[0-9]+(?:[eE][+-]?[0-9]+)?${Xb}$`).test(r)||ps(r)}function Nu(r){return Kb.has(r)}function $u(r){let e=xi(L(r));for(let t of e)if(!t.valid)return!1;return!0}function zu(r){let e=0;return ae(r,"_").every(i=>(i=L(i),i.startsWith("var(")?!0:ur(i,{loose:!0})!==null?(e++,!0):!1))?e>0:!1}function ju(r){let e=0;return ae(r,",").every(i=>(i=L(i),i.startsWith("var(")?!0:ds(i)||e0(i)||["element(","image(","cross-fade(","image-set("].some(n=>i.startsWith(n))?(e++,!0):!1))?e>0:!1}function e0(r){r=L(r);for(let e of Zb)if(r.startsWith(`${e}(`))return!0;return!1}function Vu(r){let e=0;return ae(r,"_").every(i=>(i=L(i),i.startsWith("var(")?!0:t0.has(i)||pr(i)||cr(i)?(e++,!0):!1))?e>0:!1}function Uu(r){let e=0;return ae(r,",").every(i=>(i=L(i),i.startsWith("var(")?!0:i.includes(" ")&&!/(['"])([^"']+)\1/g.test(i)||/^\d/g.test(i)?!1:(e++,!0)))?e>0:!1}function Wu(r){return r0.has(r)}function Gu(r){return i0.has(r)}function Hu(r){return n0.has(r)}var Hb,Yb,Jb,Xb,Kb,Zb,t0,r0,i0,n0,dr=C(()=>{l();fs();cs();_t();Hb=["min","max","clamp","calc"];Yb=new Set(["scroll-timeline-name","timeline-scope","view-timeline-name","font-palette","scroll-timeline","animation-timeline","view-timeline"]);Jb=["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"],Xb=`(?:${Jb.join("|")})`;Kb=new Set(["thin","medium","thick"]);Zb=new Set(["conic-gradient","linear-gradient","radial-gradient","repeating-conic-gradient","repeating-linear-gradient","repeating-radial-gradient"]);t0=new Set(["center","top","right","bottom","left"]);r0=new Set(["serif","sans-serif","monospace","cursive","fantasy","system-ui","ui-serif","ui-sans-serif","ui-monospace","ui-rounded","math","emoji","fangsong"]);i0=new Set(["xx-small","x-small","small","medium","large","x-large","xx-large","xxx-large"]);n0=new Set(["larger","smaller"])});function Yu(r){let e=["cover","contain"];return ae(r,",").every(t=>{let i=ae(t,"_").filter(Boolean);return i.length===1&&e.includes(i[0])?!0:i.length!==1&&i.length!==2?!1:i.every(n=>pr(n)||cr(n)||n==="auto")})}var Qu=C(()=>{l();dr();_t()});function Ju(r,e){r.walkClasses(t=>{t.value=e(t.value),t.raws&&t.raws.value&&(t.raws.value=wt(t.raws.value))})}function Xu(r,e){if(!it(r))return;let t=r.slice(1,-1);if(!!e(t))return L(t)}function s0(r,e={},t){let i=e[r];if(i!==void 0)return Ke(i);if(it(r)){let n=Xu(r,t);return n===void 0?void 0:Ke(n)}}function ki(r,e={},{validate:t=()=>!0}={}){let i=e.values?.[r];return i!==void 0?i:e.supportsNegativeValues&&r.startsWith("-")?s0(r.slice(1),e.values,t):Xu(r,t)}function it(r){return r.startsWith("[")&&r.endsWith("]")}function Ku(r){let e=r.lastIndexOf("/"),t=r.lastIndexOf("[",e),i=r.indexOf("]",e);return r[e-1]==="]"||r[e+1]==="["||t!==-1&&i!==-1&&t")){let e=r;return({opacityValue:t=1})=>e.replace("",t)}return r}function Zu(r){return L(r.slice(1,-1))}function a0(r,e={},{tailwindConfig:t={}}={}){if(e.values?.[r]!==void 0)return Ot(e.values?.[r]);let[i,n]=Ku(r);if(n!==void 0){let a=e.values?.[i]??(it(i)?i.slice(1,-1):void 0);return a===void 0?void 0:(a=Ot(a),it(n)?Ie(a,Zu(n)):t.theme?.opacity?.[n]===void 0?void 0:Ie(a,t.theme.opacity[n]))}return ki(r,e,{validate:zu})}function o0(r,e={}){return e.values?.[r]}function me(r){return(e,t)=>ki(e,t,{validate:r})}function l0(r,e){let t=r.indexOf(e);return t===-1?[void 0,r]:[r.slice(0,t),r.slice(t+1)]}function gs(r,e,t,i){if(t.values&&e in t.values)for(let{type:a}of r??[]){let s=ms[a](e,t,{tailwindConfig:i});if(s!==void 0)return[s,a,null]}if(it(e)){let a=e.slice(1,-1),[s,o]=l0(a,":");if(!/^[\w-_]+$/g.test(s))o=a;else if(s!==void 0&&!ef.includes(s))return[];if(o.length>0&&ef.includes(s))return[ki(`[${o}]`,t),s,null]}let n=ys(r,e,t,i);for(let a of n)return a;return[]}function*ys(r,e,t,i){let n=K(i,"generalizedModifiers"),[a,s]=Ku(e);if(n&&t.modifiers!=null&&(t.modifiers==="any"||typeof t.modifiers=="object"&&(s&&it(s)||s in t.modifiers))||(a=e,s=void 0),s!==void 0&&a===""&&(a="DEFAULT"),s!==void 0&&typeof t.modifiers=="object"){let u=t.modifiers?.[s]??null;u!==null?s=u:it(s)&&(s=Zu(s))}for(let{type:u}of r??[]){let c=ms[u](a,t,{tailwindConfig:i});c!==void 0&&(yield[c,u,s??null])}}var ms,ef,hr=C(()=>{l();bi();fr();dr();di();Qu();je();ms={any:ki,color:a0,url:me(ds),image:me(ju),length:me(pr),percentage:me(cr),position:me(Vu),lookup:o0,"generic-name":me(Wu),"family-name":me(Uu),number:me(hs),"line-width":me(Nu),"absolute-size":me(Gu),"relative-size":me(Hu),shadow:me($u),size:me(Yu)},ef=Object.keys(ms)});function N(r){return typeof r=="function"?r({}):r}var ws=C(()=>{l()});function Et(r){return typeof r=="function"}function mr(r,...e){let t=e.pop();for(let i of e)for(let n in i){let a=t(r[n],i[n]);a===void 0?ie(r[n])&&ie(i[n])?r[n]=mr({},r[n],i[n],t):r[n]=i[n]:r[n]=a}return r}function u0(r,...e){return Et(r)?r(...e):r}function f0(r){return r.reduce((e,{extend:t})=>mr(e,t,(i,n)=>i===void 0?[n]:Array.isArray(i)?[n,...i]:[n,i]),{})}function c0(r){return{...r.reduce((e,t)=>os(e,t),{}),extend:f0(r)}}function tf(r,e){if(Array.isArray(r)&&ie(r[0]))return r.concat(e);if(Array.isArray(e)&&ie(e[0])&&ie(r))return[r,...e];if(Array.isArray(e))return e}function p0({extend:r,...e}){return mr(e,r,(t,i)=>!Et(t)&&!i.some(Et)?mr({},t,...i,tf):(n,a)=>mr({},...[t,...i].map(s=>u0(s,n,a)),tf))}function*d0(r){let e=Ze(r);if(e.length===0||(yield e,Array.isArray(r)))return;let t=/^(.*?)\s*\/\s*([^/]+)$/,i=r.match(t);if(i!==null){let[,n,a]=i,s=Ze(n);s.alpha=a,yield s}}function h0(r){let e=(t,i)=>{for(let n of d0(t)){let a=0,s=r;for(;s!=null&&a(t[i]=Et(r[i])?r[i](e,bs):r[i],t),{})}function rf(r){let e=[];return r.forEach(t=>{e=[...e,t];let i=t?.plugins??[];i.length!==0&&i.forEach(n=>{n.__isOptionsFunction&&(n=n()),e=[...e,...rf([n?.config??{}])]})}),e}function m0(r){return[...r].reduceRight((t,i)=>Et(i)?i({corePlugins:t}):Au(i,t),Su)}function g0(r){return[...r].reduceRight((t,i)=>[...t,...i],[])}function vs(r){let e=[...rf(r),{prefix:"",important:!1,separator:":"}];return qu(os({theme:h0(p0(c0(e.map(t=>t?.theme??{})))),corePlugins:m0(e.map(t=>t.corePlugins)),plugins:g0(r.map(t=>t?.plugins??[]))},...e))}var bs,nf=C(()=>{l();di();Cu();_u();mi();Tu();gi();Ru();At();wi();hr();fr();ws();bs={colors:ss,negative(r){return Object.keys(r).filter(e=>r[e]!=="0").reduce((e,t)=>{let i=Ke(r[t]);return i!==void 0&&(e[`-${t}`]=i),e},{})},breakpoints(r){return Object.keys(r).filter(e=>typeof r[e]=="string").reduce((e,t)=>({...e,[`screen-${t}`]:r[t]}),{})}}});var Si=v((i3,sf)=>{l();sf.exports={content:[],presets:[],darkMode:"media",theme:{accentColor:({theme:r})=>({...r("colors"),auto:"auto"}),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"},backdropBlur:({theme:r})=>r("blur"),backdropBrightness:({theme:r})=>r("brightness"),backdropContrast:({theme:r})=>r("contrast"),backdropGrayscale:({theme:r})=>r("grayscale"),backdropHueRotate:({theme:r})=>r("hueRotate"),backdropInvert:({theme:r})=>r("invert"),backdropOpacity:({theme:r})=>r("opacity"),backdropSaturate:({theme:r})=>r("saturate"),backdropSepia:({theme:r})=>r("sepia"),backgroundColor:({theme:r})=>r("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:r})=>r("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:"0",sm:"4px",DEFAULT:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"40px","3xl":"64px"},borderColor:({theme:r})=>({...r("colors"),DEFAULT:r("colors.gray.200","currentColor")}),borderOpacity:({theme:r})=>r("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:r})=>({...r("spacing")}),borderWidth:{DEFAULT:"1px",0:"0px",2:"2px",4:"4px",8:"8px"},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:r})=>r("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"},caretColor:({theme:r})=>r("colors"),colors:({colors:r})=>({inherit:r.inherit,current:r.current,transparent:r.transparent,black:r.black,white:r.white,slate:r.slate,gray:r.gray,zinc:r.zinc,neutral:r.neutral,stone:r.stone,red:r.red,orange:r.orange,amber:r.amber,yellow:r.yellow,lime:r.lime,green:r.green,emerald:r.emerald,teal:r.teal,cyan:r.cyan,sky:r.sky,blue:r.blue,indigo:r.indigo,violet:r.violet,purple:r.purple,fuchsia:r.fuchsia,pink:r.pink,rose:r.rose}),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"},container:{},content:{none:"none"},contrast:{0:"0",50:".5",75:".75",100:"1",125:"1.25",150:"1.5",200:"2"},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:r})=>r("borderColor"),divideOpacity:({theme:r})=>r("borderOpacity"),divideWidth:({theme:r})=>r("borderWidth"),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:r})=>({none:"none",...r("colors")}),flex:{1:"1 1 0%",auto:"1 1 auto",initial:"0 1 auto",none:"none"},flexBasis:({theme:r})=>({auto:"auto",...r("spacing"),"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%"}),flexGrow:{0:"0",DEFAULT:"1"},flexShrink:{0:"0",DEFAULT:"1"},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:r})=>r("spacing"),gradientColorStops:({theme:r})=>r("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%"},grayscale:{0:"0",DEFAULT:"100%"},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"},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"},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"},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"},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))"},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))"},height:({theme:r})=>({auto:"auto",...r("spacing"),"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"}),hueRotate:{0:"0deg",15:"15deg",30:"30deg",60:"60deg",90:"90deg",180:"180deg"},inset:({theme:r})=>({auto:"auto",...r("spacing"),"1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%",full:"100%"}),invert:{0:"0",DEFAULT:"100%"},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:r})=>({auto:"auto",...r("spacing")}),lineClamp:{1:"1",2:"2",3:"3",4:"4",5:"5",6:"6"},maxHeight:({theme:r})=>({...r("spacing"),none:"none",full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content"}),maxWidth:({theme:r,breakpoints:e})=>({...r("spacing"),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(r("screens"))}),minHeight:({theme:r})=>({...r("spacing"),full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content"}),minWidth:({theme:r})=>({...r("spacing"),full:"100%",min:"min-content",max:"max-content",fit:"fit-content"}),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"},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"},outlineColor:({theme:r})=>r("colors"),outlineOffset:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},outlineWidth:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},padding:({theme:r})=>r("spacing"),placeholderColor:({theme:r})=>r("colors"),placeholderOpacity:({theme:r})=>r("opacity"),ringColor:({theme:r})=>({DEFAULT:r("colors.blue.500","#3b82f6"),...r("colors")}),ringOffsetColor:({theme:r})=>r("colors"),ringOffsetWidth:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},ringOpacity:({theme:r})=>({DEFAULT:"0.5",...r("opacity")}),ringWidth:{DEFAULT:"3px",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},rotate:{0:"0deg",1:"1deg",2:"2deg",3:"3deg",6:"6deg",12:"12deg",45:"45deg",90:"90deg",180:"180deg"},saturate:{0:"0",50:".5",100:"1",150:"1.5",200:"2"},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"},screens:{sm:"640px",md:"768px",lg:"1024px",xl:"1280px","2xl":"1536px"},scrollMargin:({theme:r})=>({...r("spacing")}),scrollPadding:({theme:r})=>r("spacing"),sepia:{0:"0",DEFAULT:"100%"},skew:{0:"0deg",1:"1deg",2:"2deg",3:"3deg",6:"6deg",12:"12deg"},space:({theme:r})=>({...r("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:r})=>({none:"none",...r("colors")}),strokeWidth:{0:"0",1:"1",2:"2"},supports:{},data:{},textColor:({theme:r})=>r("colors"),textDecorationColor:({theme:r})=>r("colors"),textDecorationThickness:{auto:"auto","from-font":"from-font",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},textIndent:({theme:r})=>({...r("spacing")}),textOpacity:({theme:r})=>r("opacity"),textUnderlineOffset:{auto:"auto",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px"},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"},transitionDuration:{DEFAULT:"150ms",0:"0s",75:"75ms",100:"100ms",150:"150ms",200:"200ms",300:"300ms",500:"500ms",700:"700ms",1e3:"1000ms"},transitionProperty:{none:"none",all:"all",DEFAULT:"color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter",colors:"color, background-color, border-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:r})=>({...r("spacing"),"1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%",full:"100%"}),size:({theme:r})=>({auto:"auto",...r("spacing"),"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"}),width:({theme:r})=>({auto:"auto",...r("spacing"),"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"}),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"}},plugins:[]}});function Ci(r){let e=(r?.presets??[af.default]).slice().reverse().flatMap(n=>Ci(n instanceof Function?n():n)),t={respectDefaultRingColorOpacity:{theme:{ringColor:({theme:n})=>({DEFAULT:"#3b82f67f",...n("colors")})}},disableColorOpacityUtilitiesByDefault:{corePlugins:{backgroundOpacity:!1,borderOpacity:!1,divideOpacity:!1,placeholderOpacity:!1,ringOpacity:!1,textOpacity:!1}}},i=Object.keys(t).filter(n=>K(r,n)).map(n=>t[n]);return[r,...i,...e]}var af,of=C(()=>{l();af=X(Si());je()});var lf={};Ae(lf,{default:()=>gr});function gr(...r){let[,...e]=Ci(r[0]);return vs([...r,...e])}var xs=C(()=>{l();nf();of()});var uf={};Ae(uf,{default:()=>Z});var Z,bt=C(()=>{l();Z={resolve:r=>r,extname:r=>"."+r.split(".").pop()}});function Ai(r){return typeof r=="object"&&r!==null}function w0(r){return Object.keys(r).length===0}function ff(r){return typeof r=="string"||r instanceof String}function ks(r){return Ai(r)&&r.config===void 0&&!w0(r)?null:Ai(r)&&r.config!==void 0&&ff(r.config)?Z.resolve(r.config):Ai(r)&&r.config!==void 0&&Ai(r.config)?null:ff(r)?Z.resolve(r):b0()}function b0(){for(let r of y0)try{let e=Z.resolve(r);return te.accessSync(e),e}catch(e){}return null}var y0,cf=C(()=>{l();ze();bt();y0=["./tailwind.config.js","./tailwind.config.cjs","./tailwind.config.mjs","./tailwind.config.ts"]});var pf={};Ae(pf,{default:()=>Ss});var Ss,Cs=C(()=>{l();Ss={parse:r=>({href:r})}});var As=v(()=>{l()});var _i=v((d3,mf)=>{l();"use strict";var df=(hi(),Ou),hf=As(),Tt=class extends Error{constructor(e,t,i,n,a,s){super(e);this.name="CssSyntaxError",this.reason=e,a&&(this.file=a),n&&(this.source=n),s&&(this.plugin=s),typeof t!="undefined"&&typeof i!="undefined"&&(typeof t=="number"?(this.line=t,this.column=i):(this.line=t.line,this.column=t.column,this.endLine=i.line,this.endColumn=i.column)),this.setMessage(),Error.captureStackTrace&&Error.captureStackTrace(this,Tt)}setMessage(){this.message=this.plugin?this.plugin+": ":"",this.message+=this.file?this.file:"",typeof this.line!="undefined"&&(this.message+=":"+this.line+":"+this.column),this.message+=": "+this.reason}showSourceCode(e){if(!this.source)return"";let t=this.source;e==null&&(e=df.isColorSupported),hf&&e&&(t=hf(t));let i=t.split(/\r?\n/),n=Math.max(this.line-3,0),a=Math.min(this.line+2,i.length),s=String(a).length,o,u;if(e){let{bold:c,red:f,gray:d}=df.createColors(!0);o=p=>c(f(p)),u=p=>d(p)}else o=u=c=>c;return i.slice(n,a).map((c,f)=>{let d=n+1+f,p=" "+(" "+d).slice(-s)+" | ";if(d===this.line){let m=u(p.replace(/\d/g," "))+c.slice(0,this.column-1).replace(/[^\t]/g," ");return o(">")+u(p)+c+` - `+m+o("^")}return" "+u(p)+c}).join(` -`)}toString(){let e=this.showSourceCode();return e&&(e=` +(() => { + var Rb = Object.create; + var ci = Object.defineProperty; + var Mb = Object.getOwnPropertyDescriptor; + var Bb = Object.getOwnPropertyNames; + var Fb = Object.getPrototypeOf, + Lb = Object.prototype.hasOwnProperty; + var gu = (r) => ci(r, "__esModule", { value: !0 }); + var yu = (r) => { + if (typeof require != "undefined") return require(r); + throw new Error('Dynamic require of "' + r + '" is not supported'); + }; + var C = (r, e) => () => (r && (e = r((r = 0))), e); + var v = (r, e) => () => (e || r((e = { exports: {} }).exports, e), e.exports), + Ae = (r, e) => { + gu(r); + for (var t in e) ci(r, t, { get: e[t], enumerable: !0 }); + }, + Nb = (r, e, t) => { + if ((e && typeof e == "object") || typeof e == "function") + for (let i of Bb(e)) + !Lb.call(r, i) && + i !== "default" && + ci(r, i, { get: () => e[i], enumerable: !(t = Mb(e, i)) || t.enumerable }); + return r; + }, + X = (r) => + Nb( + gu( + ci( + r != null ? Rb(Fb(r)) : {}, + "default", + r && r.__esModule && "default" in r + ? { get: () => r.default, enumerable: !0 } + : { value: r, enumerable: !0 } + ) + ), + r + ); + var h, + l = C(() => { + h = { platform: "", env: {}, versions: { node: "14.17.6" } }; + }); + var $b, + te, + ze = C(() => { + l(); + (($b = 0), + (te = { + readFileSync: (r) => self[r] || "", + statSync: () => ({ mtimeMs: $b++ }), + promises: { readFile: (r) => Promise.resolve(self[r] || "") }, + })); + }); + var rs = v((eE, bu) => { + l(); + ("use strict"); + var wu = class { + constructor(e = {}) { + if (!(e.maxSize && e.maxSize > 0)) throw new TypeError("`maxSize` must be a number greater than 0"); + if (typeof e.maxAge == "number" && e.maxAge === 0) + throw new TypeError("`maxAge` must be a number greater than 0"); + ((this.maxSize = e.maxSize), + (this.maxAge = e.maxAge || 1 / 0), + (this.onEviction = e.onEviction), + (this.cache = new Map()), + (this.oldCache = new Map()), + (this._size = 0)); + } + _emitEvictions(e) { + if (typeof this.onEviction == "function") for (let [t, i] of e) this.onEviction(t, i.value); + } + _deleteIfExpired(e, t) { + return typeof t.expiry == "number" && t.expiry <= Date.now() + ? (typeof this.onEviction == "function" && this.onEviction(e, t.value), this.delete(e)) + : !1; + } + _getOrDeleteIfExpired(e, t) { + if (this._deleteIfExpired(e, t) === !1) return t.value; + } + _getItemValue(e, t) { + return t.expiry ? this._getOrDeleteIfExpired(e, t) : t.value; + } + _peek(e, t) { + let i = t.get(e); + return this._getItemValue(e, i); + } + _set(e, t) { + (this.cache.set(e, t), + this._size++, + this._size >= this.maxSize && + ((this._size = 0), + this._emitEvictions(this.oldCache), + (this.oldCache = this.cache), + (this.cache = new Map()))); + } + _moveToRecent(e, t) { + (this.oldCache.delete(e), this._set(e, t)); + } + *_entriesAscending() { + for (let e of this.oldCache) { + let [t, i] = e; + this.cache.has(t) || (this._deleteIfExpired(t, i) === !1 && (yield e)); + } + for (let e of this.cache) { + let [t, i] = e; + this._deleteIfExpired(t, i) === !1 && (yield e); + } + } + get(e) { + if (this.cache.has(e)) { + let t = this.cache.get(e); + return this._getItemValue(e, t); + } + if (this.oldCache.has(e)) { + let t = this.oldCache.get(e); + if (this._deleteIfExpired(e, t) === !1) return (this._moveToRecent(e, t), t.value); + } + } + set(e, t, { maxAge: i = this.maxAge === 1 / 0 ? void 0 : Date.now() + this.maxAge } = {}) { + this.cache.has(e) ? this.cache.set(e, { value: t, maxAge: i }) : this._set(e, { value: t, expiry: i }); + } + has(e) { + return this.cache.has(e) + ? !this._deleteIfExpired(e, this.cache.get(e)) + : this.oldCache.has(e) + ? !this._deleteIfExpired(e, this.oldCache.get(e)) + : !1; + } + peek(e) { + if (this.cache.has(e)) return this._peek(e, this.cache); + if (this.oldCache.has(e)) return this._peek(e, this.oldCache); + } + delete(e) { + let t = this.cache.delete(e); + return (t && this._size--, this.oldCache.delete(e) || t); + } + clear() { + (this.cache.clear(), this.oldCache.clear(), (this._size = 0)); + } + resize(e) { + if (!(e && e > 0)) throw new TypeError("`maxSize` must be a number greater than 0"); + let t = [...this._entriesAscending()], + i = t.length - e; + (i < 0 + ? ((this.cache = new Map(t)), (this.oldCache = new Map()), (this._size = t.length)) + : (i > 0 && this._emitEvictions(t.slice(0, i)), + (this.oldCache = new Map(t.slice(i))), + (this.cache = new Map()), + (this._size = 0)), + (this.maxSize = e)); + } + *keys() { + for (let [e] of this) yield e; + } + *values() { + for (let [, e] of this) yield e; + } + *[Symbol.iterator]() { + for (let e of this.cache) { + let [t, i] = e; + this._deleteIfExpired(t, i) === !1 && (yield [t, i.value]); + } + for (let e of this.oldCache) { + let [t, i] = e; + this.cache.has(t) || (this._deleteIfExpired(t, i) === !1 && (yield [t, i.value])); + } + } + *entriesDescending() { + let e = [...this.cache]; + for (let t = e.length - 1; t >= 0; --t) { + let i = e[t], + [n, a] = i; + this._deleteIfExpired(n, a) === !1 && (yield [n, a.value]); + } + e = [...this.oldCache]; + for (let t = e.length - 1; t >= 0; --t) { + let i = e[t], + [n, a] = i; + this.cache.has(n) || (this._deleteIfExpired(n, a) === !1 && (yield [n, a.value])); + } + } + *entriesAscending() { + for (let [e, t] of this._entriesAscending()) yield [e, t.value]; + } + get size() { + if (!this._size) return this.oldCache.size; + let e = 0; + for (let t of this.oldCache.keys()) this.cache.has(t) || e++; + return Math.min(this._size + e, this.maxSize); + } + }; + bu.exports = wu; + }); + var vu, + xu = C(() => { + l(); + vu = (r) => r && r._hash; + }); + function pi(r) { + return vu(r, { ignoreUnknown: !0 }); + } + var ku = C(() => { + l(); + xu(); + }); + function Ke(r) { + if (((r = `${r}`), r === "0")) return "0"; + if (/^[+-]?(\d+|\d*\.\d+)(e[+-]?\d+)?(%|\w+)?$/.test(r)) + return r.replace(/^[+-]?/, (t) => (t === "-" ? "" : "-")); + let e = ["var", "calc", "min", "max", "clamp"]; + for (let t of e) if (r.includes(`${t}(`)) return `calc(${r} * -1)`; + } + var di = C(() => { + l(); + }); + var Su, + Cu = C(() => { + l(); + Su = [ + "preflight", + "container", + "accessibility", + "pointerEvents", + "visibility", + "position", + "inset", + "isolation", + "zIndex", + "order", + "gridColumn", + "gridColumnStart", + "gridColumnEnd", + "gridRow", + "gridRowStart", + "gridRowEnd", + "float", + "clear", + "margin", + "boxSizing", + "lineClamp", + "display", + "aspectRatio", + "size", + "height", + "maxHeight", + "minHeight", + "width", + "minWidth", + "maxWidth", + "flex", + "flexShrink", + "flexGrow", + "flexBasis", + "tableLayout", + "captionSide", + "borderCollapse", + "borderSpacing", + "transformOrigin", + "translate", + "rotate", + "skew", + "scale", + "transform", + "animation", + "cursor", + "touchAction", + "userSelect", + "resize", + "scrollSnapType", + "scrollSnapAlign", + "scrollSnapStop", + "scrollMargin", + "scrollPadding", + "listStylePosition", + "listStyleType", + "listStyleImage", + "appearance", + "columns", + "breakBefore", + "breakInside", + "breakAfter", + "gridAutoColumns", + "gridAutoFlow", + "gridAutoRows", + "gridTemplateColumns", + "gridTemplateRows", + "flexDirection", + "flexWrap", + "placeContent", + "placeItems", + "alignContent", + "alignItems", + "justifyContent", + "justifyItems", + "gap", + "space", + "divideWidth", + "divideStyle", + "divideColor", + "divideOpacity", + "placeSelf", + "alignSelf", + "justifySelf", + "overflow", + "overscrollBehavior", + "scrollBehavior", + "textOverflow", + "hyphens", + "whitespace", + "textWrap", + "wordBreak", + "borderRadius", + "borderWidth", + "borderStyle", + "borderColor", + "borderOpacity", + "backgroundColor", + "backgroundOpacity", + "backgroundImage", + "gradientColorStops", + "boxDecorationBreak", + "backgroundSize", + "backgroundAttachment", + "backgroundClip", + "backgroundPosition", + "backgroundRepeat", + "backgroundOrigin", + "fill", + "stroke", + "strokeWidth", + "objectFit", + "objectPosition", + "padding", + "textAlign", + "textIndent", + "verticalAlign", + "fontFamily", + "fontSize", + "fontWeight", + "textTransform", + "fontStyle", + "fontVariantNumeric", + "lineHeight", + "letterSpacing", + "textColor", + "textOpacity", + "textDecoration", + "textDecorationColor", + "textDecorationStyle", + "textDecorationThickness", + "textUnderlineOffset", + "fontSmoothing", + "placeholderColor", + "placeholderOpacity", + "caretColor", + "accentColor", + "opacity", + "backgroundBlendMode", + "mixBlendMode", + "boxShadow", + "boxShadowColor", + "outlineStyle", + "outlineWidth", + "outlineOffset", + "outlineColor", + "ringWidth", + "ringColor", + "ringOpacity", + "ringOffsetWidth", + "ringOffsetColor", + "blur", + "brightness", + "contrast", + "dropShadow", + "grayscale", + "hueRotate", + "invert", + "saturate", + "sepia", + "filter", + "backdropBlur", + "backdropBrightness", + "backdropContrast", + "backdropGrayscale", + "backdropHueRotate", + "backdropInvert", + "backdropOpacity", + "backdropSaturate", + "backdropSepia", + "backdropFilter", + "transitionProperty", + "transitionDelay", + "transitionDuration", + "transitionTimingFunction", + "willChange", + "contain", + "content", + "forcedColorAdjust", + ]; + }); + function Au(r, e) { + return r === void 0 + ? e + : Array.isArray(r) + ? r + : [ + ...new Set( + e.filter((i) => r !== !1 && r[i] !== !1).concat(Object.keys(r).filter((i) => r[i] !== !1)) + ), + ]; + } + var _u = C(() => { + l(); + }); + var Ou = {}; + Ae(Ou, { default: () => _e }); + var _e, + hi = C(() => { + l(); + _e = new Proxy({}, { get: () => String }); + }); + function is(r, e, t) { + (typeof h != "undefined" && h.env.JEST_WORKER_ID) || + (t && Eu.has(t)) || + (t && Eu.add(t), console.warn(""), e.forEach((i) => console.warn(r, "-", i))); + } + function ns(r) { + return _e.dim(r); + } + var Eu, + F, + Oe = C(() => { + l(); + hi(); + Eu = new Set(); + F = { + info(r, e) { + is(_e.bold(_e.cyan("info")), ...(Array.isArray(r) ? [r] : [e, r])); + }, + warn(r, e) { + ["content-problems"].includes(r) || + is(_e.bold(_e.yellow("warn")), ...(Array.isArray(r) ? [r] : [e, r])); + }, + risk(r, e) { + is(_e.bold(_e.magenta("risk")), ...(Array.isArray(r) ? [r] : [e, r])); + }, + }; + }); + var as = {}; + Ae(as, { default: () => ss }); + function lr({ version: r, from: e, to: t }) { + F.warn(`${e}-color-renamed`, [ + `As of Tailwind CSS ${r}, \`${e}\` has been renamed to \`${t}\`.`, + "Update your configuration file to silence this warning.", + ]); + } + var ss, + mi = C(() => { + l(); + Oe(); + ss = { + inherit: "inherit", + current: "currentColor", + transparent: "transparent", + black: "#000", + white: "#fff", + slate: { + 50: "#f8fafc", + 100: "#f1f5f9", + 200: "#e2e8f0", + 300: "#cbd5e1", + 400: "#94a3b8", + 500: "#64748b", + 600: "#475569", + 700: "#334155", + 800: "#1e293b", + 900: "#0f172a", + 950: "#020617", + }, + gray: { + 50: "#f9fafb", + 100: "#f3f4f6", + 200: "#e5e7eb", + 300: "#d1d5db", + 400: "#9ca3af", + 500: "#6b7280", + 600: "#4b5563", + 700: "#374151", + 800: "#1f2937", + 900: "#111827", + 950: "#030712", + }, + zinc: { + 50: "#fafafa", + 100: "#f4f4f5", + 200: "#e4e4e7", + 300: "#d4d4d8", + 400: "#a1a1aa", + 500: "#71717a", + 600: "#52525b", + 700: "#3f3f46", + 800: "#27272a", + 900: "#18181b", + 950: "#09090b", + }, + neutral: { + 50: "#fafafa", + 100: "#f5f5f5", + 200: "#e5e5e5", + 300: "#d4d4d4", + 400: "#a3a3a3", + 500: "#737373", + 600: "#525252", + 700: "#404040", + 800: "#262626", + 900: "#171717", + 950: "#0a0a0a", + }, + stone: { + 50: "#fafaf9", + 100: "#f5f5f4", + 200: "#e7e5e4", + 300: "#d6d3d1", + 400: "#a8a29e", + 500: "#78716c", + 600: "#57534e", + 700: "#44403c", + 800: "#292524", + 900: "#1c1917", + 950: "#0c0a09", + }, + red: { + 50: "#fef2f2", + 100: "#fee2e2", + 200: "#fecaca", + 300: "#fca5a5", + 400: "#f87171", + 500: "#ef4444", + 600: "#dc2626", + 700: "#b91c1c", + 800: "#991b1b", + 900: "#7f1d1d", + 950: "#450a0a", + }, + orange: { + 50: "#fff7ed", + 100: "#ffedd5", + 200: "#fed7aa", + 300: "#fdba74", + 400: "#fb923c", + 500: "#f97316", + 600: "#ea580c", + 700: "#c2410c", + 800: "#9a3412", + 900: "#7c2d12", + 950: "#431407", + }, + amber: { + 50: "#fffbeb", + 100: "#fef3c7", + 200: "#fde68a", + 300: "#fcd34d", + 400: "#fbbf24", + 500: "#f59e0b", + 600: "#d97706", + 700: "#b45309", + 800: "#92400e", + 900: "#78350f", + 950: "#451a03", + }, + yellow: { + 50: "#fefce8", + 100: "#fef9c3", + 200: "#fef08a", + 300: "#fde047", + 400: "#facc15", + 500: "#eab308", + 600: "#ca8a04", + 700: "#a16207", + 800: "#854d0e", + 900: "#713f12", + 950: "#422006", + }, + lime: { + 50: "#f7fee7", + 100: "#ecfccb", + 200: "#d9f99d", + 300: "#bef264", + 400: "#a3e635", + 500: "#84cc16", + 600: "#65a30d", + 700: "#4d7c0f", + 800: "#3f6212", + 900: "#365314", + 950: "#1a2e05", + }, + green: { + 50: "#f0fdf4", + 100: "#dcfce7", + 200: "#bbf7d0", + 300: "#86efac", + 400: "#4ade80", + 500: "#22c55e", + 600: "#16a34a", + 700: "#15803d", + 800: "#166534", + 900: "#14532d", + 950: "#052e16", + }, + emerald: { + 50: "#ecfdf5", + 100: "#d1fae5", + 200: "#a7f3d0", + 300: "#6ee7b7", + 400: "#34d399", + 500: "#10b981", + 600: "#059669", + 700: "#047857", + 800: "#065f46", + 900: "#064e3b", + 950: "#022c22", + }, + teal: { + 50: "#f0fdfa", + 100: "#ccfbf1", + 200: "#99f6e4", + 300: "#5eead4", + 400: "#2dd4bf", + 500: "#14b8a6", + 600: "#0d9488", + 700: "#0f766e", + 800: "#115e59", + 900: "#134e4a", + 950: "#042f2e", + }, + cyan: { + 50: "#ecfeff", + 100: "#cffafe", + 200: "#a5f3fc", + 300: "#67e8f9", + 400: "#22d3ee", + 500: "#06b6d4", + 600: "#0891b2", + 700: "#0e7490", + 800: "#155e75", + 900: "#164e63", + 950: "#083344", + }, + sky: { + 50: "#f0f9ff", + 100: "#e0f2fe", + 200: "#bae6fd", + 300: "#7dd3fc", + 400: "#38bdf8", + 500: "#0ea5e9", + 600: "#0284c7", + 700: "#0369a1", + 800: "#075985", + 900: "#0c4a6e", + 950: "#082f49", + }, + blue: { + 50: "#eff6ff", + 100: "#dbeafe", + 200: "#bfdbfe", + 300: "#93c5fd", + 400: "#60a5fa", + 500: "#3b82f6", + 600: "#2563eb", + 700: "#1d4ed8", + 800: "#1e40af", + 900: "#1e3a8a", + 950: "#172554", + }, + indigo: { + 50: "#eef2ff", + 100: "#e0e7ff", + 200: "#c7d2fe", + 300: "#a5b4fc", + 400: "#818cf8", + 500: "#6366f1", + 600: "#4f46e5", + 700: "#4338ca", + 800: "#3730a3", + 900: "#312e81", + 950: "#1e1b4b", + }, + violet: { + 50: "#f5f3ff", + 100: "#ede9fe", + 200: "#ddd6fe", + 300: "#c4b5fd", + 400: "#a78bfa", + 500: "#8b5cf6", + 600: "#7c3aed", + 700: "#6d28d9", + 800: "#5b21b6", + 900: "#4c1d95", + 950: "#2e1065", + }, + purple: { + 50: "#faf5ff", + 100: "#f3e8ff", + 200: "#e9d5ff", + 300: "#d8b4fe", + 400: "#c084fc", + 500: "#a855f7", + 600: "#9333ea", + 700: "#7e22ce", + 800: "#6b21a8", + 900: "#581c87", + 950: "#3b0764", + }, + fuchsia: { + 50: "#fdf4ff", + 100: "#fae8ff", + 200: "#f5d0fe", + 300: "#f0abfc", + 400: "#e879f9", + 500: "#d946ef", + 600: "#c026d3", + 700: "#a21caf", + 800: "#86198f", + 900: "#701a75", + 950: "#4a044e", + }, + pink: { + 50: "#fdf2f8", + 100: "#fce7f3", + 200: "#fbcfe8", + 300: "#f9a8d4", + 400: "#f472b6", + 500: "#ec4899", + 600: "#db2777", + 700: "#be185d", + 800: "#9d174d", + 900: "#831843", + 950: "#500724", + }, + rose: { + 50: "#fff1f2", + 100: "#ffe4e6", + 200: "#fecdd3", + 300: "#fda4af", + 400: "#fb7185", + 500: "#f43f5e", + 600: "#e11d48", + 700: "#be123c", + 800: "#9f1239", + 900: "#881337", + 950: "#4c0519", + }, + get lightBlue() { + return (lr({ version: "v2.2", from: "lightBlue", to: "sky" }), this.sky); + }, + get warmGray() { + return (lr({ version: "v3.0", from: "warmGray", to: "stone" }), this.stone); + }, + get trueGray() { + return (lr({ version: "v3.0", from: "trueGray", to: "neutral" }), this.neutral); + }, + get coolGray() { + return (lr({ version: "v3.0", from: "coolGray", to: "gray" }), this.gray); + }, + get blueGray() { + return (lr({ version: "v3.0", from: "blueGray", to: "slate" }), this.slate); + }, + }; + }); + function os(r, ...e) { + for (let t of e) { + for (let i in t) r?.hasOwnProperty?.(i) || (r[i] = t[i]); + for (let i of Object.getOwnPropertySymbols(t)) r?.hasOwnProperty?.(i) || (r[i] = t[i]); + } + return r; + } + var Tu = C(() => { + l(); + }); + function Ze(r) { + if (Array.isArray(r)) return r; + let e = r.split("[").length - 1, + t = r.split("]").length - 1; + if (e !== t) throw new Error(`Path is invalid. Has unbalanced brackets: ${r}`); + return r.split(/\.(?![^\[]*\])|[\[\]]/g).filter(Boolean); + } + var gi = C(() => { + l(); + }); + function K(r, e) { + return yi.future.includes(e) + ? r.future === "all" || (r?.future?.[e] ?? Pu[e] ?? !1) + : yi.experimental.includes(e) + ? r.experimental === "all" || (r?.experimental?.[e] ?? Pu[e] ?? !1) + : !1; + } + function Du(r) { + return r.experimental === "all" + ? yi.experimental + : Object.keys(r?.experimental ?? {}).filter((e) => yi.experimental.includes(e) && r.experimental[e]); + } + function Iu(r) { + if (h.env.JEST_WORKER_ID === void 0 && Du(r).length > 0) { + let e = Du(r) + .map((t) => _e.yellow(t)) + .join(", "); + F.warn("experimental-flags-enabled", [ + `You have enabled experimental features: ${e}`, + "Experimental features in Tailwind CSS are not covered by semver, may introduce breaking changes, and can change at any time.", + ]); + } + } + var Pu, + yi, + je = C(() => { + l(); + hi(); + Oe(); + ((Pu = { + optimizeUniversalDefaults: !1, + generalizedModifiers: !0, + disableColorOpacityUtilitiesByDefault: !1, + relativeContentPathsByDefault: !1, + }), + (yi = { + future: [ + "hoverOnlyWhenSupported", + "respectDefaultRingColorOpacity", + "disableColorOpacityUtilitiesByDefault", + "relativeContentPathsByDefault", + ], + experimental: ["optimizeUniversalDefaults", "generalizedModifiers"], + })); + }); + function qu(r) { + ((() => { + if ( + r.purge || + !r.content || + (!Array.isArray(r.content) && !(typeof r.content == "object" && r.content !== null)) + ) + return !1; + if (Array.isArray(r.content)) + return r.content.every((t) => + typeof t == "string" + ? !0 + : !(typeof t?.raw != "string" || (t?.extension && typeof t?.extension != "string")) + ); + if (typeof r.content == "object" && r.content !== null) { + if (Object.keys(r.content).some((t) => !["files", "relative", "extract", "transform"].includes(t))) + return !1; + if (Array.isArray(r.content.files)) { + if ( + !r.content.files.every((t) => + typeof t == "string" + ? !0 + : !(typeof t?.raw != "string" || (t?.extension && typeof t?.extension != "string")) + ) + ) + return !1; + if (typeof r.content.extract == "object") { + for (let t of Object.values(r.content.extract)) if (typeof t != "function") return !1; + } else if (!(r.content.extract === void 0 || typeof r.content.extract == "function")) return !1; + if (typeof r.content.transform == "object") { + for (let t of Object.values(r.content.transform)) if (typeof t != "function") return !1; + } else if (!(r.content.transform === void 0 || typeof r.content.transform == "function")) return !1; + if (typeof r.content.relative != "boolean" && typeof r.content.relative != "undefined") return !1; + } + return !0; + } + return !1; + })() || + F.warn("purge-deprecation", [ + "The `purge`/`content` options have changed in Tailwind CSS v3.0.", + "Update your configuration file to eliminate this warning.", + "https://tailwindcss.com/docs/upgrade-guide#configure-content-sources", + ]), + (r.safelist = (() => { + let { content: t, purge: i, safelist: n } = r; + return Array.isArray(n) + ? n + : Array.isArray(t?.safelist) + ? t.safelist + : Array.isArray(i?.safelist) + ? i.safelist + : Array.isArray(i?.options?.safelist) + ? i.options.safelist + : []; + })()), + (r.blocklist = (() => { + let { blocklist: t } = r; + if (Array.isArray(t)) { + if (t.every((i) => typeof i == "string")) return t; + F.warn("blocklist-invalid", [ + "The `blocklist` option must be an array of strings.", + "https://tailwindcss.com/docs/content-configuration#discarding-classes", + ]); + } + return []; + })()), + typeof r.prefix == "function" + ? (F.warn("prefix-function", [ + "As of Tailwind CSS v3.0, `prefix` cannot be a function.", + "Update `prefix` in your configuration to be a string to eliminate this warning.", + "https://tailwindcss.com/docs/upgrade-guide#prefix-cannot-be-a-function", + ]), + (r.prefix = "")) + : (r.prefix = r.prefix ?? ""), + (r.content = { + relative: (() => { + let { content: t } = r; + return t?.relative ? t.relative : K(r, "relativeContentPathsByDefault"); + })(), + files: (() => { + let { content: t, purge: i } = r; + return Array.isArray(i) + ? i + : Array.isArray(i?.content) + ? i.content + : Array.isArray(t) + ? t + : Array.isArray(t?.content) + ? t.content + : Array.isArray(t?.files) + ? t.files + : []; + })(), + extract: (() => { + let t = (() => + r.purge?.extract + ? r.purge.extract + : r.content?.extract + ? r.content.extract + : r.purge?.extract?.DEFAULT + ? r.purge.extract.DEFAULT + : r.content?.extract?.DEFAULT + ? r.content.extract.DEFAULT + : r.purge?.options?.extractors + ? r.purge.options.extractors + : r.content?.options?.extractors + ? r.content.options.extractors + : {})(), + i = {}, + n = (() => { + if (r.purge?.options?.defaultExtractor) return r.purge.options.defaultExtractor; + if (r.content?.options?.defaultExtractor) return r.content.options.defaultExtractor; + })(); + if ((n !== void 0 && (i.DEFAULT = n), typeof t == "function")) i.DEFAULT = t; + else if (Array.isArray(t)) + for (let { extensions: a, extractor: s } of t ?? []) for (let o of a) i[o] = s; + else typeof t == "object" && t !== null && Object.assign(i, t); + return i; + })(), + transform: (() => { + let t = (() => + r.purge?.transform + ? r.purge.transform + : r.content?.transform + ? r.content.transform + : r.purge?.transform?.DEFAULT + ? r.purge.transform.DEFAULT + : r.content?.transform?.DEFAULT + ? r.content.transform.DEFAULT + : {})(), + i = {}; + return ( + typeof t == "function" && (i.DEFAULT = t), + typeof t == "object" && t !== null && Object.assign(i, t), + i + ); + })(), + })); + for (let t of r.content.files) + if (typeof t == "string" && /{([^,]*?)}/g.test(t)) { + F.warn("invalid-glob-braces", [ + `The glob pattern ${ns(t)} in your Tailwind CSS configuration is invalid.`, + `Update it to ${ns(t.replace(/{([^,]*?)}/g, "$1"))} to silence this warning.`, + ]); + break; + } + return r; + } + var Ru = C(() => { + l(); + je(); + Oe(); + }); + function ie(r) { + if (Object.prototype.toString.call(r) !== "[object Object]") return !1; + let e = Object.getPrototypeOf(r); + return e === null || Object.getPrototypeOf(e) === null; + } + var At = C(() => { + l(); + }); + function et(r) { + return Array.isArray(r) + ? r.map((e) => et(e)) + : typeof r == "object" && r !== null + ? Object.fromEntries(Object.entries(r).map(([e, t]) => [e, et(t)])) + : r; + } + var wi = C(() => { + l(); + }); + function wt(r) { + return r.replace(/\\,/g, "\\2c "); + } + var bi = C(() => { + l(); + }); + var ls, + Mu = C(() => { + l(); + ls = { + aliceblue: [240, 248, 255], + antiquewhite: [250, 235, 215], + aqua: [0, 255, 255], + aquamarine: [127, 255, 212], + azure: [240, 255, 255], + beige: [245, 245, 220], + bisque: [255, 228, 196], + black: [0, 0, 0], + blanchedalmond: [255, 235, 205], + blue: [0, 0, 255], + blueviolet: [138, 43, 226], + brown: [165, 42, 42], + burlywood: [222, 184, 135], + cadetblue: [95, 158, 160], + chartreuse: [127, 255, 0], + chocolate: [210, 105, 30], + coral: [255, 127, 80], + cornflowerblue: [100, 149, 237], + cornsilk: [255, 248, 220], + crimson: [220, 20, 60], + cyan: [0, 255, 255], + darkblue: [0, 0, 139], + darkcyan: [0, 139, 139], + darkgoldenrod: [184, 134, 11], + darkgray: [169, 169, 169], + darkgreen: [0, 100, 0], + darkgrey: [169, 169, 169], + darkkhaki: [189, 183, 107], + darkmagenta: [139, 0, 139], + darkolivegreen: [85, 107, 47], + darkorange: [255, 140, 0], + darkorchid: [153, 50, 204], + darkred: [139, 0, 0], + darksalmon: [233, 150, 122], + darkseagreen: [143, 188, 143], + darkslateblue: [72, 61, 139], + darkslategray: [47, 79, 79], + darkslategrey: [47, 79, 79], + darkturquoise: [0, 206, 209], + darkviolet: [148, 0, 211], + deeppink: [255, 20, 147], + deepskyblue: [0, 191, 255], + dimgray: [105, 105, 105], + dimgrey: [105, 105, 105], + dodgerblue: [30, 144, 255], + firebrick: [178, 34, 34], + floralwhite: [255, 250, 240], + forestgreen: [34, 139, 34], + fuchsia: [255, 0, 255], + gainsboro: [220, 220, 220], + ghostwhite: [248, 248, 255], + gold: [255, 215, 0], + goldenrod: [218, 165, 32], + gray: [128, 128, 128], + green: [0, 128, 0], + greenyellow: [173, 255, 47], + grey: [128, 128, 128], + honeydew: [240, 255, 240], + hotpink: [255, 105, 180], + indianred: [205, 92, 92], + indigo: [75, 0, 130], + ivory: [255, 255, 240], + khaki: [240, 230, 140], + lavender: [230, 230, 250], + lavenderblush: [255, 240, 245], + lawngreen: [124, 252, 0], + lemonchiffon: [255, 250, 205], + lightblue: [173, 216, 230], + lightcoral: [240, 128, 128], + lightcyan: [224, 255, 255], + lightgoldenrodyellow: [250, 250, 210], + lightgray: [211, 211, 211], + lightgreen: [144, 238, 144], + lightgrey: [211, 211, 211], + lightpink: [255, 182, 193], + lightsalmon: [255, 160, 122], + lightseagreen: [32, 178, 170], + lightskyblue: [135, 206, 250], + lightslategray: [119, 136, 153], + lightslategrey: [119, 136, 153], + lightsteelblue: [176, 196, 222], + lightyellow: [255, 255, 224], + lime: [0, 255, 0], + limegreen: [50, 205, 50], + linen: [250, 240, 230], + magenta: [255, 0, 255], + maroon: [128, 0, 0], + mediumaquamarine: [102, 205, 170], + mediumblue: [0, 0, 205], + mediumorchid: [186, 85, 211], + mediumpurple: [147, 112, 219], + mediumseagreen: [60, 179, 113], + mediumslateblue: [123, 104, 238], + mediumspringgreen: [0, 250, 154], + mediumturquoise: [72, 209, 204], + mediumvioletred: [199, 21, 133], + midnightblue: [25, 25, 112], + mintcream: [245, 255, 250], + mistyrose: [255, 228, 225], + moccasin: [255, 228, 181], + navajowhite: [255, 222, 173], + navy: [0, 0, 128], + oldlace: [253, 245, 230], + olive: [128, 128, 0], + olivedrab: [107, 142, 35], + orange: [255, 165, 0], + orangered: [255, 69, 0], + orchid: [218, 112, 214], + palegoldenrod: [238, 232, 170], + palegreen: [152, 251, 152], + paleturquoise: [175, 238, 238], + palevioletred: [219, 112, 147], + papayawhip: [255, 239, 213], + peachpuff: [255, 218, 185], + peru: [205, 133, 63], + pink: [255, 192, 203], + plum: [221, 160, 221], + powderblue: [176, 224, 230], + purple: [128, 0, 128], + rebeccapurple: [102, 51, 153], + red: [255, 0, 0], + rosybrown: [188, 143, 143], + royalblue: [65, 105, 225], + saddlebrown: [139, 69, 19], + salmon: [250, 128, 114], + sandybrown: [244, 164, 96], + seagreen: [46, 139, 87], + seashell: [255, 245, 238], + sienna: [160, 82, 45], + silver: [192, 192, 192], + skyblue: [135, 206, 235], + slateblue: [106, 90, 205], + slategray: [112, 128, 144], + slategrey: [112, 128, 144], + snow: [255, 250, 250], + springgreen: [0, 255, 127], + steelblue: [70, 130, 180], + tan: [210, 180, 140], + teal: [0, 128, 128], + thistle: [216, 191, 216], + tomato: [255, 99, 71], + turquoise: [64, 224, 208], + violet: [238, 130, 238], + wheat: [245, 222, 179], + white: [255, 255, 255], + whitesmoke: [245, 245, 245], + yellow: [255, 255, 0], + yellowgreen: [154, 205, 50], + }; + }); + function ur(r, { loose: e = !1 } = {}) { + if (typeof r != "string") return null; + if (((r = r.trim()), r === "transparent")) return { mode: "rgb", color: ["0", "0", "0"], alpha: "0" }; + if (r in ls) return { mode: "rgb", color: ls[r].map((a) => a.toString()) }; + let t = r.replace(jb, (a, s, o, u, c) => ["#", s, s, o, o, u, u, c ? c + c : ""].join("")).match(zb); + if (t !== null) + return { + mode: "rgb", + color: [parseInt(t[1], 16), parseInt(t[2], 16), parseInt(t[3], 16)].map((a) => a.toString()), + alpha: t[4] ? (parseInt(t[4], 16) / 255).toString() : void 0, + }; + let i = r.match(Vb) ?? r.match(Ub); + if (i === null) return null; + let n = [i[2], i[3], i[4]].filter(Boolean).map((a) => a.toString()); + return n.length === 2 && n[0].startsWith("var(") + ? { mode: i[1], color: [n[0]], alpha: n[1] } + : (!e && n.length !== 3) || (n.length < 3 && !n.some((a) => /^var\(.*?\)$/.test(a))) + ? null + : { mode: i[1], color: n, alpha: i[5]?.toString?.() }; + } + function us({ mode: r, color: e, alpha: t }) { + let i = t !== void 0; + return r === "rgba" || r === "hsla" + ? `${r}(${e.join(", ")}${i ? `, ${t}` : ""})` + : `${r}(${e.join(" ")}${i ? ` / ${t}` : ""})`; + } + var zb, + jb, + tt, + vi, + Bu, + rt, + Vb, + Ub, + fs = C(() => { + l(); + Mu(); + ((zb = /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i), + (jb = /^#([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i), + (tt = /(?:\d+|\d*\.\d+)%?/), + (vi = /(?:\s*,\s*|\s+)/), + (Bu = /\s*[,/]\s*/), + (rt = /var\(--(?:[^ )]*?)(?:,(?:[^ )]*?|var\(--[^ )]*?\)))?\)/), + (Vb = new RegExp( + `^(rgba?)\\(\\s*(${tt.source}|${rt.source})(?:${vi.source}(${tt.source}|${rt.source}))?(?:${vi.source}(${tt.source}|${rt.source}))?(?:${Bu.source}(${tt.source}|${rt.source}))?\\s*\\)$` + )), + (Ub = new RegExp( + `^(hsla?)\\(\\s*((?:${tt.source})(?:deg|rad|grad|turn)?|${rt.source})(?:${vi.source}(${tt.source}|${rt.source}))?(?:${vi.source}(${tt.source}|${rt.source}))?(?:${Bu.source}(${tt.source}|${rt.source}))?\\s*\\)$` + ))); + }); + function Ie(r, e, t) { + if (typeof r == "function") return r({ opacityValue: e }); + let i = ur(r, { loose: !0 }); + return i === null ? t : us({ ...i, alpha: e }); + } + function se({ color: r, property: e, variable: t }) { + let i = [].concat(e); + if (typeof r == "function") + return { + [t]: "1", + ...Object.fromEntries(i.map((a) => [a, r({ opacityVariable: t, opacityValue: `var(${t})` })])), + }; + let n = ur(r); + return n === null + ? Object.fromEntries(i.map((a) => [a, r])) + : n.alpha !== void 0 + ? Object.fromEntries(i.map((a) => [a, r])) + : { [t]: "1", ...Object.fromEntries(i.map((a) => [a, us({ ...n, alpha: `var(${t})` })])) }; + } + var fr = C(() => { + l(); + fs(); + }); + function ae(r, e) { + let t = [], + i = [], + n = 0, + a = !1; + for (let s = 0; s < r.length; s++) { + let o = r[s]; + (t.length === 0 && + o === e[0] && + !a && + (e.length === 1 || r.slice(s, s + e.length) === e) && + (i.push(r.slice(n, s)), (n = s + e.length)), + a ? (a = !1) : o === "\\" && (a = !0), + o === "(" || o === "[" || o === "{" + ? t.push(o) + : ((o === ")" && t[t.length - 1] === "(") || + (o === "]" && t[t.length - 1] === "[") || + (o === "}" && t[t.length - 1] === "{")) && + t.pop()); + } + return (i.push(r.slice(n)), i); + } + var _t = C(() => { + l(); + }); + function xi(r) { + return ae(r, ",").map((t) => { + let i = t.trim(), + n = { raw: i }, + a = i.split(Gb), + s = new Set(); + for (let o of a) + ((Fu.lastIndex = 0), + !s.has("KEYWORD") && Wb.has(o) + ? ((n.keyword = o), s.add("KEYWORD")) + : Fu.test(o) + ? s.has("X") + ? s.has("Y") + ? s.has("BLUR") + ? s.has("SPREAD") || ((n.spread = o), s.add("SPREAD")) + : ((n.blur = o), s.add("BLUR")) + : ((n.y = o), s.add("Y")) + : ((n.x = o), s.add("X")) + : n.color + ? (n.unknown || (n.unknown = []), n.unknown.push(o)) + : (n.color = o)); + return ((n.valid = n.x !== void 0 && n.y !== void 0), n); + }); + } + function Lu(r) { + return r + .map((e) => (e.valid ? [e.keyword, e.x, e.y, e.blur, e.spread, e.color].filter(Boolean).join(" ") : e.raw)) + .join(", "); + } + var Wb, + Gb, + Fu, + cs = C(() => { + l(); + _t(); + ((Wb = new Set(["inset", "inherit", "initial", "revert", "unset"])), + (Gb = /\ +(?![^(]*\))/g), + (Fu = /^-?(\d+|\.\d+)(.*?)$/g)); + }); + function ps(r) { + return Hb.some((e) => new RegExp(`^${e}\\(.*\\)`).test(r)); + } + function L(r, e = null, t = !0) { + let i = e && Yb.has(e.property); + return r.startsWith("--") && !i + ? `var(${r})` + : r.includes("url(") + ? r + .split(/(url\(.*?\))/g) + .filter(Boolean) + .map((n) => (/^url\(.*?\)$/.test(n) ? n : L(n, e, !1))) + .join("") + : ((r = r + .replace(/([^\\])_+/g, (n, a) => a + " ".repeat(n.length - 1)) + .replace(/^_/g, " ") + .replace(/\\_/g, "_")), + t && (r = r.trim()), + (r = Qb(r)), + r); + } + function Qb(r) { + let e = ["theme"], + t = [ + "min-content", + "max-content", + "fit-content", + "safe-area-inset-top", + "safe-area-inset-right", + "safe-area-inset-bottom", + "safe-area-inset-left", + "titlebar-area-x", + "titlebar-area-y", + "titlebar-area-width", + "titlebar-area-height", + "keyboard-inset-top", + "keyboard-inset-right", + "keyboard-inset-bottom", + "keyboard-inset-left", + "keyboard-inset-width", + "keyboard-inset-height", + "radial-gradient", + "linear-gradient", + "conic-gradient", + "repeating-radial-gradient", + "repeating-linear-gradient", + "repeating-conic-gradient", + ]; + return r.replace(/(calc|min|max|clamp)\(.+\)/g, (i) => { + let n = ""; + function a() { + let s = n.trimEnd(); + return s[s.length - 1]; + } + for (let s = 0; s < i.length; s++) { + let o = function (f) { + return f.split("").every((d, p) => i[s + p] === d); + }, + u = function (f) { + let d = 1 / 0; + for (let m of f) { + let b = i.indexOf(m, s); + b !== -1 && b < d && (d = b); + } + let p = i.slice(s, d); + return ((s += p.length - 1), p); + }, + c = i[s]; + if (o("var")) n += u([")", ","]); + else if (t.some((f) => o(f))) { + let f = t.find((d) => o(d)); + ((n += f), (s += f.length - 1)); + } else + e.some((f) => o(f)) + ? (n += u([")"])) + : o("[") + ? (n += u(["]"])) + : ["+", "-", "*", "/"].includes(c) && !["(", "+", "-", "*", "/", ","].includes(a()) + ? (n += ` ${c} `) + : (n += c); + } + return n.replace(/\s+/g, " "); + }); + } + function ds(r) { + return r.startsWith("url("); + } + function hs(r) { + return !isNaN(Number(r)) || ps(r); + } + function cr(r) { + return (r.endsWith("%") && hs(r.slice(0, -1))) || ps(r); + } + function pr(r) { + return r === "0" || new RegExp(`^[+-]?[0-9]*.?[0-9]+(?:[eE][+-]?[0-9]+)?${Xb}$`).test(r) || ps(r); + } + function Nu(r) { + return Kb.has(r); + } + function $u(r) { + let e = xi(L(r)); + for (let t of e) if (!t.valid) return !1; + return !0; + } + function zu(r) { + let e = 0; + return ae(r, "_").every( + (i) => ((i = L(i)), i.startsWith("var(") ? !0 : ur(i, { loose: !0 }) !== null ? (e++, !0) : !1) + ) + ? e > 0 + : !1; + } + function ju(r) { + let e = 0; + return ae(r, ",").every( + (i) => ( + (i = L(i)), + i.startsWith("var(") + ? !0 + : ds(i) || e0(i) || ["element(", "image(", "cross-fade(", "image-set("].some((n) => i.startsWith(n)) + ? (e++, !0) + : !1 + ) + ) + ? e > 0 + : !1; + } + function e0(r) { + r = L(r); + for (let e of Zb) if (r.startsWith(`${e}(`)) return !0; + return !1; + } + function Vu(r) { + let e = 0; + return ae(r, "_").every( + (i) => ((i = L(i)), i.startsWith("var(") ? !0 : t0.has(i) || pr(i) || cr(i) ? (e++, !0) : !1) + ) + ? e > 0 + : !1; + } + function Uu(r) { + let e = 0; + return ae(r, ",").every( + (i) => ( + (i = L(i)), + i.startsWith("var(") + ? !0 + : (i.includes(" ") && !/(['"])([^"']+)\1/g.test(i)) || /^\d/g.test(i) + ? !1 + : (e++, !0) + ) + ) + ? e > 0 + : !1; + } + function Wu(r) { + return r0.has(r); + } + function Gu(r) { + return i0.has(r); + } + function Hu(r) { + return n0.has(r); + } + var Hb, + Yb, + Jb, + Xb, + Kb, + Zb, + t0, + r0, + i0, + n0, + dr = C(() => { + l(); + fs(); + cs(); + _t(); + Hb = ["min", "max", "clamp", "calc"]; + Yb = new Set([ + "scroll-timeline-name", + "timeline-scope", + "view-timeline-name", + "font-palette", + "scroll-timeline", + "animation-timeline", + "view-timeline", + ]); + ((Jb = [ + "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", + ]), + (Xb = `(?:${Jb.join("|")})`)); + Kb = new Set(["thin", "medium", "thick"]); + Zb = new Set([ + "conic-gradient", + "linear-gradient", + "radial-gradient", + "repeating-conic-gradient", + "repeating-linear-gradient", + "repeating-radial-gradient", + ]); + t0 = new Set(["center", "top", "right", "bottom", "left"]); + r0 = new Set([ + "serif", + "sans-serif", + "monospace", + "cursive", + "fantasy", + "system-ui", + "ui-serif", + "ui-sans-serif", + "ui-monospace", + "ui-rounded", + "math", + "emoji", + "fangsong", + ]); + i0 = new Set(["xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "xxx-large"]); + n0 = new Set(["larger", "smaller"]); + }); + function Yu(r) { + let e = ["cover", "contain"]; + return ae(r, ",").every((t) => { + let i = ae(t, "_").filter(Boolean); + return i.length === 1 && e.includes(i[0]) + ? !0 + : i.length !== 1 && i.length !== 2 + ? !1 + : i.every((n) => pr(n) || cr(n) || n === "auto"); + }); + } + var Qu = C(() => { + l(); + dr(); + _t(); + }); + function Ju(r, e) { + r.walkClasses((t) => { + ((t.value = e(t.value)), t.raws && t.raws.value && (t.raws.value = wt(t.raws.value))); + }); + } + function Xu(r, e) { + if (!it(r)) return; + let t = r.slice(1, -1); + if (!!e(t)) return L(t); + } + function s0(r, e = {}, t) { + let i = e[r]; + if (i !== void 0) return Ke(i); + if (it(r)) { + let n = Xu(r, t); + return n === void 0 ? void 0 : Ke(n); + } + } + function ki(r, e = {}, { validate: t = () => !0 } = {}) { + let i = e.values?.[r]; + return i !== void 0 + ? i + : e.supportsNegativeValues && r.startsWith("-") + ? s0(r.slice(1), e.values, t) + : Xu(r, t); + } + function it(r) { + return r.startsWith("[") && r.endsWith("]"); + } + function Ku(r) { + let e = r.lastIndexOf("/"), + t = r.lastIndexOf("[", e), + i = r.indexOf("]", e); + return ( + r[e - 1] === "]" || + r[e + 1] === "[" || + (t !== -1 && i !== -1 && t < e && e < i && (e = r.lastIndexOf("/", t))), + e === -1 || e === r.length - 1 + ? [r, void 0] + : it(r) && !r.includes("]/[") + ? [r, void 0] + : [r.slice(0, e), r.slice(e + 1)] + ); + } + function Ot(r) { + if (typeof r == "string" && r.includes("")) { + let e = r; + return ({ opacityValue: t = 1 }) => e.replace("", t); + } + return r; + } + function Zu(r) { + return L(r.slice(1, -1)); + } + function a0(r, e = {}, { tailwindConfig: t = {} } = {}) { + if (e.values?.[r] !== void 0) return Ot(e.values?.[r]); + let [i, n] = Ku(r); + if (n !== void 0) { + let a = e.values?.[i] ?? (it(i) ? i.slice(1, -1) : void 0); + return a === void 0 + ? void 0 + : ((a = Ot(a)), + it(n) ? Ie(a, Zu(n)) : t.theme?.opacity?.[n] === void 0 ? void 0 : Ie(a, t.theme.opacity[n])); + } + return ki(r, e, { validate: zu }); + } + function o0(r, e = {}) { + return e.values?.[r]; + } + function me(r) { + return (e, t) => ki(e, t, { validate: r }); + } + function l0(r, e) { + let t = r.indexOf(e); + return t === -1 ? [void 0, r] : [r.slice(0, t), r.slice(t + 1)]; + } + function gs(r, e, t, i) { + if (t.values && e in t.values) + for (let { type: a } of r ?? []) { + let s = ms[a](e, t, { tailwindConfig: i }); + if (s !== void 0) return [s, a, null]; + } + if (it(e)) { + let a = e.slice(1, -1), + [s, o] = l0(a, ":"); + if (!/^[\w-_]+$/g.test(s)) o = a; + else if (s !== void 0 && !ef.includes(s)) return []; + if (o.length > 0 && ef.includes(s)) return [ki(`[${o}]`, t), s, null]; + } + let n = ys(r, e, t, i); + for (let a of n) return a; + return []; + } + function* ys(r, e, t, i) { + let n = K(i, "generalizedModifiers"), + [a, s] = Ku(e); + if ( + ((n && + t.modifiers != null && + (t.modifiers === "any" || (typeof t.modifiers == "object" && ((s && it(s)) || s in t.modifiers)))) || + ((a = e), (s = void 0)), + s !== void 0 && a === "" && (a = "DEFAULT"), + s !== void 0 && typeof t.modifiers == "object") + ) { + let u = t.modifiers?.[s] ?? null; + u !== null ? (s = u) : it(s) && (s = Zu(s)); + } + for (let { type: u } of r ?? []) { + let c = ms[u](a, t, { tailwindConfig: i }); + c !== void 0 && (yield [c, u, s ?? null]); + } + } + var ms, + ef, + hr = C(() => { + l(); + bi(); + fr(); + dr(); + di(); + Qu(); + je(); + ((ms = { + any: ki, + color: a0, + url: me(ds), + image: me(ju), + length: me(pr), + percentage: me(cr), + position: me(Vu), + lookup: o0, + "generic-name": me(Wu), + "family-name": me(Uu), + number: me(hs), + "line-width": me(Nu), + "absolute-size": me(Gu), + "relative-size": me(Hu), + shadow: me($u), + size: me(Yu), + }), + (ef = Object.keys(ms))); + }); + function N(r) { + return typeof r == "function" ? r({}) : r; + } + var ws = C(() => { + l(); + }); + function Et(r) { + return typeof r == "function"; + } + function mr(r, ...e) { + let t = e.pop(); + for (let i of e) + for (let n in i) { + let a = t(r[n], i[n]); + a === void 0 ? (ie(r[n]) && ie(i[n]) ? (r[n] = mr({}, r[n], i[n], t)) : (r[n] = i[n])) : (r[n] = a); + } + return r; + } + function u0(r, ...e) { + return Et(r) ? r(...e) : r; + } + function f0(r) { + return r.reduce( + (e, { extend: t }) => mr(e, t, (i, n) => (i === void 0 ? [n] : Array.isArray(i) ? [n, ...i] : [n, i])), + {} + ); + } + function c0(r) { + return { ...r.reduce((e, t) => os(e, t), {}), extend: f0(r) }; + } + function tf(r, e) { + if (Array.isArray(r) && ie(r[0])) return r.concat(e); + if (Array.isArray(e) && ie(e[0]) && ie(r)) return [r, ...e]; + if (Array.isArray(e)) return e; + } + function p0({ extend: r, ...e }) { + return mr(e, r, (t, i) => + !Et(t) && !i.some(Et) ? mr({}, t, ...i, tf) : (n, a) => mr({}, ...[t, ...i].map((s) => u0(s, n, a)), tf) + ); + } + function* d0(r) { + let e = Ze(r); + if (e.length === 0 || (yield e, Array.isArray(r))) return; + let t = /^(.*?)\s*\/\s*([^/]+)$/, + i = r.match(t); + if (i !== null) { + let [, n, a] = i, + s = Ze(n); + ((s.alpha = a), yield s); + } + } + function h0(r) { + let e = (t, i) => { + for (let n of d0(t)) { + let a = 0, + s = r; + for (; s != null && a < n.length; ) + ((s = s[n[a++]]), (s = Et(s) && (n.alpha === void 0 || a <= n.length - 1) ? s(e, bs) : s)); + if (s !== void 0) { + if (n.alpha !== void 0) { + let o = Ot(s); + return Ie(o, n.alpha, N(o)); + } + return ie(s) ? et(s) : s; + } + } + return i; + }; + return ( + Object.assign(e, { theme: e, ...bs }), + Object.keys(r).reduce((t, i) => ((t[i] = Et(r[i]) ? r[i](e, bs) : r[i]), t), {}) + ); + } + function rf(r) { + let e = []; + return ( + r.forEach((t) => { + e = [...e, t]; + let i = t?.plugins ?? []; + i.length !== 0 && + i.forEach((n) => { + (n.__isOptionsFunction && (n = n()), (e = [...e, ...rf([n?.config ?? {}])])); + }); + }), + e + ); + } + function m0(r) { + return [...r].reduceRight((t, i) => (Et(i) ? i({ corePlugins: t }) : Au(i, t)), Su); + } + function g0(r) { + return [...r].reduceRight((t, i) => [...t, ...i], []); + } + function vs(r) { + let e = [...rf(r), { prefix: "", important: !1, separator: ":" }]; + return qu( + os( + { + theme: h0(p0(c0(e.map((t) => t?.theme ?? {})))), + corePlugins: m0(e.map((t) => t.corePlugins)), + plugins: g0(r.map((t) => t?.plugins ?? [])), + }, + ...e + ) + ); + } + var bs, + nf = C(() => { + l(); + di(); + Cu(); + _u(); + mi(); + Tu(); + gi(); + Ru(); + At(); + wi(); + hr(); + fr(); + ws(); + bs = { + colors: ss, + negative(r) { + return Object.keys(r) + .filter((e) => r[e] !== "0") + .reduce((e, t) => { + let i = Ke(r[t]); + return (i !== void 0 && (e[`-${t}`] = i), e); + }, {}); + }, + breakpoints(r) { + return Object.keys(r) + .filter((e) => typeof r[e] == "string") + .reduce((e, t) => ({ ...e, [`screen-${t}`]: r[t] }), {}); + }, + }; + }); + var Si = v((i3, sf) => { + l(); + sf.exports = { + content: [], + presets: [], + darkMode: "media", + theme: { + accentColor: ({ theme: r }) => ({ ...r("colors"), auto: "auto" }), + 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" }, + backdropBlur: ({ theme: r }) => r("blur"), + backdropBrightness: ({ theme: r }) => r("brightness"), + backdropContrast: ({ theme: r }) => r("contrast"), + backdropGrayscale: ({ theme: r }) => r("grayscale"), + backdropHueRotate: ({ theme: r }) => r("hueRotate"), + backdropInvert: ({ theme: r }) => r("invert"), + backdropOpacity: ({ theme: r }) => r("opacity"), + backdropSaturate: ({ theme: r }) => r("saturate"), + backdropSepia: ({ theme: r }) => r("sepia"), + backgroundColor: ({ theme: r }) => r("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: r }) => r("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: "0", + sm: "4px", + DEFAULT: "8px", + md: "12px", + lg: "16px", + xl: "24px", + "2xl": "40px", + "3xl": "64px", + }, + borderColor: ({ theme: r }) => ({ ...r("colors"), DEFAULT: r("colors.gray.200", "currentColor") }), + borderOpacity: ({ theme: r }) => r("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: r }) => ({ ...r("spacing") }), + borderWidth: { DEFAULT: "1px", 0: "0px", 2: "2px", 4: "4px", 8: "8px" }, + 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: r }) => r("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", + }, + caretColor: ({ theme: r }) => r("colors"), + colors: ({ colors: r }) => ({ + inherit: r.inherit, + current: r.current, + transparent: r.transparent, + black: r.black, + white: r.white, + slate: r.slate, + gray: r.gray, + zinc: r.zinc, + neutral: r.neutral, + stone: r.stone, + red: r.red, + orange: r.orange, + amber: r.amber, + yellow: r.yellow, + lime: r.lime, + green: r.green, + emerald: r.emerald, + teal: r.teal, + cyan: r.cyan, + sky: r.sky, + blue: r.blue, + indigo: r.indigo, + violet: r.violet, + purple: r.purple, + fuchsia: r.fuchsia, + pink: r.pink, + rose: r.rose, + }), + 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", + }, + container: {}, + content: { none: "none" }, + contrast: { 0: "0", 50: ".5", 75: ".75", 100: "1", 125: "1.25", 150: "1.5", 200: "2" }, + 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: r }) => r("borderColor"), + divideOpacity: ({ theme: r }) => r("borderOpacity"), + divideWidth: ({ theme: r }) => r("borderWidth"), + 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: r }) => ({ none: "none", ...r("colors") }), + flex: { 1: "1 1 0%", auto: "1 1 auto", initial: "0 1 auto", none: "none" }, + flexBasis: ({ theme: r }) => ({ + auto: "auto", + ...r("spacing"), + "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%", + }), + flexGrow: { 0: "0", DEFAULT: "1" }, + flexShrink: { 0: "0", DEFAULT: "1" }, + 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: r }) => r("spacing"), + gradientColorStops: ({ theme: r }) => r("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%", + }, + grayscale: { 0: "0", DEFAULT: "100%" }, + 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", + }, + 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", + }, + 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", + }, + 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", + }, + 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))", + }, + 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))", + }, + height: ({ theme: r }) => ({ + auto: "auto", + ...r("spacing"), + "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", + }), + hueRotate: { 0: "0deg", 15: "15deg", 30: "30deg", 60: "60deg", 90: "90deg", 180: "180deg" }, + inset: ({ theme: r }) => ({ + auto: "auto", + ...r("spacing"), + "1/2": "50%", + "1/3": "33.333333%", + "2/3": "66.666667%", + "1/4": "25%", + "2/4": "50%", + "3/4": "75%", + full: "100%", + }), + invert: { 0: "0", DEFAULT: "100%" }, + 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: r }) => ({ auto: "auto", ...r("spacing") }), + lineClamp: { 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6" }, + maxHeight: ({ theme: r }) => ({ + ...r("spacing"), + none: "none", + full: "100%", + screen: "100vh", + svh: "100svh", + lvh: "100lvh", + dvh: "100dvh", + min: "min-content", + max: "max-content", + fit: "fit-content", + }), + maxWidth: ({ theme: r, breakpoints: e }) => ({ + ...r("spacing"), + 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(r("screens")), + }), + minHeight: ({ theme: r }) => ({ + ...r("spacing"), + full: "100%", + screen: "100vh", + svh: "100svh", + lvh: "100lvh", + dvh: "100dvh", + min: "min-content", + max: "max-content", + fit: "fit-content", + }), + minWidth: ({ theme: r }) => ({ + ...r("spacing"), + full: "100%", + min: "min-content", + max: "max-content", + fit: "fit-content", + }), + 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", + }, + 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", + }, + outlineColor: ({ theme: r }) => r("colors"), + outlineOffset: { 0: "0px", 1: "1px", 2: "2px", 4: "4px", 8: "8px" }, + outlineWidth: { 0: "0px", 1: "1px", 2: "2px", 4: "4px", 8: "8px" }, + padding: ({ theme: r }) => r("spacing"), + placeholderColor: ({ theme: r }) => r("colors"), + placeholderOpacity: ({ theme: r }) => r("opacity"), + ringColor: ({ theme: r }) => ({ DEFAULT: r("colors.blue.500", "#3b82f6"), ...r("colors") }), + ringOffsetColor: ({ theme: r }) => r("colors"), + ringOffsetWidth: { 0: "0px", 1: "1px", 2: "2px", 4: "4px", 8: "8px" }, + ringOpacity: ({ theme: r }) => ({ DEFAULT: "0.5", ...r("opacity") }), + ringWidth: { DEFAULT: "3px", 0: "0px", 1: "1px", 2: "2px", 4: "4px", 8: "8px" }, + rotate: { + 0: "0deg", + 1: "1deg", + 2: "2deg", + 3: "3deg", + 6: "6deg", + 12: "12deg", + 45: "45deg", + 90: "90deg", + 180: "180deg", + }, + saturate: { 0: "0", 50: ".5", 100: "1", 150: "1.5", 200: "2" }, + 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", + }, + screens: { sm: "640px", md: "768px", lg: "1024px", xl: "1280px", "2xl": "1536px" }, + scrollMargin: ({ theme: r }) => ({ ...r("spacing") }), + scrollPadding: ({ theme: r }) => r("spacing"), + sepia: { 0: "0", DEFAULT: "100%" }, + skew: { 0: "0deg", 1: "1deg", 2: "2deg", 3: "3deg", 6: "6deg", 12: "12deg" }, + space: ({ theme: r }) => ({ ...r("spacing") }), + spacing: { + px: "1px", + 0: "0px", + 0.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: r }) => ({ none: "none", ...r("colors") }), + strokeWidth: { 0: "0", 1: "1", 2: "2" }, + supports: {}, + data: {}, + textColor: ({ theme: r }) => r("colors"), + textDecorationColor: ({ theme: r }) => r("colors"), + textDecorationThickness: { + auto: "auto", + "from-font": "from-font", + 0: "0px", + 1: "1px", + 2: "2px", + 4: "4px", + 8: "8px", + }, + textIndent: ({ theme: r }) => ({ ...r("spacing") }), + textOpacity: ({ theme: r }) => r("opacity"), + textUnderlineOffset: { auto: "auto", 0: "0px", 1: "1px", 2: "2px", 4: "4px", 8: "8px" }, + 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", + }, + transitionDuration: { + DEFAULT: "150ms", + 0: "0s", + 75: "75ms", + 100: "100ms", + 150: "150ms", + 200: "200ms", + 300: "300ms", + 500: "500ms", + 700: "700ms", + 1e3: "1000ms", + }, + transitionProperty: { + none: "none", + all: "all", + DEFAULT: + "color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter", + colors: "color, background-color, border-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: r }) => ({ + ...r("spacing"), + "1/2": "50%", + "1/3": "33.333333%", + "2/3": "66.666667%", + "1/4": "25%", + "2/4": "50%", + "3/4": "75%", + full: "100%", + }), + size: ({ theme: r }) => ({ + auto: "auto", + ...r("spacing"), + "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", + }), + width: ({ theme: r }) => ({ + auto: "auto", + ...r("spacing"), + "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", + }), + 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" }, + }, + plugins: [], + }; + }); + function Ci(r) { + let e = (r?.presets ?? [af.default]) + .slice() + .reverse() + .flatMap((n) => Ci(n instanceof Function ? n() : n)), + t = { + respectDefaultRingColorOpacity: { + theme: { ringColor: ({ theme: n }) => ({ DEFAULT: "#3b82f67f", ...n("colors") }) }, + }, + disableColorOpacityUtilitiesByDefault: { + corePlugins: { + backgroundOpacity: !1, + borderOpacity: !1, + divideOpacity: !1, + placeholderOpacity: !1, + ringOpacity: !1, + textOpacity: !1, + }, + }, + }, + i = Object.keys(t) + .filter((n) => K(r, n)) + .map((n) => t[n]); + return [r, ...i, ...e]; + } + var af, + of = C(() => { + l(); + af = X(Si()); + je(); + }); + var lf = {}; + Ae(lf, { default: () => gr }); + function gr(...r) { + let [, ...e] = Ci(r[0]); + return vs([...r, ...e]); + } + var xs = C(() => { + l(); + nf(); + of(); + }); + var uf = {}; + Ae(uf, { default: () => Z }); + var Z, + bt = C(() => { + l(); + Z = { resolve: (r) => r, extname: (r) => "." + r.split(".").pop() }; + }); + function Ai(r) { + return typeof r == "object" && r !== null; + } + function w0(r) { + return Object.keys(r).length === 0; + } + function ff(r) { + return typeof r == "string" || r instanceof String; + } + function ks(r) { + return Ai(r) && r.config === void 0 && !w0(r) + ? null + : Ai(r) && r.config !== void 0 && ff(r.config) + ? Z.resolve(r.config) + : Ai(r) && r.config !== void 0 && Ai(r.config) + ? null + : ff(r) + ? Z.resolve(r) + : b0(); + } + function b0() { + for (let r of y0) + try { + let e = Z.resolve(r); + return (te.accessSync(e), e); + } catch (e) {} + return null; + } + var y0, + cf = C(() => { + l(); + ze(); + bt(); + y0 = ["./tailwind.config.js", "./tailwind.config.cjs", "./tailwind.config.mjs", "./tailwind.config.ts"]; + }); + var pf = {}; + Ae(pf, { default: () => Ss }); + var Ss, + Cs = C(() => { + l(); + Ss = { parse: (r) => ({ href: r }) }; + }); + var As = v(() => { + l(); + }); + var _i = v((d3, mf) => { + l(); + ("use strict"); + var df = (hi(), Ou), + hf = As(), + Tt = class extends Error { + constructor(e, t, i, n, a, s) { + super(e); + ((this.name = "CssSyntaxError"), + (this.reason = e), + a && (this.file = a), + n && (this.source = n), + s && (this.plugin = s), + typeof t != "undefined" && + typeof i != "undefined" && + (typeof t == "number" + ? ((this.line = t), (this.column = i)) + : ((this.line = t.line), + (this.column = t.column), + (this.endLine = i.line), + (this.endColumn = i.column))), + this.setMessage(), + Error.captureStackTrace && Error.captureStackTrace(this, Tt)); + } + setMessage() { + ((this.message = this.plugin ? this.plugin + ": " : ""), + (this.message += this.file ? this.file : ""), + typeof this.line != "undefined" && (this.message += ":" + this.line + ":" + this.column), + (this.message += ": " + this.reason)); + } + showSourceCode(e) { + if (!this.source) return ""; + let t = this.source; + (e == null && (e = df.isColorSupported), hf && e && (t = hf(t))); + let i = t.split(/\r?\n/), + n = Math.max(this.line - 3, 0), + a = Math.min(this.line + 2, i.length), + s = String(a).length, + o, + u; + if (e) { + let { bold: c, red: f, gray: d } = df.createColors(!0); + ((o = (p) => c(f(p))), (u = (p) => d(p))); + } else o = u = (c) => c; + return i.slice(n, a).map((c, f) => { + let d = n + 1 + f, + p = " " + (" " + d).slice(-s) + " | "; + if (d === this.line) { + let m = u(p.replace(/\d/g, " ")) + c.slice(0, this.column - 1).replace(/[^\t]/g, " "); + return ( + o(">") + + u(p) + + c + + ` + ` + + m + + o("^") + ); + } + return " " + u(p) + c; + }).join(` +`); + } + toString() { + let e = this.showSourceCode(); + return ( + e && + (e = + ` -`+e+` -`),this.name+": "+this.message+e}};mf.exports=Tt;Tt.default=Tt});var Oi=v((h3,_s)=>{l();"use strict";_s.exports.isClean=Symbol("isClean");_s.exports.my=Symbol("my")});var Os=v((m3,yf)=>{l();"use strict";var gf={colon:": ",indent:" ",beforeDecl:` -`,beforeRule:` -`,beforeOpen:" ",beforeClose:` -`,beforeComment:` -`,after:` -`,emptyBody:"",commentLeft:" ",commentRight:" ",semicolon:!1};function v0(r){return r[0].toUpperCase()+r.slice(1)}var Ei=class{constructor(e){this.builder=e}stringify(e,t){if(!this[e.type])throw new Error("Unknown AST node type "+e.type+". Maybe you need to change PostCSS stringifier.");this[e.type](e,t)}document(e){this.body(e)}root(e){this.body(e),e.raws.after&&this.builder(e.raws.after)}comment(e){let t=this.raw(e,"left","commentLeft"),i=this.raw(e,"right","commentRight");this.builder("/*"+t+e.text+i+"*/",e)}decl(e,t){let i=this.raw(e,"between","colon"),n=e.prop+i+this.rawValue(e,"value");e.important&&(n+=e.raws.important||" !important"),t&&(n+=";"),this.builder(n,e)}rule(e){this.block(e,this.rawValue(e,"selector")),e.raws.ownSemicolon&&this.builder(e.raws.ownSemicolon,e,"end")}atrule(e,t){let i="@"+e.name,n=e.params?this.rawValue(e,"params"):"";if(typeof e.raws.afterName!="undefined"?i+=e.raws.afterName:n&&(i+=" "),e.nodes)this.block(e,i+n);else{let a=(e.raws.between||"")+(t?";":"");this.builder(i+n+a,e)}}body(e){let t=e.nodes.length-1;for(;t>0&&e.nodes[t].type==="comment";)t-=1;let i=this.raw(e,"semicolon");for(let n=0;n{if(n=u.raws[t],typeof n!="undefined")return!1})}return typeof n=="undefined"&&(n=gf[i]),s.rawCache[i]=n,n}rawSemicolon(e){let t;return e.walk(i=>{if(i.nodes&&i.nodes.length&&i.last.type==="decl"&&(t=i.raws.semicolon,typeof t!="undefined"))return!1}),t}rawEmptyBody(e){let t;return e.walk(i=>{if(i.nodes&&i.nodes.length===0&&(t=i.raws.after,typeof t!="undefined"))return!1}),t}rawIndent(e){if(e.raws.indent)return e.raws.indent;let t;return e.walk(i=>{let n=i.parent;if(n&&n!==e&&n.parent&&n.parent===e&&typeof i.raws.before!="undefined"){let a=i.raws.before.split(` -`);return t=a[a.length-1],t=t.replace(/\S/g,""),!1}}),t}rawBeforeComment(e,t){let i;return e.walkComments(n=>{if(typeof n.raws.before!="undefined")return i=n.raws.before,i.includes(` -`)&&(i=i.replace(/[^\n]+$/,"")),!1}),typeof i=="undefined"?i=this.raw(t,null,"beforeDecl"):i&&(i=i.replace(/\S/g,"")),i}rawBeforeDecl(e,t){let i;return e.walkDecls(n=>{if(typeof n.raws.before!="undefined")return i=n.raws.before,i.includes(` -`)&&(i=i.replace(/[^\n]+$/,"")),!1}),typeof i=="undefined"?i=this.raw(t,null,"beforeRule"):i&&(i=i.replace(/\S/g,"")),i}rawBeforeRule(e){let t;return e.walk(i=>{if(i.nodes&&(i.parent!==e||e.first!==i)&&typeof i.raws.before!="undefined")return t=i.raws.before,t.includes(` -`)&&(t=t.replace(/[^\n]+$/,"")),!1}),t&&(t=t.replace(/\S/g,"")),t}rawBeforeClose(e){let t;return e.walk(i=>{if(i.nodes&&i.nodes.length>0&&typeof i.raws.after!="undefined")return t=i.raws.after,t.includes(` -`)&&(t=t.replace(/[^\n]+$/,"")),!1}),t&&(t=t.replace(/\S/g,"")),t}rawBeforeOpen(e){let t;return e.walk(i=>{if(i.type!=="decl"&&(t=i.raws.between,typeof t!="undefined"))return!1}),t}rawColon(e){let t;return e.walkDecls(i=>{if(typeof i.raws.between!="undefined")return t=i.raws.between.replace(/[^\s:]/g,""),!1}),t}beforeAfter(e,t){let i;e.type==="decl"?i=this.raw(e,null,"beforeDecl"):e.type==="comment"?i=this.raw(e,null,"beforeComment"):t==="before"?i=this.raw(e,null,"beforeRule"):i=this.raw(e,null,"beforeClose");let n=e.parent,a=0;for(;n&&n.type!=="root";)a+=1,n=n.parent;if(i.includes(` -`)){let s=this.raw(e,null,"indent");if(s.length)for(let o=0;o{l();"use strict";var x0=Os();function Es(r,e){new x0(e).stringify(r)}wf.exports=Es;Es.default=Es});var wr=v((y3,bf)=>{l();"use strict";var{isClean:Ti,my:k0}=Oi(),S0=_i(),C0=Os(),A0=yr();function Ts(r,e){let t=new r.constructor;for(let i in r){if(!Object.prototype.hasOwnProperty.call(r,i)||i==="proxyCache")continue;let n=r[i],a=typeof n;i==="parent"&&a==="object"?e&&(t[i]=e):i==="source"?t[i]=n:Array.isArray(n)?t[i]=n.map(s=>Ts(s,t)):(a==="object"&&n!==null&&(n=Ts(n)),t[i]=n)}return t}var Pi=class{constructor(e={}){this.raws={},this[Ti]=!1,this[k0]=!0;for(let t in e)if(t==="nodes"){this.nodes=[];for(let i of e[t])typeof i.clone=="function"?this.append(i.clone()):this.append(i)}else this[t]=e[t]}error(e,t={}){if(this.source){let{start:i,end:n}=this.rangeBy(t);return this.source.input.error(e,{line:i.line,column:i.column},{line:n.line,column:n.column},t)}return new S0(e)}warn(e,t,i){let n={node:this};for(let a in i)n[a]=i[a];return e.warn(t,n)}remove(){return this.parent&&this.parent.removeChild(this),this.parent=void 0,this}toString(e=A0){e.stringify&&(e=e.stringify);let t="";return e(this,i=>{t+=i}),t}assign(e={}){for(let t in e)this[t]=e[t];return this}clone(e={}){let t=Ts(this);for(let i in e)t[i]=e[i];return t}cloneBefore(e={}){let t=this.clone(e);return this.parent.insertBefore(this,t),t}cloneAfter(e={}){let t=this.clone(e);return this.parent.insertAfter(this,t),t}replaceWith(...e){if(this.parent){let t=this,i=!1;for(let n of e)n===this?i=!0:i?(this.parent.insertAfter(t,n),t=n):this.parent.insertBefore(t,n);i||this.remove()}return this}next(){if(!this.parent)return;let e=this.parent.index(this);return this.parent.nodes[e+1]}prev(){if(!this.parent)return;let e=this.parent.index(this);return this.parent.nodes[e-1]}before(e){return this.parent.insertBefore(this,e),this}after(e){return this.parent.insertAfter(this,e),this}root(){let e=this;for(;e.parent&&e.parent.type!=="document";)e=e.parent;return e}raw(e,t){return new C0().raw(this,e,t)}cleanRaws(e){delete this.raws.before,delete this.raws.after,e||delete this.raws.between}toJSON(e,t){let i={},n=t==null;t=t||new Map;let a=0;for(let s in this){if(!Object.prototype.hasOwnProperty.call(this,s)||s==="parent"||s==="proxyCache")continue;let o=this[s];if(Array.isArray(o))i[s]=o.map(u=>typeof u=="object"&&u.toJSON?u.toJSON(null,t):u);else if(typeof o=="object"&&o.toJSON)i[s]=o.toJSON(null,t);else if(s==="source"){let u=t.get(o.input);u==null&&(u=a,t.set(o.input,a),a++),i[s]={inputId:u,start:o.start,end:o.end}}else i[s]=o}return n&&(i.inputs=[...t.keys()].map(s=>s.toJSON())),i}positionInside(e){let t=this.toString(),i=this.source.start.column,n=this.source.start.line;for(let a=0;ae.root().toProxy():e[t]}}}toProxy(){return this.proxyCache||(this.proxyCache=new Proxy(this,this.getProxyProcessor())),this.proxyCache}addToError(e){if(e.postcssNode=this,e.stack&&this.source&&/\n\s{4}at /.test(e.stack)){let t=this.source;e.stack=e.stack.replace(/\n\s{4}at /,`$&${t.input.from}:${t.start.line}:${t.start.column}$&`)}return e}markDirty(){if(this[Ti]){this[Ti]=!1;let e=this;for(;e=e.parent;)e[Ti]=!1}}get proxyOf(){return this}};bf.exports=Pi;Pi.default=Pi});var br=v((w3,vf)=>{l();"use strict";var _0=wr(),Di=class extends _0{constructor(e){e&&typeof e.value!="undefined"&&typeof e.value!="string"&&(e={...e,value:String(e.value)});super(e);this.type="decl"}get variable(){return this.prop.startsWith("--")||this.prop[0]==="$"}};vf.exports=Di;Di.default=Di});var Ps=v((b3,xf)=>{l();xf.exports=function(r,e){return{generate:()=>{let t="";return r(e,i=>{t+=i}),[t]}}}});var vr=v((v3,kf)=>{l();"use strict";var O0=wr(),Ii=class extends O0{constructor(e){super(e);this.type="comment"}};kf.exports=Ii;Ii.default=Ii});var nt=v((x3,Df)=>{l();"use strict";var{isClean:Sf,my:Cf}=Oi(),Af=br(),_f=vr(),E0=wr(),Of,Ds,Is,Ef;function Tf(r){return r.map(e=>(e.nodes&&(e.nodes=Tf(e.nodes)),delete e.source,e))}function Pf(r){if(r[Sf]=!1,r.proxyOf.nodes)for(let e of r.proxyOf.nodes)Pf(e)}var we=class extends E0{push(e){return e.parent=this,this.proxyOf.nodes.push(e),this}each(e){if(!this.proxyOf.nodes)return;let t=this.getIterator(),i,n;for(;this.indexes[t]{let n;try{n=e(t,i)}catch(a){throw t.addToError(a)}return n!==!1&&t.walk&&(n=t.walk(e)),n})}walkDecls(e,t){return t?e instanceof RegExp?this.walk((i,n)=>{if(i.type==="decl"&&e.test(i.prop))return t(i,n)}):this.walk((i,n)=>{if(i.type==="decl"&&i.prop===e)return t(i,n)}):(t=e,this.walk((i,n)=>{if(i.type==="decl")return t(i,n)}))}walkRules(e,t){return t?e instanceof RegExp?this.walk((i,n)=>{if(i.type==="rule"&&e.test(i.selector))return t(i,n)}):this.walk((i,n)=>{if(i.type==="rule"&&i.selector===e)return t(i,n)}):(t=e,this.walk((i,n)=>{if(i.type==="rule")return t(i,n)}))}walkAtRules(e,t){return t?e instanceof RegExp?this.walk((i,n)=>{if(i.type==="atrule"&&e.test(i.name))return t(i,n)}):this.walk((i,n)=>{if(i.type==="atrule"&&i.name===e)return t(i,n)}):(t=e,this.walk((i,n)=>{if(i.type==="atrule")return t(i,n)}))}walkComments(e){return this.walk((t,i)=>{if(t.type==="comment")return e(t,i)})}append(...e){for(let t of e){let i=this.normalize(t,this.last);for(let n of i)this.proxyOf.nodes.push(n)}return this.markDirty(),this}prepend(...e){e=e.reverse();for(let t of e){let i=this.normalize(t,this.first,"prepend").reverse();for(let n of i)this.proxyOf.nodes.unshift(n);for(let n in this.indexes)this.indexes[n]=this.indexes[n]+i.length}return this.markDirty(),this}cleanRaws(e){if(super.cleanRaws(e),this.nodes)for(let t of this.nodes)t.cleanRaws(e)}insertBefore(e,t){let i=this.index(e),n=i===0?"prepend":!1,a=this.normalize(t,this.proxyOf.nodes[i],n).reverse();i=this.index(e);for(let o of a)this.proxyOf.nodes.splice(i,0,o);let s;for(let o in this.indexes)s=this.indexes[o],i<=s&&(this.indexes[o]=s+a.length);return this.markDirty(),this}insertAfter(e,t){let i=this.index(e),n=this.normalize(t,this.proxyOf.nodes[i]).reverse();i=this.index(e);for(let s of n)this.proxyOf.nodes.splice(i+1,0,s);let a;for(let s in this.indexes)a=this.indexes[s],i=e&&(this.indexes[i]=t-1);return this.markDirty(),this}removeAll(){for(let e of this.proxyOf.nodes)e.parent=void 0;return this.proxyOf.nodes=[],this.markDirty(),this}replaceValues(e,t,i){return i||(i=t,t={}),this.walkDecls(n=>{t.props&&!t.props.includes(n.prop)||t.fast&&!n.value.includes(t.fast)||(n.value=n.value.replace(e,i))}),this.markDirty(),this}every(e){return this.nodes.every(e)}some(e){return this.nodes.some(e)}index(e){return typeof e=="number"?e:(e.proxyOf&&(e=e.proxyOf),this.proxyOf.nodes.indexOf(e))}get first(){if(!!this.proxyOf.nodes)return this.proxyOf.nodes[0]}get last(){if(!!this.proxyOf.nodes)return this.proxyOf.nodes[this.proxyOf.nodes.length-1]}normalize(e,t){if(typeof e=="string")e=Tf(Of(e).nodes);else if(Array.isArray(e)){e=e.slice(0);for(let n of e)n.parent&&n.parent.removeChild(n,"ignore")}else if(e.type==="root"&&this.type!=="document"){e=e.nodes.slice(0);for(let n of e)n.parent&&n.parent.removeChild(n,"ignore")}else if(e.type)e=[e];else if(e.prop){if(typeof e.value=="undefined")throw new Error("Value field is missed in node creation");typeof e.value!="string"&&(e.value=String(e.value)),e=[new Af(e)]}else if(e.selector)e=[new Ds(e)];else if(e.name)e=[new Is(e)];else if(e.text)e=[new _f(e)];else throw new Error("Unknown node type in node creation");return e.map(n=>(n[Cf]||we.rebuild(n),n=n.proxyOf,n.parent&&n.parent.removeChild(n),n[Sf]&&Pf(n),typeof n.raws.before=="undefined"&&t&&typeof t.raws.before!="undefined"&&(n.raws.before=t.raws.before.replace(/\S/g,"")),n.parent=this.proxyOf,n))}getProxyProcessor(){return{set(e,t,i){return e[t]===i||(e[t]=i,(t==="name"||t==="params"||t==="selector")&&e.markDirty()),!0},get(e,t){return t==="proxyOf"?e:e[t]?t==="each"||typeof t=="string"&&t.startsWith("walk")?(...i)=>e[t](...i.map(n=>typeof n=="function"?(a,s)=>n(a.toProxy(),s):n)):t==="every"||t==="some"?i=>e[t]((n,...a)=>i(n.toProxy(),...a)):t==="root"?()=>e.root().toProxy():t==="nodes"?e.nodes.map(i=>i.toProxy()):t==="first"||t==="last"?e[t].toProxy():e[t]:e[t]}}}getIterator(){this.lastEach||(this.lastEach=0),this.indexes||(this.indexes={}),this.lastEach+=1;let e=this.lastEach;return this.indexes[e]=0,e}};we.registerParse=r=>{Of=r};we.registerRule=r=>{Ds=r};we.registerAtRule=r=>{Is=r};we.registerRoot=r=>{Ef=r};Df.exports=we;we.default=we;we.rebuild=r=>{r.type==="atrule"?Object.setPrototypeOf(r,Is.prototype):r.type==="rule"?Object.setPrototypeOf(r,Ds.prototype):r.type==="decl"?Object.setPrototypeOf(r,Af.prototype):r.type==="comment"?Object.setPrototypeOf(r,_f.prototype):r.type==="root"&&Object.setPrototypeOf(r,Ef.prototype),r[Cf]=!0,r.nodes&&r.nodes.forEach(e=>{we.rebuild(e)})}});var qi=v((k3,Rf)=>{l();"use strict";var T0=nt(),If,qf,Pt=class extends T0{constructor(e){super({type:"document",...e});this.nodes||(this.nodes=[])}toResult(e={}){return new If(new qf,this,e).stringify()}};Pt.registerLazyResult=r=>{If=r};Pt.registerProcessor=r=>{qf=r};Rf.exports=Pt;Pt.default=Pt});var qs=v((S3,Bf)=>{l();"use strict";var Mf={};Bf.exports=function(e){Mf[e]||(Mf[e]=!0,typeof console!="undefined"&&console.warn&&console.warn(e))}});var Rs=v((C3,Ff)=>{l();"use strict";var Ri=class{constructor(e,t={}){if(this.type="warning",this.text=e,t.node&&t.node.source){let i=t.node.rangeBy(t);this.line=i.start.line,this.column=i.start.column,this.endLine=i.end.line,this.endColumn=i.end.column}for(let i in t)this[i]=t[i]}toString(){return this.node?this.node.error(this.text,{plugin:this.plugin,index:this.index,word:this.word}).message:this.plugin?this.plugin+": "+this.text:this.text}};Ff.exports=Ri;Ri.default=Ri});var Bi=v((A3,Lf)=>{l();"use strict";var P0=Rs(),Mi=class{constructor(e,t,i){this.processor=e,this.messages=[],this.root=t,this.opts=i,this.css=void 0,this.map=void 0}toString(){return this.css}warn(e,t={}){t.plugin||this.lastPlugin&&this.lastPlugin.postcssPlugin&&(t.plugin=this.lastPlugin.postcssPlugin);let i=new P0(e,t);return this.messages.push(i),i}warnings(){return this.messages.filter(e=>e.type==="warning")}get content(){return this.css}};Lf.exports=Mi;Mi.default=Mi});var Vf=v((_3,jf)=>{l();"use strict";var Ms="'".charCodeAt(0),Nf='"'.charCodeAt(0),Fi="\\".charCodeAt(0),$f="/".charCodeAt(0),Li=` -`.charCodeAt(0),xr=" ".charCodeAt(0),Ni="\f".charCodeAt(0),$i=" ".charCodeAt(0),zi="\r".charCodeAt(0),D0="[".charCodeAt(0),I0="]".charCodeAt(0),q0="(".charCodeAt(0),R0=")".charCodeAt(0),M0="{".charCodeAt(0),B0="}".charCodeAt(0),F0=";".charCodeAt(0),L0="*".charCodeAt(0),N0=":".charCodeAt(0),$0="@".charCodeAt(0),ji=/[\t\n\f\r "#'()/;[\\\]{}]/g,Vi=/[\t\n\f\r !"#'():;@[\\\]{}]|\/(?=\*)/g,z0=/.[\n"'(/\\]/,zf=/[\da-f]/i;jf.exports=function(e,t={}){let i=e.css.valueOf(),n=t.ignoreErrors,a,s,o,u,c,f,d,p,m,b,x=i.length,y=0,w=[],k=[];function S(){return y}function _(R){throw e.error("Unclosed "+R,y)}function E(){return k.length===0&&y>=x}function I(R){if(k.length)return k.pop();if(y>=x)return;let J=R?R.ignoreUnclosed:!1;switch(a=i.charCodeAt(y),a){case Li:case xr:case $i:case zi:case Ni:{s=y;do s+=1,a=i.charCodeAt(s);while(a===xr||a===Li||a===$i||a===zi||a===Ni);b=["space",i.slice(y,s)],y=s-1;break}case D0:case I0:case M0:case B0:case N0:case F0:case R0:{let ue=String.fromCharCode(a);b=[ue,ue,y];break}case q0:{if(p=w.length?w.pop()[1]:"",m=i.charCodeAt(y+1),p==="url"&&m!==Ms&&m!==Nf&&m!==xr&&m!==Li&&m!==$i&&m!==Ni&&m!==zi){s=y;do{if(f=!1,s=i.indexOf(")",s+1),s===-1)if(n||J){s=y;break}else _("bracket");for(d=s;i.charCodeAt(d-1)===Fi;)d-=1,f=!f}while(f);b=["brackets",i.slice(y,s+1),y,s],y=s}else s=i.indexOf(")",y+1),u=i.slice(y,s+1),s===-1||z0.test(u)?b=["(","(",y]:(b=["brackets",u,y,s],y=s);break}case Ms:case Nf:{o=a===Ms?"'":'"',s=y;do{if(f=!1,s=i.indexOf(o,s+1),s===-1)if(n||J){s=y+1;break}else _("string");for(d=s;i.charCodeAt(d-1)===Fi;)d-=1,f=!f}while(f);b=["string",i.slice(y,s+1),y,s],y=s;break}case $0:{ji.lastIndex=y+1,ji.test(i),ji.lastIndex===0?s=i.length-1:s=ji.lastIndex-2,b=["at-word",i.slice(y,s+1),y,s],y=s;break}case Fi:{for(s=y,c=!0;i.charCodeAt(s+1)===Fi;)s+=1,c=!c;if(a=i.charCodeAt(s+1),c&&a!==$f&&a!==xr&&a!==Li&&a!==$i&&a!==zi&&a!==Ni&&(s+=1,zf.test(i.charAt(s)))){for(;zf.test(i.charAt(s+1));)s+=1;i.charCodeAt(s+1)===xr&&(s+=1)}b=["word",i.slice(y,s+1),y,s],y=s;break}default:{a===$f&&i.charCodeAt(y+1)===L0?(s=i.indexOf("*/",y+2)+1,s===0&&(n||J?s=i.length:_("comment")),b=["comment",i.slice(y,s+1),y,s],y=s):(Vi.lastIndex=y+1,Vi.test(i),Vi.lastIndex===0?s=i.length-1:s=Vi.lastIndex-2,b=["word",i.slice(y,s+1),y,s],w.push(b),y=s);break}}return y++,b}function q(R){k.push(R)}return{back:q,nextToken:I,endOfFile:E,position:S}}});var Ui=v((O3,Wf)=>{l();"use strict";var Uf=nt(),kr=class extends Uf{constructor(e){super(e);this.type="atrule"}append(...e){return this.proxyOf.nodes||(this.nodes=[]),super.append(...e)}prepend(...e){return this.proxyOf.nodes||(this.nodes=[]),super.prepend(...e)}};Wf.exports=kr;kr.default=kr;Uf.registerAtRule(kr)});var Dt=v((E3,Qf)=>{l();"use strict";var Gf=nt(),Hf,Yf,vt=class extends Gf{constructor(e){super(e);this.type="root",this.nodes||(this.nodes=[])}removeChild(e,t){let i=this.index(e);return!t&&i===0&&this.nodes.length>1&&(this.nodes[1].raws.before=this.nodes[i].raws.before),super.removeChild(e)}normalize(e,t,i){let n=super.normalize(e);if(t){if(i==="prepend")this.nodes.length>1?t.raws.before=this.nodes[1].raws.before:delete t.raws.before;else if(this.first!==t)for(let a of n)a.raws.before=t.raws.before}return n}toResult(e={}){return new Hf(new Yf,this,e).stringify()}};vt.registerLazyResult=r=>{Hf=r};vt.registerProcessor=r=>{Yf=r};Qf.exports=vt;vt.default=vt;Gf.registerRoot(vt)});var Bs=v((T3,Jf)=>{l();"use strict";var Sr={split(r,e,t){let i=[],n="",a=!1,s=0,o=!1,u="",c=!1;for(let f of r)c?c=!1:f==="\\"?c=!0:o?f===u&&(o=!1):f==='"'||f==="'"?(o=!0,u=f):f==="("?s+=1:f===")"?s>0&&(s-=1):s===0&&e.includes(f)&&(a=!0),a?(n!==""&&i.push(n.trim()),n="",a=!1):n+=f;return(t||n!=="")&&i.push(n.trim()),i},space(r){let e=[" ",` -`," "];return Sr.split(r,e)},comma(r){return Sr.split(r,[","],!0)}};Jf.exports=Sr;Sr.default=Sr});var Wi=v((P3,Kf)=>{l();"use strict";var Xf=nt(),j0=Bs(),Cr=class extends Xf{constructor(e){super(e);this.type="rule",this.nodes||(this.nodes=[])}get selectors(){return j0.comma(this.selector)}set selectors(e){let t=this.selector?this.selector.match(/,\s*/):null,i=t?t[0]:","+this.raw("between","beforeOpen");this.selector=e.join(i)}};Kf.exports=Cr;Cr.default=Cr;Xf.registerRule(Cr)});var ic=v((D3,rc)=>{l();"use strict";var V0=br(),U0=Vf(),W0=vr(),G0=Ui(),H0=Dt(),Zf=Wi(),ec={empty:!0,space:!0};function Y0(r){for(let e=r.length-1;e>=0;e--){let t=r[e],i=t[3]||t[2];if(i)return i}}var tc=class{constructor(e){this.input=e,this.root=new H0,this.current=this.root,this.spaces="",this.semicolon=!1,this.customProperty=!1,this.createTokenizer(),this.root.source={input:e,start:{offset:0,line:1,column:1}}}createTokenizer(){this.tokenizer=U0(this.input)}parse(){let e;for(;!this.tokenizer.endOfFile();)switch(e=this.tokenizer.nextToken(),e[0]){case"space":this.spaces+=e[1];break;case";":this.freeSemicolon(e);break;case"}":this.end(e);break;case"comment":this.comment(e);break;case"at-word":this.atrule(e);break;case"{":this.emptyRule(e);break;default:this.other(e);break}this.endFile()}comment(e){let t=new W0;this.init(t,e[2]),t.source.end=this.getPosition(e[3]||e[2]);let i=e[1].slice(2,-2);if(/^\s*$/.test(i))t.text="",t.raws.left=i,t.raws.right="";else{let n=i.match(/^(\s*)([^]*\S)(\s*)$/);t.text=n[2],t.raws.left=n[1],t.raws.right=n[3]}}emptyRule(e){let t=new Zf;this.init(t,e[2]),t.selector="",t.raws.between="",this.current=t}other(e){let t=!1,i=null,n=!1,a=null,s=[],o=e[1].startsWith("--"),u=[],c=e;for(;c;){if(i=c[0],u.push(c),i==="("||i==="[")a||(a=c),s.push(i==="("?")":"]");else if(o&&n&&i==="{")a||(a=c),s.push("}");else if(s.length===0)if(i===";")if(n){this.decl(u,o);return}else break;else if(i==="{"){this.rule(u);return}else if(i==="}"){this.tokenizer.back(u.pop()),t=!0;break}else i===":"&&(n=!0);else i===s[s.length-1]&&(s.pop(),s.length===0&&(a=null));c=this.tokenizer.nextToken()}if(this.tokenizer.endOfFile()&&(t=!0),s.length>0&&this.unclosedBracket(a),t&&n){if(!o)for(;u.length&&(c=u[u.length-1][0],!(c!=="space"&&c!=="comment"));)this.tokenizer.back(u.pop());this.decl(u,o)}else this.unknownWord(u)}rule(e){e.pop();let t=new Zf;this.init(t,e[0][2]),t.raws.between=this.spacesAndCommentsFromEnd(e),this.raw(t,"selector",e),this.current=t}decl(e,t){let i=new V0;this.init(i,e[0][2]);let n=e[e.length-1];for(n[0]===";"&&(this.semicolon=!0,e.pop()),i.source.end=this.getPosition(n[3]||n[2]||Y0(e));e[0][0]!=="word";)e.length===1&&this.unknownWord(e),i.raws.before+=e.shift()[1];for(i.source.start=this.getPosition(e[0][2]),i.prop="";e.length;){let c=e[0][0];if(c===":"||c==="space"||c==="comment")break;i.prop+=e.shift()[1]}i.raws.between="";let a;for(;e.length;)if(a=e.shift(),a[0]===":"){i.raws.between+=a[1];break}else a[0]==="word"&&/\w/.test(a[1])&&this.unknownWord([a]),i.raws.between+=a[1];(i.prop[0]==="_"||i.prop[0]==="*")&&(i.raws.before+=i.prop[0],i.prop=i.prop.slice(1));let s=[],o;for(;e.length&&(o=e[0][0],!(o!=="space"&&o!=="comment"));)s.push(e.shift());this.precheckMissedSemicolon(e);for(let c=e.length-1;c>=0;c--){if(a=e[c],a[1].toLowerCase()==="!important"){i.important=!0;let f=this.stringFrom(e,c);f=this.spacesFromEnd(e)+f,f!==" !important"&&(i.raws.important=f);break}else if(a[1].toLowerCase()==="important"){let f=e.slice(0),d="";for(let p=c;p>0;p--){let m=f[p][0];if(d.trim().indexOf("!")===0&&m!=="space")break;d=f.pop()[1]+d}d.trim().indexOf("!")===0&&(i.important=!0,i.raws.important=d,e=f)}if(a[0]!=="space"&&a[0]!=="comment")break}e.some(c=>c[0]!=="space"&&c[0]!=="comment")&&(i.raws.between+=s.map(c=>c[1]).join(""),s=[]),this.raw(i,"value",s.concat(e),t),i.value.includes(":")&&!t&&this.checkMissedSemicolon(e)}atrule(e){let t=new G0;t.name=e[1].slice(1),t.name===""&&this.unnamedAtrule(t,e),this.init(t,e[2]);let i,n,a,s=!1,o=!1,u=[],c=[];for(;!this.tokenizer.endOfFile();){if(e=this.tokenizer.nextToken(),i=e[0],i==="("||i==="["?c.push(i==="("?")":"]"):i==="{"&&c.length>0?c.push("}"):i===c[c.length-1]&&c.pop(),c.length===0)if(i===";"){t.source.end=this.getPosition(e[2]),this.semicolon=!0;break}else if(i==="{"){o=!0;break}else if(i==="}"){if(u.length>0){for(a=u.length-1,n=u[a];n&&n[0]==="space";)n=u[--a];n&&(t.source.end=this.getPosition(n[3]||n[2]))}this.end(e);break}else u.push(e);else u.push(e);if(this.tokenizer.endOfFile()){s=!0;break}}t.raws.between=this.spacesAndCommentsFromEnd(u),u.length?(t.raws.afterName=this.spacesAndCommentsFromStart(u),this.raw(t,"params",u),s&&(e=u[u.length-1],t.source.end=this.getPosition(e[3]||e[2]),this.spaces=t.raws.between,t.raws.between="")):(t.raws.afterName="",t.params=""),o&&(t.nodes=[],this.current=t)}end(e){this.current.nodes&&this.current.nodes.length&&(this.current.raws.semicolon=this.semicolon),this.semicolon=!1,this.current.raws.after=(this.current.raws.after||"")+this.spaces,this.spaces="",this.current.parent?(this.current.source.end=this.getPosition(e[2]),this.current=this.current.parent):this.unexpectedClose(e)}endFile(){this.current.parent&&this.unclosedBlock(),this.current.nodes&&this.current.nodes.length&&(this.current.raws.semicolon=this.semicolon),this.current.raws.after=(this.current.raws.after||"")+this.spaces}freeSemicolon(e){if(this.spaces+=e[1],this.current.nodes){let t=this.current.nodes[this.current.nodes.length-1];t&&t.type==="rule"&&!t.raws.ownSemicolon&&(t.raws.ownSemicolon=this.spaces,this.spaces="")}}getPosition(e){let t=this.input.fromOffset(e);return{offset:e,line:t.line,column:t.col}}init(e,t){this.current.push(e),e.source={start:this.getPosition(t),input:this.input},e.raws.before=this.spaces,this.spaces="",e.type!=="comment"&&(this.semicolon=!1)}raw(e,t,i,n){let a,s,o=i.length,u="",c=!0,f,d;for(let p=0;pm+b[1],"");e.raws[t]={value:u,raw:p}}e[t]=u}spacesAndCommentsFromEnd(e){let t,i="";for(;e.length&&(t=e[e.length-1][0],!(t!=="space"&&t!=="comment"));)i=e.pop()[1]+i;return i}spacesAndCommentsFromStart(e){let t,i="";for(;e.length&&(t=e[0][0],!(t!=="space"&&t!=="comment"));)i+=e.shift()[1];return i}spacesFromEnd(e){let t,i="";for(;e.length&&(t=e[e.length-1][0],t==="space");)i=e.pop()[1]+i;return i}stringFrom(e,t){let i="";for(let n=t;n=0&&(n=e[a],!(n[0]!=="space"&&(i+=1,i===2)));a--);throw this.input.error("Missed semicolon",n[0]==="word"?n[3]+1:n[2])}};rc.exports=tc});var nc=v(()=>{l()});var ac=v((R3,sc)=>{l();var Q0="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict",J0=(r,e=21)=>(t=e)=>{let i="",n=t;for(;n--;)i+=r[Math.random()*r.length|0];return i},X0=(r=21)=>{let e="",t=r;for(;t--;)e+=Q0[Math.random()*64|0];return e};sc.exports={nanoid:X0,customAlphabet:J0}});var Fs=v((M3,oc)=>{l();oc.exports={}});var Hi=v((B3,cc)=>{l();"use strict";var{SourceMapConsumer:K0,SourceMapGenerator:Z0}=nc(),{fileURLToPath:lc,pathToFileURL:Gi}=(Cs(),pf),{resolve:Ls,isAbsolute:Ns}=(bt(),uf),{nanoid:ev}=ac(),$s=As(),uc=_i(),tv=Fs(),zs=Symbol("fromOffsetCache"),rv=Boolean(K0&&Z0),fc=Boolean(Ls&&Ns),Ar=class{constructor(e,t={}){if(e===null||typeof e=="undefined"||typeof e=="object"&&!e.toString)throw new Error(`PostCSS received ${e} instead of CSS string`);if(this.css=e.toString(),this.css[0]==="\uFEFF"||this.css[0]==="\uFFFE"?(this.hasBOM=!0,this.css=this.css.slice(1)):this.hasBOM=!1,t.from&&(!fc||/^\w+:\/\//.test(t.from)||Ns(t.from)?this.file=t.from:this.file=Ls(t.from)),fc&&rv){let i=new tv(this.css,t);if(i.text){this.map=i;let n=i.consumer().file;!this.file&&n&&(this.file=this.mapResolve(n))}}this.file||(this.id=""),this.map&&(this.map.file=this.from)}fromOffset(e){let t,i;if(this[zs])i=this[zs];else{let a=this.css.split(` -`);i=new Array(a.length);let s=0;for(let o=0,u=a.length;o=t)n=i.length-1;else{let a=i.length-2,s;for(;n>1),e=i[s+1])n=s+1;else{n=s;break}}return{line:n+1,col:e-i[n]+1}}error(e,t,i,n={}){let a,s,o;if(t&&typeof t=="object"){let c=t,f=i;if(typeof c.offset=="number"){let d=this.fromOffset(c.offset);t=d.line,i=d.col}else t=c.line,i=c.column;if(typeof f.offset=="number"){let d=this.fromOffset(f.offset);s=d.line,o=d.col}else s=f.line,o=f.column}else if(!i){let c=this.fromOffset(t);t=c.line,i=c.col}let u=this.origin(t,i,s,o);return u?a=new uc(e,u.endLine===void 0?u.line:{line:u.line,column:u.column},u.endLine===void 0?u.column:{line:u.endLine,column:u.endColumn},u.source,u.file,n.plugin):a=new uc(e,s===void 0?t:{line:t,column:i},s===void 0?i:{line:s,column:o},this.css,this.file,n.plugin),a.input={line:t,column:i,endLine:s,endColumn:o,source:this.css},this.file&&(Gi&&(a.input.url=Gi(this.file).toString()),a.input.file=this.file),a}origin(e,t,i,n){if(!this.map)return!1;let a=this.map.consumer(),s=a.originalPositionFor({line:e,column:t});if(!s.source)return!1;let o;typeof i=="number"&&(o=a.originalPositionFor({line:i,column:n}));let u;Ns(s.source)?u=Gi(s.source):u=new URL(s.source,this.map.consumer().sourceRoot||Gi(this.map.mapFile));let c={url:u.toString(),line:s.line,column:s.column,endLine:o&&o.line,endColumn:o&&o.column};if(u.protocol==="file:")if(lc)c.file=lc(u);else throw new Error("file: protocol is not available in this PostCSS build");let f=a.sourceContentFor(s.source);return f&&(c.source=f),c}mapResolve(e){return/^\w+:\/\//.test(e)?e:Ls(this.map.consumer().sourceRoot||this.map.root||".",e)}get from(){return this.file||this.id}toJSON(){let e={};for(let t of["hasBOM","css","file","id"])this[t]!=null&&(e[t]=this[t]);return this.map&&(e.map={...this.map},e.map.consumerCache&&(e.map.consumerCache=void 0)),e}};cc.exports=Ar;Ar.default=Ar;$s&&$s.registerInput&&$s.registerInput(Ar)});var Qi=v((F3,pc)=>{l();"use strict";var iv=nt(),nv=ic(),sv=Hi();function Yi(r,e){let t=new sv(r,e),i=new nv(t);try{i.parse()}catch(n){throw n}return i.root}pc.exports=Yi;Yi.default=Yi;iv.registerParse(Yi)});var Us=v((N3,gc)=>{l();"use strict";var{isClean:qe,my:av}=Oi(),ov=Ps(),lv=yr(),uv=nt(),fv=qi(),L3=qs(),dc=Bi(),cv=Qi(),pv=Dt(),dv={document:"Document",root:"Root",atrule:"AtRule",rule:"Rule",decl:"Declaration",comment:"Comment"},hv={postcssPlugin:!0,prepare:!0,Once:!0,Document:!0,Root:!0,Declaration:!0,Rule:!0,AtRule:!0,Comment:!0,DeclarationExit:!0,RuleExit:!0,AtRuleExit:!0,CommentExit:!0,RootExit:!0,DocumentExit:!0,OnceExit:!0},mv={postcssPlugin:!0,prepare:!0,Once:!0},It=0;function _r(r){return typeof r=="object"&&typeof r.then=="function"}function hc(r){let e=!1,t=dv[r.type];return r.type==="decl"?e=r.prop.toLowerCase():r.type==="atrule"&&(e=r.name.toLowerCase()),e&&r.append?[t,t+"-"+e,It,t+"Exit",t+"Exit-"+e]:e?[t,t+"-"+e,t+"Exit",t+"Exit-"+e]:r.append?[t,It,t+"Exit"]:[t,t+"Exit"]}function mc(r){let e;return r.type==="document"?e=["Document",It,"DocumentExit"]:r.type==="root"?e=["Root",It,"RootExit"]:e=hc(r),{node:r,events:e,eventIndex:0,visitors:[],visitorIndex:0,iterator:0}}function js(r){return r[qe]=!1,r.nodes&&r.nodes.forEach(e=>js(e)),r}var Vs={},Ve=class{constructor(e,t,i){this.stringified=!1,this.processed=!1;let n;if(typeof t=="object"&&t!==null&&(t.type==="root"||t.type==="document"))n=js(t);else if(t instanceof Ve||t instanceof dc)n=js(t.root),t.map&&(typeof i.map=="undefined"&&(i.map={}),i.map.inline||(i.map.inline=!1),i.map.prev=t.map);else{let a=cv;i.syntax&&(a=i.syntax.parse),i.parser&&(a=i.parser),a.parse&&(a=a.parse);try{n=a(t,i)}catch(s){this.processed=!0,this.error=s}n&&!n[av]&&uv.rebuild(n)}this.result=new dc(e,n,i),this.helpers={...Vs,result:this.result,postcss:Vs},this.plugins=this.processor.plugins.map(a=>typeof a=="object"&&a.prepare?{...a,...a.prepare(this.result)}:a)}get[Symbol.toStringTag](){return"LazyResult"}get processor(){return this.result.processor}get opts(){return this.result.opts}get css(){return this.stringify().css}get content(){return this.stringify().content}get map(){return this.stringify().map}get root(){return this.sync().root}get messages(){return this.sync().messages}warnings(){return this.sync().warnings()}toString(){return this.css}then(e,t){return this.async().then(e,t)}catch(e){return this.async().catch(e)}finally(e){return this.async().then(e,e)}async(){return this.error?Promise.reject(this.error):this.processed?Promise.resolve(this.result):(this.processing||(this.processing=this.runAsync()),this.processing)}sync(){if(this.error)throw this.error;if(this.processed)return this.result;if(this.processed=!0,this.processing)throw this.getAsyncError();for(let e of this.plugins){let t=this.runOnRoot(e);if(_r(t))throw this.getAsyncError()}if(this.prepareVisitors(),this.hasListener){let e=this.result.root;for(;!e[qe];)e[qe]=!0,this.walkSync(e);if(this.listeners.OnceExit)if(e.type==="document")for(let t of e.nodes)this.visitSync(this.listeners.OnceExit,t);else this.visitSync(this.listeners.OnceExit,e)}return this.result}stringify(){if(this.error)throw this.error;if(this.stringified)return this.result;this.stringified=!0,this.sync();let e=this.result.opts,t=lv;e.syntax&&(t=e.syntax.stringify),e.stringifier&&(t=e.stringifier),t.stringify&&(t=t.stringify);let n=new ov(t,this.result.root,this.result.opts).generate();return this.result.css=n[0],this.result.map=n[1],this.result}walkSync(e){e[qe]=!0;let t=hc(e);for(let i of t)if(i===It)e.nodes&&e.each(n=>{n[qe]||this.walkSync(n)});else{let n=this.listeners[i];if(n&&this.visitSync(n,e.toProxy()))return}}visitSync(e,t){for(let[i,n]of e){this.result.lastPlugin=i;let a;try{a=n(t,this.helpers)}catch(s){throw this.handleError(s,t.proxyOf)}if(t.type!=="root"&&t.type!=="document"&&!t.parent)return!0;if(_r(a))throw this.getAsyncError()}}runOnRoot(e){this.result.lastPlugin=e;try{if(typeof e=="object"&&e.Once){if(this.result.root.type==="document"){let t=this.result.root.nodes.map(i=>e.Once(i,this.helpers));return _r(t[0])?Promise.all(t):t}return e.Once(this.result.root,this.helpers)}else if(typeof e=="function")return e(this.result.root,this.result)}catch(t){throw this.handleError(t)}}getAsyncError(){throw new Error("Use process(css).then(cb) to work with async plugins")}handleError(e,t){let i=this.result.lastPlugin;try{t&&t.addToError(e),this.error=e,e.name==="CssSyntaxError"&&!e.plugin?(e.plugin=i.postcssPlugin,e.setMessage()):i.postcssVersion}catch(n){console&&console.error&&console.error(n)}return e}async runAsync(){this.plugin=0;for(let e=0;e0;){let i=this.visitTick(t);if(_r(i))try{await i}catch(n){let a=t[t.length-1].node;throw this.handleError(n,a)}}}if(this.listeners.OnceExit)for(let[t,i]of this.listeners.OnceExit){this.result.lastPlugin=t;try{if(e.type==="document"){let n=e.nodes.map(a=>i(a,this.helpers));await Promise.all(n)}else await i(e,this.helpers)}catch(n){throw this.handleError(n)}}}return this.processed=!0,this.stringify()}prepareVisitors(){this.listeners={};let e=(t,i,n)=>{this.listeners[i]||(this.listeners[i]=[]),this.listeners[i].push([t,n])};for(let t of this.plugins)if(typeof t=="object")for(let i in t){if(!hv[i]&&/^[A-Z]/.test(i))throw new Error(`Unknown event ${i} in ${t.postcssPlugin}. Try to update PostCSS (${this.processor.version} now).`);if(!mv[i])if(typeof t[i]=="object")for(let n in t[i])n==="*"?e(t,i,t[i][n]):e(t,i+"-"+n.toLowerCase(),t[i][n]);else typeof t[i]=="function"&&e(t,i,t[i])}this.hasListener=Object.keys(this.listeners).length>0}visitTick(e){let t=e[e.length-1],{node:i,visitors:n}=t;if(i.type!=="root"&&i.type!=="document"&&!i.parent){e.pop();return}if(n.length>0&&t.visitorIndex{Vs=r};gc.exports=Ve;Ve.default=Ve;pv.registerLazyResult(Ve);fv.registerLazyResult(Ve)});var wc=v((z3,yc)=>{l();"use strict";var gv=Ps(),yv=yr(),$3=qs(),wv=Qi(),bv=Bi(),Ji=class{constructor(e,t,i){t=t.toString(),this.stringified=!1,this._processor=e,this._css=t,this._opts=i,this._map=void 0;let n,a=yv;this.result=new bv(this._processor,n,this._opts),this.result.css=t;let s=this;Object.defineProperty(this.result,"root",{get(){return s.root}});let o=new gv(a,n,this._opts,t);if(o.isMap()){let[u,c]=o.generate();u&&(this.result.css=u),c&&(this.result.map=c)}}get[Symbol.toStringTag](){return"NoWorkResult"}get processor(){return this.result.processor}get opts(){return this.result.opts}get css(){return this.result.css}get content(){return this.result.css}get map(){return this.result.map}get root(){if(this._root)return this._root;let e,t=wv;try{e=t(this._css,this._opts)}catch(i){this.error=i}if(this.error)throw this.error;return this._root=e,e}get messages(){return[]}warnings(){return[]}toString(){return this._css}then(e,t){return this.async().then(e,t)}catch(e){return this.async().catch(e)}finally(e){return this.async().then(e,e)}async(){return this.error?Promise.reject(this.error):Promise.resolve(this.result)}sync(){if(this.error)throw this.error;return this.result}};yc.exports=Ji;Ji.default=Ji});var vc=v((j3,bc)=>{l();"use strict";var vv=wc(),xv=Us(),kv=qi(),Sv=Dt(),qt=class{constructor(e=[]){this.version="8.4.24",this.plugins=this.normalize(e)}use(e){return this.plugins=this.plugins.concat(this.normalize([e])),this}process(e,t={}){return this.plugins.length===0&&typeof t.parser=="undefined"&&typeof t.stringifier=="undefined"&&typeof t.syntax=="undefined"?new vv(this,e,t):new xv(this,e,t)}normalize(e){let t=[];for(let i of e)if(i.postcss===!0?i=i():i.postcss&&(i=i.postcss),typeof i=="object"&&Array.isArray(i.plugins))t=t.concat(i.plugins);else if(typeof i=="object"&&i.postcssPlugin)t.push(i);else if(typeof i=="function")t.push(i);else if(!(typeof i=="object"&&(i.parse||i.stringify)))throw new Error(i+" is not a PostCSS plugin");return t}};bc.exports=qt;qt.default=qt;Sv.registerProcessor(qt);kv.registerProcessor(qt)});var kc=v((V3,xc)=>{l();"use strict";var Cv=br(),Av=Fs(),_v=vr(),Ov=Ui(),Ev=Hi(),Tv=Dt(),Pv=Wi();function Or(r,e){if(Array.isArray(r))return r.map(n=>Or(n));let{inputs:t,...i}=r;if(t){e=[];for(let n of t){let a={...n,__proto__:Ev.prototype};a.map&&(a.map={...a.map,__proto__:Av.prototype}),e.push(a)}}if(i.nodes&&(i.nodes=r.nodes.map(n=>Or(n,e))),i.source){let{inputId:n,...a}=i.source;i.source=a,n!=null&&(i.source.input=e[n])}if(i.type==="root")return new Tv(i);if(i.type==="decl")return new Cv(i);if(i.type==="rule")return new Pv(i);if(i.type==="comment")return new _v(i);if(i.type==="atrule")return new Ov(i);throw new Error("Unknown node type: "+r.type)}xc.exports=Or;Or.default=Or});var ge=v((U3,Tc)=>{l();"use strict";var Dv=_i(),Sc=br(),Iv=Us(),qv=nt(),Ws=vc(),Rv=yr(),Mv=kc(),Cc=qi(),Bv=Rs(),Ac=vr(),_c=Ui(),Fv=Bi(),Lv=Hi(),Nv=Qi(),$v=Bs(),Oc=Wi(),Ec=Dt(),zv=wr();function z(...r){return r.length===1&&Array.isArray(r[0])&&(r=r[0]),new Ws(r)}z.plugin=function(e,t){let i=!1;function n(...s){console&&console.warn&&!i&&(i=!0,console.warn(e+`: postcss.plugin was deprecated. Migration guide: -https://evilmartians.com/chronicles/postcss-8-plugin-migration`),h.env.LANG&&h.env.LANG.startsWith("cn")&&console.warn(e+`: \u91CC\u9762 postcss.plugin \u88AB\u5F03\u7528. \u8FC1\u79FB\u6307\u5357: -https://www.w3ctech.com/topic/2226`));let o=t(...s);return o.postcssPlugin=e,o.postcssVersion=new Ws().version,o}let a;return Object.defineProperty(n,"postcss",{get(){return a||(a=n()),a}}),n.process=function(s,o,u){return z([n(u)]).process(s,o)},n};z.stringify=Rv;z.parse=Nv;z.fromJSON=Mv;z.list=$v;z.comment=r=>new Ac(r);z.atRule=r=>new _c(r);z.decl=r=>new Sc(r);z.rule=r=>new Oc(r);z.root=r=>new Ec(r);z.document=r=>new Cc(r);z.CssSyntaxError=Dv;z.Declaration=Sc;z.Container=qv;z.Processor=Ws;z.Document=Cc;z.Comment=Ac;z.Warning=Bv;z.AtRule=_c;z.Result=Fv;z.Input=Lv;z.Rule=Oc;z.Root=Ec;z.Node=zv;Iv.registerPostcss(z);Tc.exports=z;z.default=z});var U,j,W3,G3,H3,Y3,Q3,J3,X3,K3,Z3,eT,tT,rT,iT,nT,sT,aT,oT,lT,uT,fT,cT,pT,dT,hT,st=C(()=>{l();U=X(ge()),j=U.default,W3=U.default.stringify,G3=U.default.fromJSON,H3=U.default.plugin,Y3=U.default.parse,Q3=U.default.list,J3=U.default.document,X3=U.default.comment,K3=U.default.atRule,Z3=U.default.rule,eT=U.default.decl,tT=U.default.root,rT=U.default.CssSyntaxError,iT=U.default.Declaration,nT=U.default.Container,sT=U.default.Processor,aT=U.default.Document,oT=U.default.Comment,lT=U.default.Warning,uT=U.default.AtRule,fT=U.default.Result,cT=U.default.Input,pT=U.default.Rule,dT=U.default.Root,hT=U.default.Node});var Gs=v((gT,Pc)=>{l();Pc.exports=function(r,e,t,i,n){for(e=e.split?e.split("."):e,i=0;i{l();"use strict";Xi.__esModule=!0;Xi.default=Uv;function jv(r){for(var e=r.toLowerCase(),t="",i=!1,n=0;n<6&&e[n]!==void 0;n++){var a=e.charCodeAt(n),s=a>=97&&a<=102||a>=48&&a<=57;if(i=a===32,!s)break;t+=e[n]}if(t.length!==0){var o=parseInt(t,16),u=o>=55296&&o<=57343;return u||o===0||o>1114111?["\uFFFD",t.length+(i?1:0)]:[String.fromCodePoint(o),t.length+(i?1:0)]}}var Vv=/\\/;function Uv(r){var e=Vv.test(r);if(!e)return r;for(var t="",i=0;i{l();"use strict";Zi.__esModule=!0;Zi.default=Wv;function Wv(r){for(var e=arguments.length,t=new Array(e>1?e-1:0),i=1;i0;){var n=t.shift();if(!r[n])return;r=r[n]}return r}Ic.exports=Zi.default});var Mc=v((en,Rc)=>{l();"use strict";en.__esModule=!0;en.default=Gv;function Gv(r){for(var e=arguments.length,t=new Array(e>1?e-1:0),i=1;i0;){var n=t.shift();r[n]||(r[n]={}),r=r[n]}}Rc.exports=en.default});var Fc=v((tn,Bc)=>{l();"use strict";tn.__esModule=!0;tn.default=Hv;function Hv(r){for(var e="",t=r.indexOf("/*"),i=0;t>=0;){e=e+r.slice(i,t);var n=r.indexOf("*/",t+2);if(n<0)return e;i=n+2,t=r.indexOf("/*",i)}return e=e+r.slice(i),e}Bc.exports=tn.default});var Er=v(Re=>{l();"use strict";Re.__esModule=!0;Re.unesc=Re.stripComments=Re.getProp=Re.ensureObject=void 0;var Yv=rn(Ki());Re.unesc=Yv.default;var Qv=rn(qc());Re.getProp=Qv.default;var Jv=rn(Mc());Re.ensureObject=Jv.default;var Xv=rn(Fc());Re.stripComments=Xv.default;function rn(r){return r&&r.__esModule?r:{default:r}}});var Ue=v((Tr,$c)=>{l();"use strict";Tr.__esModule=!0;Tr.default=void 0;var Lc=Er();function Nc(r,e){for(var t=0;ti||this.source.end.linen||this.source.end.line===i&&this.source.end.column{l();"use strict";W.__esModule=!0;W.UNIVERSAL=W.TAG=W.STRING=W.SELECTOR=W.ROOT=W.PSEUDO=W.NESTING=W.ID=W.COMMENT=W.COMBINATOR=W.CLASS=W.ATTRIBUTE=void 0;var tx="tag";W.TAG=tx;var rx="string";W.STRING=rx;var ix="selector";W.SELECTOR=ix;var nx="root";W.ROOT=nx;var sx="pseudo";W.PSEUDO=sx;var ax="nesting";W.NESTING=ax;var ox="id";W.ID=ox;var lx="comment";W.COMMENT=lx;var ux="combinator";W.COMBINATOR=ux;var fx="class";W.CLASS=fx;var cx="attribute";W.ATTRIBUTE=cx;var px="universal";W.UNIVERSAL=px});var nn=v((Pr,Uc)=>{l();"use strict";Pr.__esModule=!0;Pr.default=void 0;var dx=mx(Ue()),We=hx(ne());function zc(r){if(typeof WeakMap!="function")return null;var e=new WeakMap,t=new WeakMap;return(zc=function(n){return n?t:e})(r)}function hx(r,e){if(!e&&r&&r.__esModule)return r;if(r===null||typeof r!="object"&&typeof r!="function")return{default:r};var t=zc(e);if(t&&t.has(r))return t.get(r);var i={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in r)if(a!=="default"&&Object.prototype.hasOwnProperty.call(r,a)){var s=n?Object.getOwnPropertyDescriptor(r,a):null;s&&(s.get||s.set)?Object.defineProperty(i,a,s):i[a]=r[a]}return i.default=r,t&&t.set(r,i),i}function mx(r){return r&&r.__esModule?r:{default:r}}function gx(r,e){var t=typeof Symbol!="undefined"&&r[Symbol.iterator]||r["@@iterator"];if(t)return(t=t.call(r)).next.bind(t);if(Array.isArray(r)||(t=yx(r))||e&&r&&typeof r.length=="number"){t&&(r=t);var i=0;return function(){return i>=r.length?{done:!0}:{done:!1,value:r[i++]}}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function yx(r,e){if(!!r){if(typeof r=="string")return jc(r,e);var t=Object.prototype.toString.call(r).slice(8,-1);if(t==="Object"&&r.constructor&&(t=r.constructor.name),t==="Map"||t==="Set")return Array.from(r);if(t==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return jc(r,e)}}function jc(r,e){(e==null||e>r.length)&&(e=r.length);for(var t=0,i=new Array(e);t=n&&(this.indexes[s]=a-1);return this},t.removeAll=function(){for(var n=gx(this.nodes),a;!(a=n()).done;){var s=a.value;s.parent=void 0}return this.nodes=[],this},t.empty=function(){return this.removeAll()},t.insertAfter=function(n,a){a.parent=this;var s=this.index(n);this.nodes.splice(s+1,0,a),a.parent=this;var o;for(var u in this.indexes)o=this.indexes[u],s<=o&&(this.indexes[u]=o+1);return this},t.insertBefore=function(n,a){a.parent=this;var s=this.index(n);this.nodes.splice(s,0,a),a.parent=this;var o;for(var u in this.indexes)o=this.indexes[u],o<=s&&(this.indexes[u]=o+1);return this},t._findChildAtPosition=function(n,a){var s=void 0;return this.each(function(o){if(o.atPosition){var u=o.atPosition(n,a);if(u)return s=u,!1}else if(o.isAtPosition(n,a))return s=o,!1}),s},t.atPosition=function(n,a){if(this.isAtPosition(n,a))return this._findChildAtPosition(n,a)||this},t._inferEndPosition=function(){this.last&&this.last.source&&this.last.source.end&&(this.source=this.source||{},this.source.end=this.source.end||{},Object.assign(this.source.end,this.last.source.end))},t.each=function(n){this.lastEach||(this.lastEach=0),this.indexes||(this.indexes={}),this.lastEach++;var a=this.lastEach;if(this.indexes[a]=0,!!this.length){for(var s,o;this.indexes[a]{l();"use strict";Dr.__esModule=!0;Dr.default=void 0;var xx=Sx(nn()),kx=ne();function Sx(r){return r&&r.__esModule?r:{default:r}}function Wc(r,e){for(var t=0;t{l();"use strict";Ir.__esModule=!0;Ir.default=void 0;var Ox=Tx(nn()),Ex=ne();function Tx(r){return r&&r.__esModule?r:{default:r}}function Px(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,Js(r,e)}function Js(r,e){return Js=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},Js(r,e)}var Dx=function(r){Px(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=Ex.SELECTOR,i}return e}(Ox.default);Ir.default=Dx;Hc.exports=Ir.default});var sn=v((bT,Yc)=>{l();"use strict";var Ix={},qx=Ix.hasOwnProperty,Rx=function(e,t){if(!e)return t;var i={};for(var n in t)i[n]=qx.call(e,n)?e[n]:t[n];return i},Mx=/[ -,\.\/:-@\[-\^`\{-~]/,Bx=/[ -,\.\/:-@\[\]\^`\{-~]/,Fx=/(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g,Ks=function r(e,t){t=Rx(t,r.options),t.quotes!="single"&&t.quotes!="double"&&(t.quotes="single");for(var i=t.quotes=="double"?'"':"'",n=t.isIdentifier,a=e.charAt(0),s="",o=0,u=e.length;o126){if(f>=55296&&f<=56319&&o{l();"use strict";qr.__esModule=!0;qr.default=void 0;var Lx=Qc(sn()),Nx=Er(),$x=Qc(Ue()),zx=ne();function Qc(r){return r&&r.__esModule?r:{default:r}}function Jc(r,e){for(var t=0;t{l();"use strict";Rr.__esModule=!0;Rr.default=void 0;var Wx=Hx(Ue()),Gx=ne();function Hx(r){return r&&r.__esModule?r:{default:r}}function Yx(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,ta(r,e)}function ta(r,e){return ta=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},ta(r,e)}var Qx=function(r){Yx(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=Gx.COMMENT,i}return e}(Wx.default);Rr.default=Qx;Kc.exports=Rr.default});var na=v((Mr,Zc)=>{l();"use strict";Mr.__esModule=!0;Mr.default=void 0;var Jx=Kx(Ue()),Xx=ne();function Kx(r){return r&&r.__esModule?r:{default:r}}function Zx(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,ia(r,e)}function ia(r,e){return ia=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},ia(r,e)}var e1=function(r){Zx(e,r);function e(i){var n;return n=r.call(this,i)||this,n.type=Xx.ID,n}var t=e.prototype;return t.valueToString=function(){return"#"+r.prototype.valueToString.call(this)},e}(Jx.default);Mr.default=e1;Zc.exports=Mr.default});var an=v((Br,rp)=>{l();"use strict";Br.__esModule=!0;Br.default=void 0;var t1=ep(sn()),r1=Er(),i1=ep(Ue());function ep(r){return r&&r.__esModule?r:{default:r}}function tp(r,e){for(var t=0;t{l();"use strict";Fr.__esModule=!0;Fr.default=void 0;var o1=u1(an()),l1=ne();function u1(r){return r&&r.__esModule?r:{default:r}}function f1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,aa(r,e)}function aa(r,e){return aa=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},aa(r,e)}var c1=function(r){f1(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=l1.TAG,i}return e}(o1.default);Fr.default=c1;ip.exports=Fr.default});var ua=v((Lr,np)=>{l();"use strict";Lr.__esModule=!0;Lr.default=void 0;var p1=h1(Ue()),d1=ne();function h1(r){return r&&r.__esModule?r:{default:r}}function m1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,la(r,e)}function la(r,e){return la=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},la(r,e)}var g1=function(r){m1(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=d1.STRING,i}return e}(p1.default);Lr.default=g1;np.exports=Lr.default});var ca=v((Nr,sp)=>{l();"use strict";Nr.__esModule=!0;Nr.default=void 0;var y1=b1(nn()),w1=ne();function b1(r){return r&&r.__esModule?r:{default:r}}function v1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,fa(r,e)}function fa(r,e){return fa=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},fa(r,e)}var x1=function(r){v1(e,r);function e(i){var n;return n=r.call(this,i)||this,n.type=w1.PSEUDO,n}var t=e.prototype;return t.toString=function(){var n=this.length?"("+this.map(String).join(",")+")":"";return[this.rawSpaceBefore,this.stringifyProperty("value"),n,this.rawSpaceAfter].join("")},e}(y1.default);Nr.default=x1;sp.exports=Nr.default});var ap={};Ae(ap,{deprecate:()=>k1});function k1(r){return r}var op=C(()=>{l()});var up=v((vT,lp)=>{l();lp.exports=(op(),ap).deprecate});var ya=v(jr=>{l();"use strict";jr.__esModule=!0;jr.default=void 0;jr.unescapeValue=ma;var $r=da(sn()),S1=da(Ki()),C1=da(an()),A1=ne(),pa;function da(r){return r&&r.__esModule?r:{default:r}}function fp(r,e){for(var t=0;t0&&!n.quoted&&o.before.length===0&&!(n.spaces.value&&n.spaces.value.after)&&(o.before=" "),cp(s,o)}))),a.push("]"),a.push(this.rawSpaceAfter),a.join("")},_1(e,[{key:"quoted",get:function(){var n=this.quoteMark;return n==="'"||n==='"'},set:function(n){P1()}},{key:"quoteMark",get:function(){return this._quoteMark},set:function(n){if(!this._constructed){this._quoteMark=n;return}this._quoteMark!==n&&(this._quoteMark=n,this._syncRawValue())}},{key:"qualifiedAttribute",get:function(){return this.qualifiedName(this.raws.attribute||this.attribute)}},{key:"insensitiveFlag",get:function(){return this.insensitive?"i":""}},{key:"value",get:function(){return this._value},set:function(n){if(this._constructed){var a=ma(n),s=a.deprecatedUsage,o=a.unescaped,u=a.quoteMark;if(s&&T1(),o===this._value&&u===this._quoteMark)return;this._value=o,this._quoteMark=u,this._syncRawValue()}else this._value=n}},{key:"insensitive",get:function(){return this._insensitive},set:function(n){n||(this._insensitive=!1,this.raws&&(this.raws.insensitiveFlag==="I"||this.raws.insensitiveFlag==="i")&&(this.raws.insensitiveFlag=void 0)),this._insensitive=n}},{key:"attribute",get:function(){return this._attribute},set:function(n){this._handleEscapes("attribute",n),this._attribute=n}}]),e}(C1.default);jr.default=on;on.NO_QUOTE=null;on.SINGLE_QUOTE="'";on.DOUBLE_QUOTE='"';var ga=(pa={"'":{quotes:"single",wrap:!0},'"':{quotes:"double",wrap:!0}},pa[null]={isIdentifier:!0},pa);function cp(r,e){return""+e.before+r+e.after}});var ba=v((Vr,pp)=>{l();"use strict";Vr.__esModule=!0;Vr.default=void 0;var q1=M1(an()),R1=ne();function M1(r){return r&&r.__esModule?r:{default:r}}function B1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,wa(r,e)}function wa(r,e){return wa=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},wa(r,e)}var F1=function(r){B1(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=R1.UNIVERSAL,i.value="*",i}return e}(q1.default);Vr.default=F1;pp.exports=Vr.default});var xa=v((Ur,dp)=>{l();"use strict";Ur.__esModule=!0;Ur.default=void 0;var L1=$1(Ue()),N1=ne();function $1(r){return r&&r.__esModule?r:{default:r}}function z1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,va(r,e)}function va(r,e){return va=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},va(r,e)}var j1=function(r){z1(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=N1.COMBINATOR,i}return e}(L1.default);Ur.default=j1;dp.exports=Ur.default});var Sa=v((Wr,hp)=>{l();"use strict";Wr.__esModule=!0;Wr.default=void 0;var V1=W1(Ue()),U1=ne();function W1(r){return r&&r.__esModule?r:{default:r}}function G1(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,ka(r,e)}function ka(r,e){return ka=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},ka(r,e)}var H1=function(r){G1(e,r);function e(t){var i;return i=r.call(this,t)||this,i.type=U1.NESTING,i.value="&",i}return e}(V1.default);Wr.default=H1;hp.exports=Wr.default});var gp=v((ln,mp)=>{l();"use strict";ln.__esModule=!0;ln.default=Y1;function Y1(r){return r.sort(function(e,t){return e-t})}mp.exports=ln.default});var Ca=v(D=>{l();"use strict";D.__esModule=!0;D.word=D.tilde=D.tab=D.str=D.space=D.slash=D.singleQuote=D.semicolon=D.plus=D.pipe=D.openSquare=D.openParenthesis=D.newline=D.greaterThan=D.feed=D.equals=D.doubleQuote=D.dollar=D.cr=D.comment=D.comma=D.combinator=D.colon=D.closeSquare=D.closeParenthesis=D.caret=D.bang=D.backslash=D.at=D.asterisk=D.ampersand=void 0;var Q1=38;D.ampersand=Q1;var J1=42;D.asterisk=J1;var X1=64;D.at=X1;var K1=44;D.comma=K1;var Z1=58;D.colon=Z1;var ek=59;D.semicolon=ek;var tk=40;D.openParenthesis=tk;var rk=41;D.closeParenthesis=rk;var ik=91;D.openSquare=ik;var nk=93;D.closeSquare=nk;var sk=36;D.dollar=sk;var ak=126;D.tilde=ak;var ok=94;D.caret=ok;var lk=43;D.plus=lk;var uk=61;D.equals=uk;var fk=124;D.pipe=fk;var ck=62;D.greaterThan=ck;var pk=32;D.space=pk;var yp=39;D.singleQuote=yp;var dk=34;D.doubleQuote=dk;var hk=47;D.slash=hk;var mk=33;D.bang=mk;var gk=92;D.backslash=gk;var yk=13;D.cr=yk;var wk=12;D.feed=wk;var bk=10;D.newline=bk;var vk=9;D.tab=vk;var xk=yp;D.str=xk;var kk=-1;D.comment=kk;var Sk=-2;D.word=Sk;var Ck=-3;D.combinator=Ck});var vp=v(Gr=>{l();"use strict";Gr.__esModule=!0;Gr.FIELDS=void 0;Gr.default=Dk;var O=Ak(Ca()),Rt,V;function wp(r){if(typeof WeakMap!="function")return null;var e=new WeakMap,t=new WeakMap;return(wp=function(n){return n?t:e})(r)}function Ak(r,e){if(!e&&r&&r.__esModule)return r;if(r===null||typeof r!="object"&&typeof r!="function")return{default:r};var t=wp(e);if(t&&t.has(r))return t.get(r);var i={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in r)if(a!=="default"&&Object.prototype.hasOwnProperty.call(r,a)){var s=n?Object.getOwnPropertyDescriptor(r,a):null;s&&(s.get||s.set)?Object.defineProperty(i,a,s):i[a]=r[a]}return i.default=r,t&&t.set(r,i),i}var _k=(Rt={},Rt[O.tab]=!0,Rt[O.newline]=!0,Rt[O.cr]=!0,Rt[O.feed]=!0,Rt),Ok=(V={},V[O.space]=!0,V[O.tab]=!0,V[O.newline]=!0,V[O.cr]=!0,V[O.feed]=!0,V[O.ampersand]=!0,V[O.asterisk]=!0,V[O.bang]=!0,V[O.comma]=!0,V[O.colon]=!0,V[O.semicolon]=!0,V[O.openParenthesis]=!0,V[O.closeParenthesis]=!0,V[O.openSquare]=!0,V[O.closeSquare]=!0,V[O.singleQuote]=!0,V[O.doubleQuote]=!0,V[O.plus]=!0,V[O.pipe]=!0,V[O.tilde]=!0,V[O.greaterThan]=!0,V[O.equals]=!0,V[O.dollar]=!0,V[O.caret]=!0,V[O.slash]=!0,V),Aa={},bp="0123456789abcdefABCDEF";for(un=0;un0?(k=s+x,S=w-y[x].length):(k=s,S=a),E=O.comment,s=k,p=k,d=w-S):c===O.slash?(w=o,E=c,p=s,d=o-a,u=w+1):(w=Ek(t,o),E=O.word,p=s,d=w-a),u=w+1;break}e.push([E,s,o-a,p,d,o,u]),S&&(a=S,S=null),o=u}return e}});var Ep=v((Hr,Op)=>{l();"use strict";Hr.__esModule=!0;Hr.default=void 0;var Ik=be(Qs()),_a=be(Xs()),qk=be(ea()),xp=be(ra()),Rk=be(na()),Mk=be(oa()),Oa=be(ua()),Bk=be(ca()),kp=fn(ya()),Fk=be(ba()),Ea=be(xa()),Lk=be(Sa()),Nk=be(gp()),A=fn(vp()),T=fn(Ca()),$k=fn(ne()),Y=Er(),xt,Ta;function Sp(r){if(typeof WeakMap!="function")return null;var e=new WeakMap,t=new WeakMap;return(Sp=function(n){return n?t:e})(r)}function fn(r,e){if(!e&&r&&r.__esModule)return r;if(r===null||typeof r!="object"&&typeof r!="function")return{default:r};var t=Sp(e);if(t&&t.has(r))return t.get(r);var i={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in r)if(a!=="default"&&Object.prototype.hasOwnProperty.call(r,a)){var s=n?Object.getOwnPropertyDescriptor(r,a):null;s&&(s.get||s.set)?Object.defineProperty(i,a,s):i[a]=r[a]}return i.default=r,t&&t.set(r,i),i}function be(r){return r&&r.__esModule?r:{default:r}}function Cp(r,e){for(var t=0;t0){var s=this.current.last;if(s){var o=this.convertWhitespaceNodesToSpace(a),u=o.space,c=o.rawSpace;c!==void 0&&(s.rawSpaceAfter+=c),s.spaces.after+=u}else a.forEach(function(E){return i.newNode(E)})}return}var f=this.currToken,d=void 0;n>this.position&&(d=this.parseWhitespaceEquivalentTokens(n));var p;if(this.isNamedCombinator()?p=this.namedCombinator():this.currToken[A.FIELDS.TYPE]===T.combinator?(p=new Ea.default({value:this.content(),source:Mt(this.currToken),sourceIndex:this.currToken[A.FIELDS.START_POS]}),this.position++):Pa[this.currToken[A.FIELDS.TYPE]]||d||this.unexpected(),p){if(d){var m=this.convertWhitespaceNodesToSpace(d),b=m.space,x=m.rawSpace;p.spaces.before=b,p.rawSpaceBefore=x}}else{var y=this.convertWhitespaceNodesToSpace(d,!0),w=y.space,k=y.rawSpace;k||(k=w);var S={},_={spaces:{}};w.endsWith(" ")&&k.endsWith(" ")?(S.before=w.slice(0,w.length-1),_.spaces.before=k.slice(0,k.length-1)):w.startsWith(" ")&&k.startsWith(" ")?(S.after=w.slice(1),_.spaces.after=k.slice(1)):_.value=k,p=new Ea.default({value:" ",source:Da(f,this.tokens[this.position-1]),sourceIndex:f[A.FIELDS.START_POS],spaces:S,raws:_})}return this.currToken&&this.currToken[A.FIELDS.TYPE]===T.space&&(p.spaces.after=this.optionalSpace(this.content()),this.position++),this.newNode(p)},e.comma=function(){if(this.position===this.tokens.length-1){this.root.trailingComma=!0,this.position++;return}this.current._inferEndPosition();var i=new _a.default({source:{start:Ap(this.tokens[this.position+1])}});this.current.parent.append(i),this.current=i,this.position++},e.comment=function(){var i=this.currToken;this.newNode(new xp.default({value:this.content(),source:Mt(i),sourceIndex:i[A.FIELDS.START_POS]})),this.position++},e.error=function(i,n){throw this.root.error(i,n)},e.missingBackslash=function(){return this.error("Expected a backslash preceding the semicolon.",{index:this.currToken[A.FIELDS.START_POS]})},e.missingParenthesis=function(){return this.expected("opening parenthesis",this.currToken[A.FIELDS.START_POS])},e.missingSquareBracket=function(){return this.expected("opening square bracket",this.currToken[A.FIELDS.START_POS])},e.unexpected=function(){return this.error("Unexpected '"+this.content()+"'. Escaping special characters with \\ may help.",this.currToken[A.FIELDS.START_POS])},e.unexpectedPipe=function(){return this.error("Unexpected '|'.",this.currToken[A.FIELDS.START_POS])},e.namespace=function(){var i=this.prevToken&&this.content(this.prevToken)||!0;if(this.nextToken[A.FIELDS.TYPE]===T.word)return this.position++,this.word(i);if(this.nextToken[A.FIELDS.TYPE]===T.asterisk)return this.position++,this.universal(i);this.unexpectedPipe()},e.nesting=function(){if(this.nextToken){var i=this.content(this.nextToken);if(i==="|"){this.position++;return}}var n=this.currToken;this.newNode(new Lk.default({value:this.content(),source:Mt(n),sourceIndex:n[A.FIELDS.START_POS]})),this.position++},e.parentheses=function(){var i=this.current.last,n=1;if(this.position++,i&&i.type===$k.PSEUDO){var a=new _a.default({source:{start:Ap(this.tokens[this.position-1])}}),s=this.current;for(i.append(a),this.current=a;this.position1&&i.nextToken&&i.nextToken[A.FIELDS.TYPE]===T.openParenthesis&&i.error("Misplaced parenthesis.",{index:i.nextToken[A.FIELDS.START_POS]})});else return this.expected(["pseudo-class","pseudo-element"],this.currToken[A.FIELDS.START_POS])},e.space=function(){var i=this.content();this.position===0||this.prevToken[A.FIELDS.TYPE]===T.comma||this.prevToken[A.FIELDS.TYPE]===T.openParenthesis||this.current.nodes.every(function(n){return n.type==="comment"})?(this.spaces=this.optionalSpace(i),this.position++):this.position===this.tokens.length-1||this.nextToken[A.FIELDS.TYPE]===T.comma||this.nextToken[A.FIELDS.TYPE]===T.closeParenthesis?(this.current.last.spaces.after=this.optionalSpace(i),this.position++):this.combinator()},e.string=function(){var i=this.currToken;this.newNode(new Oa.default({value:this.content(),source:Mt(i),sourceIndex:i[A.FIELDS.START_POS]})),this.position++},e.universal=function(i){var n=this.nextToken;if(n&&this.content(n)==="|")return this.position++,this.namespace();var a=this.currToken;this.newNode(new Fk.default({value:this.content(),source:Mt(a),sourceIndex:a[A.FIELDS.START_POS]}),i),this.position++},e.splitWord=function(i,n){for(var a=this,s=this.nextToken,o=this.content();s&&~[T.dollar,T.caret,T.equals,T.word].indexOf(s[A.FIELDS.TYPE]);){this.position++;var u=this.content();if(o+=u,u.lastIndexOf("\\")===u.length-1){var c=this.nextToken;c&&c[A.FIELDS.TYPE]===T.space&&(o+=this.requiredSpace(this.content(c)),this.position++)}s=this.nextToken}var f=Ia(o,".").filter(function(b){var x=o[b-1]==="\\",y=/^\d+\.\d+%$/.test(o);return!x&&!y}),d=Ia(o,"#").filter(function(b){return o[b-1]!=="\\"}),p=Ia(o,"#{");p.length&&(d=d.filter(function(b){return!~p.indexOf(b)}));var m=(0,Nk.default)(Vk([0].concat(f,d)));m.forEach(function(b,x){var y=m[x+1]||o.length,w=o.slice(b,y);if(x===0&&n)return n.call(a,w,m.length);var k,S=a.currToken,_=S[A.FIELDS.START_POS]+m[x],E=kt(S[1],S[2]+b,S[3],S[2]+(y-1));if(~f.indexOf(b)){var I={value:w.slice(1),source:E,sourceIndex:_};k=new qk.default(Bt(I,"value"))}else if(~d.indexOf(b)){var q={value:w.slice(1),source:E,sourceIndex:_};k=new Rk.default(Bt(q,"value"))}else{var R={value:w,source:E,sourceIndex:_};Bt(R,"value"),k=new Mk.default(R)}a.newNode(k,i),i=null}),this.position++},e.word=function(i){var n=this.nextToken;return n&&this.content(n)==="|"?(this.position++,this.namespace()):this.splitWord(i)},e.loop=function(){for(;this.position{l();"use strict";Yr.__esModule=!0;Yr.default=void 0;var Wk=Gk(Ep());function Gk(r){return r&&r.__esModule?r:{default:r}}var Hk=function(){function r(t,i){this.func=t||function(){},this.funcRes=null,this.options=i}var e=r.prototype;return e._shouldUpdateSelector=function(i,n){n===void 0&&(n={});var a=Object.assign({},this.options,n);return a.updateSelector===!1?!1:typeof i!="string"},e._isLossy=function(i){i===void 0&&(i={});var n=Object.assign({},this.options,i);return n.lossless===!1},e._root=function(i,n){n===void 0&&(n={});var a=new Wk.default(i,this._parseOptions(n));return a.root},e._parseOptions=function(i){return{lossy:this._isLossy(i)}},e._run=function(i,n){var a=this;return n===void 0&&(n={}),new Promise(function(s,o){try{var u=a._root(i,n);Promise.resolve(a.func(u)).then(function(c){var f=void 0;return a._shouldUpdateSelector(i,n)&&(f=u.toString(),i.selector=f),{transform:c,root:u,string:f}}).then(s,o)}catch(c){o(c);return}})},e._runSync=function(i,n){n===void 0&&(n={});var a=this._root(i,n),s=this.func(a);if(s&&typeof s.then=="function")throw new Error("Selector processor returned a promise to a synchronous call.");var o=void 0;return n.updateSelector&&typeof i!="string"&&(o=a.toString(),i.selector=o),{transform:s,root:a,string:o}},e.ast=function(i,n){return this._run(i,n).then(function(a){return a.root})},e.astSync=function(i,n){return this._runSync(i,n).root},e.transform=function(i,n){return this._run(i,n).then(function(a){return a.transform})},e.transformSync=function(i,n){return this._runSync(i,n).transform},e.process=function(i,n){return this._run(i,n).then(function(a){return a.string||a.root.toString()})},e.processSync=function(i,n){var a=this._runSync(i,n);return a.string||a.root.toString()},r}();Yr.default=Hk;Tp.exports=Yr.default});var Dp=v(G=>{l();"use strict";G.__esModule=!0;G.universal=G.tag=G.string=G.selector=G.root=G.pseudo=G.nesting=G.id=G.comment=G.combinator=G.className=G.attribute=void 0;var Yk=ve(ya()),Qk=ve(ea()),Jk=ve(xa()),Xk=ve(ra()),Kk=ve(na()),Zk=ve(Sa()),eS=ve(ca()),tS=ve(Qs()),rS=ve(Xs()),iS=ve(ua()),nS=ve(oa()),sS=ve(ba());function ve(r){return r&&r.__esModule?r:{default:r}}var aS=function(e){return new Yk.default(e)};G.attribute=aS;var oS=function(e){return new Qk.default(e)};G.className=oS;var lS=function(e){return new Jk.default(e)};G.combinator=lS;var uS=function(e){return new Xk.default(e)};G.comment=uS;var fS=function(e){return new Kk.default(e)};G.id=fS;var cS=function(e){return new Zk.default(e)};G.nesting=cS;var pS=function(e){return new eS.default(e)};G.pseudo=pS;var dS=function(e){return new tS.default(e)};G.root=dS;var hS=function(e){return new rS.default(e)};G.selector=hS;var mS=function(e){return new iS.default(e)};G.string=mS;var gS=function(e){return new nS.default(e)};G.tag=gS;var yS=function(e){return new sS.default(e)};G.universal=yS});var Mp=v($=>{l();"use strict";$.__esModule=!0;$.isComment=$.isCombinator=$.isClassName=$.isAttribute=void 0;$.isContainer=TS;$.isIdentifier=void 0;$.isNamespace=PS;$.isNesting=void 0;$.isNode=qa;$.isPseudo=void 0;$.isPseudoClass=ES;$.isPseudoElement=Rp;$.isUniversal=$.isTag=$.isString=$.isSelector=$.isRoot=void 0;var Q=ne(),fe,wS=(fe={},fe[Q.ATTRIBUTE]=!0,fe[Q.CLASS]=!0,fe[Q.COMBINATOR]=!0,fe[Q.COMMENT]=!0,fe[Q.ID]=!0,fe[Q.NESTING]=!0,fe[Q.PSEUDO]=!0,fe[Q.ROOT]=!0,fe[Q.SELECTOR]=!0,fe[Q.STRING]=!0,fe[Q.TAG]=!0,fe[Q.UNIVERSAL]=!0,fe);function qa(r){return typeof r=="object"&&wS[r.type]}function xe(r,e){return qa(e)&&e.type===r}var Ip=xe.bind(null,Q.ATTRIBUTE);$.isAttribute=Ip;var bS=xe.bind(null,Q.CLASS);$.isClassName=bS;var vS=xe.bind(null,Q.COMBINATOR);$.isCombinator=vS;var xS=xe.bind(null,Q.COMMENT);$.isComment=xS;var kS=xe.bind(null,Q.ID);$.isIdentifier=kS;var SS=xe.bind(null,Q.NESTING);$.isNesting=SS;var Ra=xe.bind(null,Q.PSEUDO);$.isPseudo=Ra;var CS=xe.bind(null,Q.ROOT);$.isRoot=CS;var AS=xe.bind(null,Q.SELECTOR);$.isSelector=AS;var _S=xe.bind(null,Q.STRING);$.isString=_S;var qp=xe.bind(null,Q.TAG);$.isTag=qp;var OS=xe.bind(null,Q.UNIVERSAL);$.isUniversal=OS;function Rp(r){return Ra(r)&&r.value&&(r.value.startsWith("::")||r.value.toLowerCase()===":before"||r.value.toLowerCase()===":after"||r.value.toLowerCase()===":first-letter"||r.value.toLowerCase()===":first-line")}function ES(r){return Ra(r)&&!Rp(r)}function TS(r){return!!(qa(r)&&r.walk)}function PS(r){return Ip(r)||qp(r)}});var Bp=v(Ee=>{l();"use strict";Ee.__esModule=!0;var Ma=ne();Object.keys(Ma).forEach(function(r){r==="default"||r==="__esModule"||r in Ee&&Ee[r]===Ma[r]||(Ee[r]=Ma[r])});var Ba=Dp();Object.keys(Ba).forEach(function(r){r==="default"||r==="__esModule"||r in Ee&&Ee[r]===Ba[r]||(Ee[r]=Ba[r])});var Fa=Mp();Object.keys(Fa).forEach(function(r){r==="default"||r==="__esModule"||r in Ee&&Ee[r]===Fa[r]||(Ee[r]=Fa[r])})});var Me=v((Qr,Lp)=>{l();"use strict";Qr.__esModule=!0;Qr.default=void 0;var DS=RS(Pp()),IS=qS(Bp());function Fp(r){if(typeof WeakMap!="function")return null;var e=new WeakMap,t=new WeakMap;return(Fp=function(n){return n?t:e})(r)}function qS(r,e){if(!e&&r&&r.__esModule)return r;if(r===null||typeof r!="object"&&typeof r!="function")return{default:r};var t=Fp(e);if(t&&t.has(r))return t.get(r);var i={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in r)if(a!=="default"&&Object.prototype.hasOwnProperty.call(r,a)){var s=n?Object.getOwnPropertyDescriptor(r,a):null;s&&(s.get||s.set)?Object.defineProperty(i,a,s):i[a]=r[a]}return i.default=r,t&&t.set(r,i),i}function RS(r){return r&&r.__esModule?r:{default:r}}var La=function(e){return new DS.default(e)};Object.assign(La,IS);delete La.__esModule;var MS=La;Qr.default=MS;Lp.exports=Qr.default});function Ge(r){return["fontSize","outline"].includes(r)?e=>(typeof e=="function"&&(e=e({})),Array.isArray(e)&&(e=e[0]),e):r==="fontFamily"?e=>{typeof e=="function"&&(e=e({}));let t=Array.isArray(e)&&ie(e[1])?e[0]:e;return Array.isArray(t)?t.join(", "):t}:["boxShadow","transitionProperty","transitionDuration","transitionDelay","transitionTimingFunction","backgroundImage","backgroundSize","backgroundColor","cursor","animation"].includes(r)?e=>(typeof e=="function"&&(e=e({})),Array.isArray(e)&&(e=e.join(", ")),e):["gridTemplateColumns","gridTemplateRows","objectPosition"].includes(r)?e=>(typeof e=="function"&&(e=e({})),typeof e=="string"&&(e=j.list.comma(e).join(" ")),e):(e,t={})=>(typeof e=="function"&&(e=e(t)),e)}var Jr=C(()=>{l();st();At()});var Wp=v((PT,Va)=>{l();var{Rule:Np,AtRule:BS}=ge(),$p=Me();function Na(r,e){let t;try{$p(i=>{t=i}).processSync(r)}catch(i){throw r.includes(":")?e?e.error("Missed semicolon"):i:e?e.error(i.message):i}return t.at(0)}function zp(r,e){let t=!1;return r.each(i=>{if(i.type==="nesting"){let n=e.clone({});i.value!=="&"?i.replaceWith(Na(i.value.replace("&",n.toString()))):i.replaceWith(n),t=!0}else"nodes"in i&&i.nodes&&zp(i,e)&&(t=!0)}),t}function jp(r,e){let t=[];return r.selectors.forEach(i=>{let n=Na(i,r);e.selectors.forEach(a=>{if(!a)return;let s=Na(a,e);zp(s,n)||(s.prepend($p.combinator({value:" "})),s.prepend(n.clone({}))),t.push(s.toString())})}),t}function cn(r,e){let t=r.prev();for(e.after(r);t&&t.type==="comment";){let i=t.prev();e.after(t),t=i}return r}function FS(r){return function e(t,i,n,a=n){let s=[];if(i.each(o=>{o.type==="rule"&&n?a&&(o.selectors=jp(t,o)):o.type==="atrule"&&o.nodes?r[o.name]?e(t,o,a):i[za]!==!1&&s.push(o):s.push(o)}),n&&s.length){let o=t.clone({nodes:[]});for(let u of s)o.append(u);i.prepend(o)}}}function $a(r,e,t){let i=new Np({selector:r,nodes:[]});return i.append(e),t.after(i),i}function Vp(r,e){let t={};for(let i of r)t[i]=!0;if(e)for(let i of e)t[i.replace(/^@/,"")]=!0;return t}function LS(r){r=r.trim();let e=r.match(/^\((.*)\)$/);if(!e)return{type:"basic",selector:r};let t=e[1].match(/^(with(?:out)?):(.+)$/);if(t){let i=t[1]==="with",n=Object.fromEntries(t[2].trim().split(/\s+/).map(s=>[s,!0]));if(i&&n.all)return{type:"noop"};let a=s=>!!n[s];return n.all?a=()=>!0:i&&(a=s=>s==="all"?!1:!n[s]),{type:"withrules",escapes:a}}return{type:"unknown"}}function NS(r){let e=[],t=r.parent;for(;t&&t instanceof BS;)e.push(t),t=t.parent;return e}function $S(r){let e=r[Up];if(!e)r.after(r.nodes);else{let t=r.nodes,i,n=-1,a,s,o,u=NS(r);if(u.forEach((c,f)=>{if(e(c.name))i=c,n=f,s=o;else{let d=o;o=c.clone({nodes:[]}),d&&o.append(d),a=a||o}}),i?s?(a.append(t),i.after(s)):i.after(t):r.after(t),r.next()&&i){let c;u.slice(0,n+1).forEach((f,d,p)=>{let m=c;c=f.clone({nodes:[]}),m&&c.append(m);let b=[],y=(p[d-1]||r).next();for(;y;)b.push(y),y=y.next();c.append(b)}),c&&(s||t[t.length-1]).after(c)}}r.remove()}var za=Symbol("rootRuleMergeSel"),Up=Symbol("rootRuleEscapes");function zS(r){let{params:e}=r,{type:t,selector:i,escapes:n}=LS(e);if(t==="unknown")throw r.error(`Unknown @${r.name} parameter ${JSON.stringify(e)}`);if(t==="basic"&&i){let a=new Np({selector:i,nodes:r.nodes});r.removeAll(),r.append(a)}r[Up]=n,r[za]=n?!n("all"):t==="noop"}var ja=Symbol("hasRootRule");Va.exports=(r={})=>{let e=Vp(["media","supports","layer","container"],r.bubble),t=FS(e),i=Vp(["document","font-face","keyframes","-webkit-keyframes","-moz-keyframes"],r.unwrap),n=(r.rootRuleName||"at-root").replace(/^@/,""),a=r.preserveEmpty;return{postcssPlugin:"postcss-nested",Once(s){s.walkAtRules(n,o=>{zS(o),s[ja]=!0})},Rule(s){let o=!1,u=s,c=!1,f=[];s.each(d=>{d.type==="rule"?(f.length&&(u=$a(s.selector,f,u),f=[]),c=!0,o=!0,d.selectors=jp(s,d),u=cn(d,u)):d.type==="atrule"?(f.length&&(u=$a(s.selector,f,u),f=[]),d.name===n?(o=!0,t(s,d,!0,d[za]),u=cn(d,u)):e[d.name]?(c=!0,o=!0,t(s,d,!0),u=cn(d,u)):i[d.name]?(c=!0,o=!0,t(s,d,!1),u=cn(d,u)):c&&f.push(d)):d.type==="decl"&&c&&f.push(d)}),f.length&&(u=$a(s.selector,f,u)),o&&a!==!0&&(s.raws.semicolon=!0,s.nodes.length===0&&s.remove())},RootExit(s){s[ja]&&(s.walkAtRules(n,$S),s[ja]=!1)}}};Va.exports.postcss=!0});var Qp=v((DT,Yp)=>{l();"use strict";var Gp=/-(\w|$)/g,Hp=(r,e)=>e.toUpperCase(),jS=r=>(r=r.toLowerCase(),r==="float"?"cssFloat":r.startsWith("-ms-")?r.substr(1).replace(Gp,Hp):r.replace(Gp,Hp));Yp.exports=jS});var Ga=v((IT,Jp)=>{l();var VS=Qp(),US={boxFlex:!0,boxFlexGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0};function Ua(r){return typeof r.nodes=="undefined"?!0:Wa(r)}function Wa(r){let e,t={};return r.each(i=>{if(i.type==="atrule")e="@"+i.name,i.params&&(e+=" "+i.params),typeof t[e]=="undefined"?t[e]=Ua(i):Array.isArray(t[e])?t[e].push(Ua(i)):t[e]=[t[e],Ua(i)];else if(i.type==="rule"){let n=Wa(i);if(t[i.selector])for(let a in n)t[i.selector][a]=n[a];else t[i.selector]=n}else if(i.type==="decl"){i.prop[0]==="-"&&i.prop[1]==="-"||i.parent&&i.parent.selector===":export"?e=i.prop:e=VS(i.prop);let n=i.value;!isNaN(i.value)&&US[e]&&(n=parseFloat(i.value)),i.important&&(n+=" !important"),typeof t[e]=="undefined"?t[e]=n:Array.isArray(t[e])?t[e].push(n):t[e]=[t[e],n]}}),t}Jp.exports=Wa});var pn=v((qT,ed)=>{l();var Xr=ge(),Xp=/\s*!important\s*$/i,WS={"box-flex":!0,"box-flex-group":!0,"column-count":!0,flex:!0,"flex-grow":!0,"flex-positive":!0,"flex-shrink":!0,"flex-negative":!0,"font-weight":!0,"line-clamp":!0,"line-height":!0,opacity:!0,order:!0,orphans:!0,"tab-size":!0,widows:!0,"z-index":!0,zoom:!0,"fill-opacity":!0,"stroke-dashoffset":!0,"stroke-opacity":!0,"stroke-width":!0};function GS(r){return r.replace(/([A-Z])/g,"-$1").replace(/^ms-/,"-ms-").toLowerCase()}function Kp(r,e,t){t===!1||t===null||(e.startsWith("--")||(e=GS(e)),typeof t=="number"&&(t===0||WS[e]?t=t.toString():t+="px"),e==="css-float"&&(e="float"),Xp.test(t)?(t=t.replace(Xp,""),r.push(Xr.decl({prop:e,value:t,important:!0}))):r.push(Xr.decl({prop:e,value:t})))}function Zp(r,e,t){let i=Xr.atRule({name:e[1],params:e[3]||""});typeof t=="object"&&(i.nodes=[],Ha(t,i)),r.push(i)}function Ha(r,e){let t,i,n;for(t in r)if(i=r[t],!(i===null||typeof i=="undefined"))if(t[0]==="@"){let a=t.match(/@(\S+)(\s+([\W\w]*)\s*)?/);if(Array.isArray(i))for(let s of i)Zp(e,a,s);else Zp(e,a,i)}else if(Array.isArray(i))for(let a of i)Kp(e,t,a);else typeof i=="object"?(n=Xr.rule({selector:t}),Ha(i,n),e.push(n)):Kp(e,t,i)}ed.exports=function(r){let e=Xr.root();return Ha(r,e),e}});var Ya=v((RT,td)=>{l();var HS=Ga();td.exports=function(e){return console&&console.warn&&e.warnings().forEach(t=>{let i=t.plugin||"PostCSS";console.warn(i+": "+t.text)}),HS(e.root)}});var id=v((MT,rd)=>{l();var YS=ge(),QS=Ya(),JS=pn();rd.exports=function(e){let t=YS(e);return async i=>{let n=await t.process(i,{parser:JS,from:void 0});return QS(n)}}});var sd=v((BT,nd)=>{l();var XS=ge(),KS=Ya(),ZS=pn();nd.exports=function(r){let e=XS(r);return t=>{let i=e.process(t,{parser:ZS,from:void 0});return KS(i)}}});var od=v((FT,ad)=>{l();var e2=Ga(),t2=pn(),r2=id(),i2=sd();ad.exports={objectify:e2,parse:t2,async:r2,sync:i2}});var Ft,ld,LT,NT,$T,zT,ud=C(()=>{l();Ft=X(od()),ld=Ft.default,LT=Ft.default.objectify,NT=Ft.default.parse,$T=Ft.default.async,zT=Ft.default.sync});function Lt(r){return Array.isArray(r)?r.flatMap(e=>j([(0,fd.default)({bubble:["screen"]})]).process(e,{parser:ld}).root.nodes):Lt([r])}var fd,Qa=C(()=>{l();st();fd=X(Wp());ud()});function Nt(r,e,t=!1){if(r==="")return e;let i=typeof e=="string"?(0,cd.default)().astSync(e):e;return i.walkClasses(n=>{let a=n.value,s=t&&a.startsWith("-");n.value=s?`-${r}${a.slice(1)}`:`${r}${a}`}),typeof e=="string"?i.toString():i}var cd,dn=C(()=>{l();cd=X(Me())});function ce(r){let e=pd.default.className();return e.value=r,wt(e?.raws?.value??e.value)}var pd,$t=C(()=>{l();pd=X(Me());bi()});function Ja(r){return wt(`.${ce(r)}`)}function hn(r,e){return Ja(Kr(r,e))}function Kr(r,e){return e==="DEFAULT"?r:e==="-"||e==="-DEFAULT"?`-${r}`:e.startsWith("-")?`-${r}${e}`:e.startsWith("/")?`${r}${e}`:`${r}-${e}`}var Xa=C(()=>{l();$t();bi()});function P(r,e=[[r,[r]]],{filterDefault:t=!1,...i}={}){let n=Ge(r);return function({matchUtilities:a,theme:s}){for(let o of e){let u=Array.isArray(o[0])?o:[o];a(u.reduce((c,[f,d])=>Object.assign(c,{[f]:p=>d.reduce((m,b)=>Array.isArray(b)?Object.assign(m,{[b[0]]:b[1]}):Object.assign(m,{[b]:n(p)}),{})}),{}),{...i,values:t?Object.fromEntries(Object.entries(s(r)??{}).filter(([c])=>c!=="DEFAULT")):s(r)})}}}var dd=C(()=>{l();Jr()});function at(r){return r=Array.isArray(r)?r:[r],r.map(e=>{let t=e.values.map(i=>i.raw!==void 0?i.raw:[i.min&&`(min-width: ${i.min})`,i.max&&`(max-width: ${i.max})`].filter(Boolean).join(" and "));return e.not?`not all and ${t}`:t}).join(", ")}var mn=C(()=>{l()});function Ka(r){return r.split(f2).map(t=>{let i=t.trim(),n={value:i},a=i.split(c2),s=new Set;for(let o of a)!s.has("DIRECTIONS")&&n2.has(o)?(n.direction=o,s.add("DIRECTIONS")):!s.has("PLAY_STATES")&&s2.has(o)?(n.playState=o,s.add("PLAY_STATES")):!s.has("FILL_MODES")&&a2.has(o)?(n.fillMode=o,s.add("FILL_MODES")):!s.has("ITERATION_COUNTS")&&(o2.has(o)||p2.test(o))?(n.iterationCount=o,s.add("ITERATION_COUNTS")):!s.has("TIMING_FUNCTION")&&l2.has(o)||!s.has("TIMING_FUNCTION")&&u2.some(u=>o.startsWith(`${u}(`))?(n.timingFunction=o,s.add("TIMING_FUNCTION")):!s.has("DURATION")&&hd.test(o)?(n.duration=o,s.add("DURATION")):!s.has("DELAY")&&hd.test(o)?(n.delay=o,s.add("DELAY")):s.has("NAME")?(n.unknown||(n.unknown=[]),n.unknown.push(o)):(n.name=o,s.add("NAME"));return n})}var n2,s2,a2,o2,l2,u2,f2,c2,hd,p2,md=C(()=>{l();n2=new Set(["normal","reverse","alternate","alternate-reverse"]),s2=new Set(["running","paused"]),a2=new Set(["none","forwards","backwards","both"]),o2=new Set(["infinite"]),l2=new Set(["linear","ease","ease-in","ease-out","ease-in-out","step-start","step-end"]),u2=["cubic-bezier","steps"],f2=/\,(?![^(]*\))/g,c2=/\ +(?![^(]*\))/g,hd=/^(-?[\d.]+m?s)$/,p2=/^(\d+)$/});var gd,re,yd=C(()=>{l();gd=r=>Object.assign({},...Object.entries(r??{}).flatMap(([e,t])=>typeof t=="object"?Object.entries(gd(t)).map(([i,n])=>({[e+(i==="DEFAULT"?"":`-${i}`)]:n})):[{[`${e}`]:t}])),re=gd});var bd,wd=C(()=>{bd="3.4.3"});function ot(r,e=!0){return Array.isArray(r)?r.map(t=>{if(e&&Array.isArray(t))throw new Error("The tuple syntax is not supported for `screens`.");if(typeof t=="string")return{name:t.toString(),not:!1,values:[{min:t,max:void 0}]};let[i,n]=t;return i=i.toString(),typeof n=="string"?{name:i,not:!1,values:[{min:n,max:void 0}]}:Array.isArray(n)?{name:i,not:!1,values:n.map(a=>xd(a))}:{name:i,not:!1,values:[xd(n)]}}):ot(Object.entries(r??{}),!1)}function gn(r){return r.values.length!==1?{result:!1,reason:"multiple-values"}:r.values[0].raw!==void 0?{result:!1,reason:"raw-values"}:r.values[0].min!==void 0&&r.values[0].max!==void 0?{result:!1,reason:"min-and-max"}:{result:!0,reason:null}}function vd(r,e,t){let i=yn(e,r),n=yn(t,r),a=gn(i),s=gn(n);if(a.reason==="multiple-values"||s.reason==="multiple-values")throw new Error("Attempted to sort a screen with multiple values. This should never happen. Please open a bug report.");if(a.reason==="raw-values"||s.reason==="raw-values")throw new Error("Attempted to sort a screen with raw values. This should never happen. Please open a bug report.");if(a.reason==="min-and-max"||s.reason==="min-and-max")throw new Error("Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report.");let{min:o,max:u}=i.values[0],{min:c,max:f}=n.values[0];e.not&&([o,u]=[u,o]),t.not&&([c,f]=[f,c]),o=o===void 0?o:parseFloat(o),u=u===void 0?u:parseFloat(u),c=c===void 0?c:parseFloat(c),f=f===void 0?f:parseFloat(f);let[d,p]=r==="min"?[o,c]:[f,u];return d-p}function yn(r,e){return typeof r=="object"?r:{name:"arbitrary-screen",values:[{[e]:r}]}}function xd({"min-width":r,min:e=r,max:t,raw:i}={}){return{min:e,max:t,raw:i}}var wn=C(()=>{l()});function bn(r,e){r.walkDecls(t=>{if(e.includes(t.prop)){t.remove();return}for(let i of e)t.value.includes(`/ var(${i})`)&&(t.value=t.value.replace(`/ var(${i})`,""))})}var kd=C(()=>{l()});var H,Te,Be,Fe,Sd,Cd=C(()=>{l();ze();bt();st();dd();mn();$t();md();yd();fr();ws();At();Jr();wd();Oe();wn();cs();kd();je();dr();ei();H={childVariant:({addVariant:r})=>{r("*","& > *")},pseudoElementVariants:({addVariant:r})=>{r("first-letter","&::first-letter"),r("first-line","&::first-line"),r("marker",[({container:e})=>(bn(e,["--tw-text-opacity"]),"& *::marker"),({container:e})=>(bn(e,["--tw-text-opacity"]),"&::marker")]),r("selection",["& *::selection","&::selection"]),r("file","&::file-selector-button"),r("placeholder","&::placeholder"),r("backdrop","&::backdrop"),r("before",({container:e})=>(e.walkRules(t=>{let i=!1;t.walkDecls("content",()=>{i=!0}),i||t.prepend(j.decl({prop:"content",value:"var(--tw-content)"}))}),"&::before")),r("after",({container:e})=>(e.walkRules(t=>{let i=!1;t.walkDecls("content",()=>{i=!0}),i||t.prepend(j.decl({prop:"content",value:"var(--tw-content)"}))}),"&::after"))},pseudoClassVariants:({addVariant:r,matchVariant:e,config:t,prefix:i})=>{let n=[["first","&:first-child"],["last","&:last-child"],["only","&:only-child"],["odd","&:nth-child(odd)"],["even","&:nth-child(even)"],"first-of-type","last-of-type","only-of-type",["visited",({container:s})=>(bn(s,["--tw-text-opacity","--tw-border-opacity","--tw-bg-opacity"]),"&:visited")],"target",["open","&[open]"],"default","checked","indeterminate","placeholder-shown","autofill","optional","required","valid","invalid","in-range","out-of-range","read-only","empty","focus-within",["hover",K(t(),"hoverOnlyWhenSupported")?"@media (hover: hover) and (pointer: fine) { &:hover }":"&:hover"],"focus","focus-visible","active","enabled","disabled"].map(s=>Array.isArray(s)?s:[s,`&:${s}`]);for(let[s,o]of n)r(s,u=>typeof o=="function"?o(u):o);let a={group:(s,{modifier:o})=>o?[`:merge(${i(".group")}\\/${ce(o)})`," &"]:[`:merge(${i(".group")})`," &"],peer:(s,{modifier:o})=>o?[`:merge(${i(".peer")}\\/${ce(o)})`," ~ &"]:[`:merge(${i(".peer")})`," ~ &"]};for(let[s,o]of Object.entries(a))e(s,(u="",c)=>{let f=L(typeof u=="function"?u(c):u);f.includes("&")||(f="&"+f);let[d,p]=o("",c),m=null,b=null,x=0;for(let y=0;y{r("ltr",'&:where([dir="ltr"], [dir="ltr"] *)'),r("rtl",'&:where([dir="rtl"], [dir="rtl"] *)')},reducedMotionVariants:({addVariant:r})=>{r("motion-safe","@media (prefers-reduced-motion: no-preference)"),r("motion-reduce","@media (prefers-reduced-motion: reduce)")},darkVariants:({config:r,addVariant:e})=>{let[t,i=".dark"]=[].concat(r("darkMode","media"));if(t===!1&&(t="media",F.warn("darkmode-false",["The `darkMode` option in your Tailwind CSS configuration is set to `false`, which now behaves the same as `media`.","Change `darkMode` to `media` or remove it entirely.","https://tailwindcss.com/docs/upgrade-guide#remove-dark-mode-configuration"])),t==="variant"){let n;if(Array.isArray(i)||typeof i=="function"?n=i:typeof i=="string"&&(n=[i]),Array.isArray(n))for(let a of n)a===".dark"?(t=!1,F.warn("darkmode-variant-without-selector",["When using `variant` for `darkMode`, you must provide a selector.",'Example: `darkMode: ["variant", ".your-selector &"]`'])):a.includes("&")||(t=!1,F.warn("darkmode-variant-without-ampersand",["When using `variant` for `darkMode`, your selector must contain `&`.",'Example `darkMode: ["variant", ".your-selector &"]`']));i=n}t==="selector"?e("dark",`&:where(${i}, ${i} *)`):t==="media"?e("dark","@media (prefers-color-scheme: dark)"):t==="variant"?e("dark",i):t==="class"&&e("dark",`&:is(${i} *)`)},printVariant:({addVariant:r})=>{r("print","@media print")},screenVariants:({theme:r,addVariant:e,matchVariant:t})=>{let i=r("screens")??{},n=Object.values(i).every(w=>typeof w=="string"),a=ot(r("screens")),s=new Set([]);function o(w){return w.match(/(\D+)$/)?.[1]??"(none)"}function u(w){w!==void 0&&s.add(o(w))}function c(w){return u(w),s.size===1}for(let w of a)for(let k of w.values)u(k.min),u(k.max);let f=s.size<=1;function d(w){return Object.fromEntries(a.filter(k=>gn(k).result).map(k=>{let{min:S,max:_}=k.values[0];if(w==="min"&&S!==void 0)return k;if(w==="min"&&_!==void 0)return{...k,not:!k.not};if(w==="max"&&_!==void 0)return k;if(w==="max"&&S!==void 0)return{...k,not:!k.not}}).map(k=>[k.name,k]))}function p(w){return(k,S)=>vd(w,k.value,S.value)}let m=p("max"),b=p("min");function x(w){return k=>{if(n)if(f){if(typeof k=="string"&&!c(k))return F.warn("minmax-have-mixed-units",["The `min-*` and `max-*` variants are not supported with a `screens` configuration containing mixed units."]),[]}else return F.warn("mixed-screen-units",["The `min-*` and `max-*` variants are not supported with a `screens` configuration containing mixed units."]),[];else return F.warn("complex-screen-config",["The `min-*` and `max-*` variants are not supported with a `screens` configuration containing objects."]),[];return[`@media ${at(yn(k,w))}`]}}t("max",x("max"),{sort:m,values:n?d("max"):{}});let y="min-screens";for(let w of a)e(w.name,`@media ${at(w)}`,{id:y,sort:n&&f?b:void 0,value:w});t("min",x("min"),{id:y,sort:b})},supportsVariants:({matchVariant:r,theme:e})=>{r("supports",(t="")=>{let i=L(t),n=/^\w*\s*\(/.test(i);return i=n?i.replace(/\b(and|or|not)\b/g," $1 "):i,n?`@supports ${i}`:(i.includes(":")||(i=`${i}: var(--tw)`),i.startsWith("(")&&i.endsWith(")")||(i=`(${i})`),`@supports ${i}`)},{values:e("supports")??{}})},hasVariants:({matchVariant:r})=>{r("has",e=>`&:has(${L(e)})`,{values:{}}),r("group-has",(e,{modifier:t})=>t?`:merge(.group\\/${t}):has(${L(e)}) &`:`:merge(.group):has(${L(e)}) &`,{values:{}}),r("peer-has",(e,{modifier:t})=>t?`:merge(.peer\\/${t}):has(${L(e)}) ~ &`:`:merge(.peer):has(${L(e)}) ~ &`,{values:{}})},ariaVariants:({matchVariant:r,theme:e})=>{r("aria",t=>`&[aria-${L(t)}]`,{values:e("aria")??{}}),r("group-aria",(t,{modifier:i})=>i?`:merge(.group\\/${i})[aria-${L(t)}] &`:`:merge(.group)[aria-${L(t)}] &`,{values:e("aria")??{}}),r("peer-aria",(t,{modifier:i})=>i?`:merge(.peer\\/${i})[aria-${L(t)}] ~ &`:`:merge(.peer)[aria-${L(t)}] ~ &`,{values:e("aria")??{}})},dataVariants:({matchVariant:r,theme:e})=>{r("data",t=>`&[data-${L(t)}]`,{values:e("data")??{}}),r("group-data",(t,{modifier:i})=>i?`:merge(.group\\/${i})[data-${L(t)}] &`:`:merge(.group)[data-${L(t)}] &`,{values:e("data")??{}}),r("peer-data",(t,{modifier:i})=>i?`:merge(.peer\\/${i})[data-${L(t)}] ~ &`:`:merge(.peer)[data-${L(t)}] ~ &`,{values:e("data")??{}})},orientationVariants:({addVariant:r})=>{r("portrait","@media (orientation: portrait)"),r("landscape","@media (orientation: landscape)")},prefersContrastVariants:({addVariant:r})=>{r("contrast-more","@media (prefers-contrast: more)"),r("contrast-less","@media (prefers-contrast: less)")},forcedColorsVariants:({addVariant:r})=>{r("forced-colors","@media (forced-colors: active)")}},Te=["translate(var(--tw-translate-x), var(--tw-translate-y))","rotate(var(--tw-rotate))","skewX(var(--tw-skew-x))","skewY(var(--tw-skew-y))","scaleX(var(--tw-scale-x))","scaleY(var(--tw-scale-y))"].join(" "),Be=["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(" "),Fe=["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(" "),Sd={preflight:({addBase:r})=>{let e=j.parse(`*,::after,::before{box-sizing:border-box;border-width:0;border-style:solid;border-color:theme('borderColor.DEFAULT', currentColor)}::after,::before{--tw-content:''}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:theme('fontFamily.sans', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:theme('fontFamily.sans[1].fontFeatureSettings', normal);font-variation-settings:theme('fontFamily.sans[1].fontVariationSettings', normal);-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:theme('fontFamily.mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:theme('fontFamily.mono[1].fontFeatureSettings', normal);font-variation-settings:theme('fontFamily.mono[1].fontVariationSettings', normal);font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:theme('colors.gray.4', #9ca3af)}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}`);r([j.comment({text:`! tailwindcss v${bd} | MIT License | https://tailwindcss.com`}),...e.nodes])},container:(()=>{function r(t=[]){return t.flatMap(i=>i.values.map(n=>n.min)).filter(i=>i!==void 0)}function e(t,i,n){if(typeof n=="undefined")return[];if(!(typeof n=="object"&&n!==null))return[{screen:"DEFAULT",minWidth:0,padding:n}];let a=[];n.DEFAULT&&a.push({screen:"DEFAULT",minWidth:0,padding:n.DEFAULT});for(let s of t)for(let o of i)for(let{min:u}of o.values)u===s&&a.push({minWidth:s,padding:n[o.name]});return a}return function({addComponents:t,theme:i}){let n=ot(i("container.screens",i("screens"))),a=r(n),s=e(a,n,i("container.padding")),o=c=>{let f=s.find(d=>d.minWidth===c);return f?{paddingRight:f.padding,paddingLeft:f.padding}:{}},u=Array.from(new Set(a.slice().sort((c,f)=>parseInt(c)-parseInt(f)))).map(c=>({[`@media (min-width: ${c})`]:{".container":{"max-width":c,...o(c)}}}));t([{".container":Object.assign({width:"100%"},i("container.center",!1)?{marginRight:"auto",marginLeft:"auto"}:{},o(0))},...u])}})(),accessibility:({addUtilities:r})=>{r({".sr-only":{position:"absolute",width:"1px",height:"1px",padding:"0",margin:"-1px",overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",borderWidth:"0"},".not-sr-only":{position:"static",width:"auto",height:"auto",padding:"0",margin:"0",overflow:"visible",clip:"auto",whiteSpace:"normal"}})},pointerEvents:({addUtilities:r})=>{r({".pointer-events-none":{"pointer-events":"none"},".pointer-events-auto":{"pointer-events":"auto"}})},visibility:({addUtilities:r})=>{r({".visible":{visibility:"visible"},".invisible":{visibility:"hidden"},".collapse":{visibility:"collapse"}})},position:({addUtilities:r})=>{r({".static":{position:"static"},".fixed":{position:"fixed"},".absolute":{position:"absolute"},".relative":{position:"relative"},".sticky":{position:"sticky"}})},inset:P("inset",[["inset",["inset"]],[["inset-x",["left","right"]],["inset-y",["top","bottom"]]],[["start",["inset-inline-start"]],["end",["inset-inline-end"]],["top",["top"]],["right",["right"]],["bottom",["bottom"]],["left",["left"]]]],{supportsNegativeValues:!0}),isolation:({addUtilities:r})=>{r({".isolate":{isolation:"isolate"},".isolation-auto":{isolation:"auto"}})},zIndex:P("zIndex",[["z",["zIndex"]]],{supportsNegativeValues:!0}),order:P("order",void 0,{supportsNegativeValues:!0}),gridColumn:P("gridColumn",[["col",["gridColumn"]]]),gridColumnStart:P("gridColumnStart",[["col-start",["gridColumnStart"]]]),gridColumnEnd:P("gridColumnEnd",[["col-end",["gridColumnEnd"]]]),gridRow:P("gridRow",[["row",["gridRow"]]]),gridRowStart:P("gridRowStart",[["row-start",["gridRowStart"]]]),gridRowEnd:P("gridRowEnd",[["row-end",["gridRowEnd"]]]),float:({addUtilities:r})=>{r({".float-start":{float:"inline-start"},".float-end":{float:"inline-end"},".float-right":{float:"right"},".float-left":{float:"left"},".float-none":{float:"none"}})},clear:({addUtilities:r})=>{r({".clear-start":{clear:"inline-start"},".clear-end":{clear:"inline-end"},".clear-left":{clear:"left"},".clear-right":{clear:"right"},".clear-both":{clear:"both"},".clear-none":{clear:"none"}})},margin:P("margin",[["m",["margin"]],[["mx",["margin-left","margin-right"]],["my",["margin-top","margin-bottom"]]],[["ms",["margin-inline-start"]],["me",["margin-inline-end"]],["mt",["margin-top"]],["mr",["margin-right"]],["mb",["margin-bottom"]],["ml",["margin-left"]]]],{supportsNegativeValues:!0}),boxSizing:({addUtilities:r})=>{r({".box-border":{"box-sizing":"border-box"},".box-content":{"box-sizing":"content-box"}})},lineClamp:({matchUtilities:r,addUtilities:e,theme:t})=>{r({"line-clamp":i=>({overflow:"hidden",display:"-webkit-box","-webkit-box-orient":"vertical","-webkit-line-clamp":`${i}`})},{values:t("lineClamp")}),e({".line-clamp-none":{overflow:"visible",display:"block","-webkit-box-orient":"horizontal","-webkit-line-clamp":"none"}})},display:({addUtilities:r})=>{r({".block":{display:"block"},".inline-block":{display:"inline-block"},".inline":{display:"inline"},".flex":{display:"flex"},".inline-flex":{display:"inline-flex"},".table":{display:"table"},".inline-table":{display:"inline-table"},".table-caption":{display:"table-caption"},".table-cell":{display:"table-cell"},".table-column":{display:"table-column"},".table-column-group":{display:"table-column-group"},".table-footer-group":{display:"table-footer-group"},".table-header-group":{display:"table-header-group"},".table-row-group":{display:"table-row-group"},".table-row":{display:"table-row"},".flow-root":{display:"flow-root"},".grid":{display:"grid"},".inline-grid":{display:"inline-grid"},".contents":{display:"contents"},".list-item":{display:"list-item"},".hidden":{display:"none"}})},aspectRatio:P("aspectRatio",[["aspect",["aspect-ratio"]]]),size:P("size",[["size",["width","height"]]]),height:P("height",[["h",["height"]]]),maxHeight:P("maxHeight",[["max-h",["maxHeight"]]]),minHeight:P("minHeight",[["min-h",["minHeight"]]]),width:P("width",[["w",["width"]]]),minWidth:P("minWidth",[["min-w",["minWidth"]]]),maxWidth:P("maxWidth",[["max-w",["maxWidth"]]]),flex:P("flex"),flexShrink:P("flexShrink",[["flex-shrink",["flex-shrink"]],["shrink",["flex-shrink"]]]),flexGrow:P("flexGrow",[["flex-grow",["flex-grow"]],["grow",["flex-grow"]]]),flexBasis:P("flexBasis",[["basis",["flex-basis"]]]),tableLayout:({addUtilities:r})=>{r({".table-auto":{"table-layout":"auto"},".table-fixed":{"table-layout":"fixed"}})},captionSide:({addUtilities:r})=>{r({".caption-top":{"caption-side":"top"},".caption-bottom":{"caption-side":"bottom"}})},borderCollapse:({addUtilities:r})=>{r({".border-collapse":{"border-collapse":"collapse"},".border-separate":{"border-collapse":"separate"}})},borderSpacing:({addDefaults:r,matchUtilities:e,theme:t})=>{r("border-spacing",{"--tw-border-spacing-x":0,"--tw-border-spacing-y":0}),e({"border-spacing":i=>({"--tw-border-spacing-x":i,"--tw-border-spacing-y":i,"@defaults border-spacing":{},"border-spacing":"var(--tw-border-spacing-x) var(--tw-border-spacing-y)"}),"border-spacing-x":i=>({"--tw-border-spacing-x":i,"@defaults border-spacing":{},"border-spacing":"var(--tw-border-spacing-x) var(--tw-border-spacing-y)"}),"border-spacing-y":i=>({"--tw-border-spacing-y":i,"@defaults border-spacing":{},"border-spacing":"var(--tw-border-spacing-x) var(--tw-border-spacing-y)"})},{values:t("borderSpacing")})},transformOrigin:P("transformOrigin",[["origin",["transformOrigin"]]]),translate:P("translate",[[["translate-x",[["@defaults transform",{}],"--tw-translate-x",["transform",Te]]],["translate-y",[["@defaults transform",{}],"--tw-translate-y",["transform",Te]]]]],{supportsNegativeValues:!0}),rotate:P("rotate",[["rotate",[["@defaults transform",{}],"--tw-rotate",["transform",Te]]]],{supportsNegativeValues:!0}),skew:P("skew",[[["skew-x",[["@defaults transform",{}],"--tw-skew-x",["transform",Te]]],["skew-y",[["@defaults transform",{}],"--tw-skew-y",["transform",Te]]]]],{supportsNegativeValues:!0}),scale:P("scale",[["scale",[["@defaults transform",{}],"--tw-scale-x","--tw-scale-y",["transform",Te]]],[["scale-x",[["@defaults transform",{}],"--tw-scale-x",["transform",Te]]],["scale-y",[["@defaults transform",{}],"--tw-scale-y",["transform",Te]]]]],{supportsNegativeValues:!0}),transform:({addDefaults:r,addUtilities:e})=>{r("transform",{"--tw-translate-x":"0","--tw-translate-y":"0","--tw-rotate":"0","--tw-skew-x":"0","--tw-skew-y":"0","--tw-scale-x":"1","--tw-scale-y":"1"}),e({".transform":{"@defaults transform":{},transform:Te},".transform-cpu":{transform:Te},".transform-gpu":{transform:Te.replace("translate(var(--tw-translate-x), var(--tw-translate-y))","translate3d(var(--tw-translate-x), var(--tw-translate-y), 0)")},".transform-none":{transform:"none"}})},animation:({matchUtilities:r,theme:e,config:t})=>{let i=a=>ce(t("prefix")+a),n=Object.fromEntries(Object.entries(e("keyframes")??{}).map(([a,s])=>[a,{[`@keyframes ${i(a)}`]:s}]));r({animate:a=>{let s=Ka(a);return[...s.flatMap(o=>n[o.name]),{animation:s.map(({name:o,value:u})=>o===void 0||n[o]===void 0?u:u.replace(o,i(o))).join(", ")}]}},{values:e("animation")})},cursor:P("cursor"),touchAction:({addDefaults:r,addUtilities:e})=>{r("touch-action",{"--tw-pan-x":" ","--tw-pan-y":" ","--tw-pinch-zoom":" "});let t="var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)";e({".touch-auto":{"touch-action":"auto"},".touch-none":{"touch-action":"none"},".touch-pan-x":{"@defaults touch-action":{},"--tw-pan-x":"pan-x","touch-action":t},".touch-pan-left":{"@defaults touch-action":{},"--tw-pan-x":"pan-left","touch-action":t},".touch-pan-right":{"@defaults touch-action":{},"--tw-pan-x":"pan-right","touch-action":t},".touch-pan-y":{"@defaults touch-action":{},"--tw-pan-y":"pan-y","touch-action":t},".touch-pan-up":{"@defaults touch-action":{},"--tw-pan-y":"pan-up","touch-action":t},".touch-pan-down":{"@defaults touch-action":{},"--tw-pan-y":"pan-down","touch-action":t},".touch-pinch-zoom":{"@defaults touch-action":{},"--tw-pinch-zoom":"pinch-zoom","touch-action":t},".touch-manipulation":{"touch-action":"manipulation"}})},userSelect:({addUtilities:r})=>{r({".select-none":{"user-select":"none"},".select-text":{"user-select":"text"},".select-all":{"user-select":"all"},".select-auto":{"user-select":"auto"}})},resize:({addUtilities:r})=>{r({".resize-none":{resize:"none"},".resize-y":{resize:"vertical"},".resize-x":{resize:"horizontal"},".resize":{resize:"both"}})},scrollSnapType:({addDefaults:r,addUtilities:e})=>{r("scroll-snap-type",{"--tw-scroll-snap-strictness":"proximity"}),e({".snap-none":{"scroll-snap-type":"none"},".snap-x":{"@defaults scroll-snap-type":{},"scroll-snap-type":"x var(--tw-scroll-snap-strictness)"},".snap-y":{"@defaults scroll-snap-type":{},"scroll-snap-type":"y var(--tw-scroll-snap-strictness)"},".snap-both":{"@defaults scroll-snap-type":{},"scroll-snap-type":"both var(--tw-scroll-snap-strictness)"},".snap-mandatory":{"--tw-scroll-snap-strictness":"mandatory"},".snap-proximity":{"--tw-scroll-snap-strictness":"proximity"}})},scrollSnapAlign:({addUtilities:r})=>{r({".snap-start":{"scroll-snap-align":"start"},".snap-end":{"scroll-snap-align":"end"},".snap-center":{"scroll-snap-align":"center"},".snap-align-none":{"scroll-snap-align":"none"}})},scrollSnapStop:({addUtilities:r})=>{r({".snap-normal":{"scroll-snap-stop":"normal"},".snap-always":{"scroll-snap-stop":"always"}})},scrollMargin:P("scrollMargin",[["scroll-m",["scroll-margin"]],[["scroll-mx",["scroll-margin-left","scroll-margin-right"]],["scroll-my",["scroll-margin-top","scroll-margin-bottom"]]],[["scroll-ms",["scroll-margin-inline-start"]],["scroll-me",["scroll-margin-inline-end"]],["scroll-mt",["scroll-margin-top"]],["scroll-mr",["scroll-margin-right"]],["scroll-mb",["scroll-margin-bottom"]],["scroll-ml",["scroll-margin-left"]]]],{supportsNegativeValues:!0}),scrollPadding:P("scrollPadding",[["scroll-p",["scroll-padding"]],[["scroll-px",["scroll-padding-left","scroll-padding-right"]],["scroll-py",["scroll-padding-top","scroll-padding-bottom"]]],[["scroll-ps",["scroll-padding-inline-start"]],["scroll-pe",["scroll-padding-inline-end"]],["scroll-pt",["scroll-padding-top"]],["scroll-pr",["scroll-padding-right"]],["scroll-pb",["scroll-padding-bottom"]],["scroll-pl",["scroll-padding-left"]]]]),listStylePosition:({addUtilities:r})=>{r({".list-inside":{"list-style-position":"inside"},".list-outside":{"list-style-position":"outside"}})},listStyleType:P("listStyleType",[["list",["listStyleType"]]]),listStyleImage:P("listStyleImage",[["list-image",["listStyleImage"]]]),appearance:({addUtilities:r})=>{r({".appearance-none":{appearance:"none"},".appearance-auto":{appearance:"auto"}})},columns:P("columns",[["columns",["columns"]]]),breakBefore:({addUtilities:r})=>{r({".break-before-auto":{"break-before":"auto"},".break-before-avoid":{"break-before":"avoid"},".break-before-all":{"break-before":"all"},".break-before-avoid-page":{"break-before":"avoid-page"},".break-before-page":{"break-before":"page"},".break-before-left":{"break-before":"left"},".break-before-right":{"break-before":"right"},".break-before-column":{"break-before":"column"}})},breakInside:({addUtilities:r})=>{r({".break-inside-auto":{"break-inside":"auto"},".break-inside-avoid":{"break-inside":"avoid"},".break-inside-avoid-page":{"break-inside":"avoid-page"},".break-inside-avoid-column":{"break-inside":"avoid-column"}})},breakAfter:({addUtilities:r})=>{r({".break-after-auto":{"break-after":"auto"},".break-after-avoid":{"break-after":"avoid"},".break-after-all":{"break-after":"all"},".break-after-avoid-page":{"break-after":"avoid-page"},".break-after-page":{"break-after":"page"},".break-after-left":{"break-after":"left"},".break-after-right":{"break-after":"right"},".break-after-column":{"break-after":"column"}})},gridAutoColumns:P("gridAutoColumns",[["auto-cols",["gridAutoColumns"]]]),gridAutoFlow:({addUtilities:r})=>{r({".grid-flow-row":{gridAutoFlow:"row"},".grid-flow-col":{gridAutoFlow:"column"},".grid-flow-dense":{gridAutoFlow:"dense"},".grid-flow-row-dense":{gridAutoFlow:"row dense"},".grid-flow-col-dense":{gridAutoFlow:"column dense"}})},gridAutoRows:P("gridAutoRows",[["auto-rows",["gridAutoRows"]]]),gridTemplateColumns:P("gridTemplateColumns",[["grid-cols",["gridTemplateColumns"]]]),gridTemplateRows:P("gridTemplateRows",[["grid-rows",["gridTemplateRows"]]]),flexDirection:({addUtilities:r})=>{r({".flex-row":{"flex-direction":"row"},".flex-row-reverse":{"flex-direction":"row-reverse"},".flex-col":{"flex-direction":"column"},".flex-col-reverse":{"flex-direction":"column-reverse"}})},flexWrap:({addUtilities:r})=>{r({".flex-wrap":{"flex-wrap":"wrap"},".flex-wrap-reverse":{"flex-wrap":"wrap-reverse"},".flex-nowrap":{"flex-wrap":"nowrap"}})},placeContent:({addUtilities:r})=>{r({".place-content-center":{"place-content":"center"},".place-content-start":{"place-content":"start"},".place-content-end":{"place-content":"end"},".place-content-between":{"place-content":"space-between"},".place-content-around":{"place-content":"space-around"},".place-content-evenly":{"place-content":"space-evenly"},".place-content-baseline":{"place-content":"baseline"},".place-content-stretch":{"place-content":"stretch"}})},placeItems:({addUtilities:r})=>{r({".place-items-start":{"place-items":"start"},".place-items-end":{"place-items":"end"},".place-items-center":{"place-items":"center"},".place-items-baseline":{"place-items":"baseline"},".place-items-stretch":{"place-items":"stretch"}})},alignContent:({addUtilities:r})=>{r({".content-normal":{"align-content":"normal"},".content-center":{"align-content":"center"},".content-start":{"align-content":"flex-start"},".content-end":{"align-content":"flex-end"},".content-between":{"align-content":"space-between"},".content-around":{"align-content":"space-around"},".content-evenly":{"align-content":"space-evenly"},".content-baseline":{"align-content":"baseline"},".content-stretch":{"align-content":"stretch"}})},alignItems:({addUtilities:r})=>{r({".items-start":{"align-items":"flex-start"},".items-end":{"align-items":"flex-end"},".items-center":{"align-items":"center"},".items-baseline":{"align-items":"baseline"},".items-stretch":{"align-items":"stretch"}})},justifyContent:({addUtilities:r})=>{r({".justify-normal":{"justify-content":"normal"},".justify-start":{"justify-content":"flex-start"},".justify-end":{"justify-content":"flex-end"},".justify-center":{"justify-content":"center"},".justify-between":{"justify-content":"space-between"},".justify-around":{"justify-content":"space-around"},".justify-evenly":{"justify-content":"space-evenly"},".justify-stretch":{"justify-content":"stretch"}})},justifyItems:({addUtilities:r})=>{r({".justify-items-start":{"justify-items":"start"},".justify-items-end":{"justify-items":"end"},".justify-items-center":{"justify-items":"center"},".justify-items-stretch":{"justify-items":"stretch"}})},gap:P("gap",[["gap",["gap"]],[["gap-x",["columnGap"]],["gap-y",["rowGap"]]]]),space:({matchUtilities:r,addUtilities:e,theme:t})=>{r({"space-x":i=>(i=i==="0"?"0px":i,{"& > :not([hidden]) ~ :not([hidden])":{"--tw-space-x-reverse":"0","margin-right":`calc(${i} * var(--tw-space-x-reverse))`,"margin-left":`calc(${i} * calc(1 - var(--tw-space-x-reverse)))`}}),"space-y":i=>(i=i==="0"?"0px":i,{"& > :not([hidden]) ~ :not([hidden])":{"--tw-space-y-reverse":"0","margin-top":`calc(${i} * calc(1 - var(--tw-space-y-reverse)))`,"margin-bottom":`calc(${i} * var(--tw-space-y-reverse))`}})},{values:t("space"),supportsNegativeValues:!0}),e({".space-y-reverse > :not([hidden]) ~ :not([hidden])":{"--tw-space-y-reverse":"1"},".space-x-reverse > :not([hidden]) ~ :not([hidden])":{"--tw-space-x-reverse":"1"}})},divideWidth:({matchUtilities:r,addUtilities:e,theme:t})=>{r({"divide-x":i=>(i=i==="0"?"0px":i,{"& > :not([hidden]) ~ :not([hidden])":{"@defaults border-width":{},"--tw-divide-x-reverse":"0","border-right-width":`calc(${i} * var(--tw-divide-x-reverse))`,"border-left-width":`calc(${i} * calc(1 - var(--tw-divide-x-reverse)))`}}),"divide-y":i=>(i=i==="0"?"0px":i,{"& > :not([hidden]) ~ :not([hidden])":{"@defaults border-width":{},"--tw-divide-y-reverse":"0","border-top-width":`calc(${i} * calc(1 - var(--tw-divide-y-reverse)))`,"border-bottom-width":`calc(${i} * var(--tw-divide-y-reverse))`}})},{values:t("divideWidth"),type:["line-width","length","any"]}),e({".divide-y-reverse > :not([hidden]) ~ :not([hidden])":{"@defaults border-width":{},"--tw-divide-y-reverse":"1"},".divide-x-reverse > :not([hidden]) ~ :not([hidden])":{"@defaults border-width":{},"--tw-divide-x-reverse":"1"}})},divideStyle:({addUtilities:r})=>{r({".divide-solid > :not([hidden]) ~ :not([hidden])":{"border-style":"solid"},".divide-dashed > :not([hidden]) ~ :not([hidden])":{"border-style":"dashed"},".divide-dotted > :not([hidden]) ~ :not([hidden])":{"border-style":"dotted"},".divide-double > :not([hidden]) ~ :not([hidden])":{"border-style":"double"},".divide-none > :not([hidden]) ~ :not([hidden])":{"border-style":"none"}})},divideColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({divide:i=>t("divideOpacity")?{["& > :not([hidden]) ~ :not([hidden])"]:se({color:i,property:"border-color",variable:"--tw-divide-opacity"})}:{["& > :not([hidden]) ~ :not([hidden])"]:{"border-color":N(i)}}},{values:(({DEFAULT:i,...n})=>n)(re(e("divideColor"))),type:["color","any"]})},divideOpacity:({matchUtilities:r,theme:e})=>{r({"divide-opacity":t=>({["& > :not([hidden]) ~ :not([hidden])"]:{"--tw-divide-opacity":t}})},{values:e("divideOpacity")})},placeSelf:({addUtilities:r})=>{r({".place-self-auto":{"place-self":"auto"},".place-self-start":{"place-self":"start"},".place-self-end":{"place-self":"end"},".place-self-center":{"place-self":"center"},".place-self-stretch":{"place-self":"stretch"}})},alignSelf:({addUtilities:r})=>{r({".self-auto":{"align-self":"auto"},".self-start":{"align-self":"flex-start"},".self-end":{"align-self":"flex-end"},".self-center":{"align-self":"center"},".self-stretch":{"align-self":"stretch"},".self-baseline":{"align-self":"baseline"}})},justifySelf:({addUtilities:r})=>{r({".justify-self-auto":{"justify-self":"auto"},".justify-self-start":{"justify-self":"start"},".justify-self-end":{"justify-self":"end"},".justify-self-center":{"justify-self":"center"},".justify-self-stretch":{"justify-self":"stretch"}})},overflow:({addUtilities:r})=>{r({".overflow-auto":{overflow:"auto"},".overflow-hidden":{overflow:"hidden"},".overflow-clip":{overflow:"clip"},".overflow-visible":{overflow:"visible"},".overflow-scroll":{overflow:"scroll"},".overflow-x-auto":{"overflow-x":"auto"},".overflow-y-auto":{"overflow-y":"auto"},".overflow-x-hidden":{"overflow-x":"hidden"},".overflow-y-hidden":{"overflow-y":"hidden"},".overflow-x-clip":{"overflow-x":"clip"},".overflow-y-clip":{"overflow-y":"clip"},".overflow-x-visible":{"overflow-x":"visible"},".overflow-y-visible":{"overflow-y":"visible"},".overflow-x-scroll":{"overflow-x":"scroll"},".overflow-y-scroll":{"overflow-y":"scroll"}})},overscrollBehavior:({addUtilities:r})=>{r({".overscroll-auto":{"overscroll-behavior":"auto"},".overscroll-contain":{"overscroll-behavior":"contain"},".overscroll-none":{"overscroll-behavior":"none"},".overscroll-y-auto":{"overscroll-behavior-y":"auto"},".overscroll-y-contain":{"overscroll-behavior-y":"contain"},".overscroll-y-none":{"overscroll-behavior-y":"none"},".overscroll-x-auto":{"overscroll-behavior-x":"auto"},".overscroll-x-contain":{"overscroll-behavior-x":"contain"},".overscroll-x-none":{"overscroll-behavior-x":"none"}})},scrollBehavior:({addUtilities:r})=>{r({".scroll-auto":{"scroll-behavior":"auto"},".scroll-smooth":{"scroll-behavior":"smooth"}})},textOverflow:({addUtilities:r})=>{r({".truncate":{overflow:"hidden","text-overflow":"ellipsis","white-space":"nowrap"},".overflow-ellipsis":{"text-overflow":"ellipsis"},".text-ellipsis":{"text-overflow":"ellipsis"},".text-clip":{"text-overflow":"clip"}})},hyphens:({addUtilities:r})=>{r({".hyphens-none":{hyphens:"none"},".hyphens-manual":{hyphens:"manual"},".hyphens-auto":{hyphens:"auto"}})},whitespace:({addUtilities:r})=>{r({".whitespace-normal":{"white-space":"normal"},".whitespace-nowrap":{"white-space":"nowrap"},".whitespace-pre":{"white-space":"pre"},".whitespace-pre-line":{"white-space":"pre-line"},".whitespace-pre-wrap":{"white-space":"pre-wrap"},".whitespace-break-spaces":{"white-space":"break-spaces"}})},textWrap:({addUtilities:r})=>{r({".text-wrap":{"text-wrap":"wrap"},".text-nowrap":{"text-wrap":"nowrap"},".text-balance":{"text-wrap":"balance"},".text-pretty":{"text-wrap":"pretty"}})},wordBreak:({addUtilities:r})=>{r({".break-normal":{"overflow-wrap":"normal","word-break":"normal"},".break-words":{"overflow-wrap":"break-word"},".break-all":{"word-break":"break-all"},".break-keep":{"word-break":"keep-all"}})},borderRadius:P("borderRadius",[["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"]]]]),borderWidth:P("borderWidth",[["border",[["@defaults border-width",{}],"border-width"]],[["border-x",[["@defaults border-width",{}],"border-left-width","border-right-width"]],["border-y",[["@defaults border-width",{}],"border-top-width","border-bottom-width"]]],[["border-s",[["@defaults border-width",{}],"border-inline-start-width"]],["border-e",[["@defaults border-width",{}],"border-inline-end-width"]],["border-t",[["@defaults border-width",{}],"border-top-width"]],["border-r",[["@defaults border-width",{}],"border-right-width"]],["border-b",[["@defaults border-width",{}],"border-bottom-width"]],["border-l",[["@defaults border-width",{}],"border-left-width"]]]],{type:["line-width","length"]}),borderStyle:({addUtilities:r})=>{r({".border-solid":{"border-style":"solid"},".border-dashed":{"border-style":"dashed"},".border-dotted":{"border-style":"dotted"},".border-double":{"border-style":"double"},".border-hidden":{"border-style":"hidden"},".border-none":{"border-style":"none"}})},borderColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({border:i=>t("borderOpacity")?se({color:i,property:"border-color",variable:"--tw-border-opacity"}):{"border-color":N(i)}},{values:(({DEFAULT:i,...n})=>n)(re(e("borderColor"))),type:["color","any"]}),r({"border-x":i=>t("borderOpacity")?se({color:i,property:["border-left-color","border-right-color"],variable:"--tw-border-opacity"}):{"border-left-color":N(i),"border-right-color":N(i)},"border-y":i=>t("borderOpacity")?se({color:i,property:["border-top-color","border-bottom-color"],variable:"--tw-border-opacity"}):{"border-top-color":N(i),"border-bottom-color":N(i)}},{values:(({DEFAULT:i,...n})=>n)(re(e("borderColor"))),type:["color","any"]}),r({"border-s":i=>t("borderOpacity")?se({color:i,property:"border-inline-start-color",variable:"--tw-border-opacity"}):{"border-inline-start-color":N(i)},"border-e":i=>t("borderOpacity")?se({color:i,property:"border-inline-end-color",variable:"--tw-border-opacity"}):{"border-inline-end-color":N(i)},"border-t":i=>t("borderOpacity")?se({color:i,property:"border-top-color",variable:"--tw-border-opacity"}):{"border-top-color":N(i)},"border-r":i=>t("borderOpacity")?se({color:i,property:"border-right-color",variable:"--tw-border-opacity"}):{"border-right-color":N(i)},"border-b":i=>t("borderOpacity")?se({color:i,property:"border-bottom-color",variable:"--tw-border-opacity"}):{"border-bottom-color":N(i)},"border-l":i=>t("borderOpacity")?se({color:i,property:"border-left-color",variable:"--tw-border-opacity"}):{"border-left-color":N(i)}},{values:(({DEFAULT:i,...n})=>n)(re(e("borderColor"))),type:["color","any"]})},borderOpacity:P("borderOpacity",[["border-opacity",["--tw-border-opacity"]]]),backgroundColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({bg:i=>t("backgroundOpacity")?se({color:i,property:"background-color",variable:"--tw-bg-opacity"}):{"background-color":N(i)}},{values:re(e("backgroundColor")),type:["color","any"]})},backgroundOpacity:P("backgroundOpacity",[["bg-opacity",["--tw-bg-opacity"]]]),backgroundImage:P("backgroundImage",[["bg",["background-image"]]],{type:["lookup","image","url"]}),gradientColorStops:(()=>{function r(e){return Ie(e,0,"rgb(255 255 255 / 0)")}return function({matchUtilities:e,theme:t,addDefaults:i}){i("gradient-color-stops",{"--tw-gradient-from-position":" ","--tw-gradient-via-position":" ","--tw-gradient-to-position":" "});let n={values:re(t("gradientColorStops")),type:["color","any"]},a={values:t("gradientColorStopPositions"),type:["length","percentage"]};e({from:s=>{let o=r(s);return{"@defaults gradient-color-stops":{},"--tw-gradient-from":`${N(s)} var(--tw-gradient-from-position)`,"--tw-gradient-to":`${o} var(--tw-gradient-to-position)`,"--tw-gradient-stops":"var(--tw-gradient-from), var(--tw-gradient-to)"}}},n),e({from:s=>({"--tw-gradient-from-position":s})},a),e({via:s=>{let o=r(s);return{"@defaults gradient-color-stops":{},"--tw-gradient-to":`${o} var(--tw-gradient-to-position)`,"--tw-gradient-stops":`var(--tw-gradient-from), ${N(s)} var(--tw-gradient-via-position), var(--tw-gradient-to)`}}},n),e({via:s=>({"--tw-gradient-via-position":s})},a),e({to:s=>({"@defaults gradient-color-stops":{},"--tw-gradient-to":`${N(s)} var(--tw-gradient-to-position)`})},n),e({to:s=>({"--tw-gradient-to-position":s})},a)}})(),boxDecorationBreak:({addUtilities:r})=>{r({".decoration-slice":{"box-decoration-break":"slice"},".decoration-clone":{"box-decoration-break":"clone"},".box-decoration-slice":{"box-decoration-break":"slice"},".box-decoration-clone":{"box-decoration-break":"clone"}})},backgroundSize:P("backgroundSize",[["bg",["background-size"]]],{type:["lookup","length","percentage","size"]}),backgroundAttachment:({addUtilities:r})=>{r({".bg-fixed":{"background-attachment":"fixed"},".bg-local":{"background-attachment":"local"},".bg-scroll":{"background-attachment":"scroll"}})},backgroundClip:({addUtilities:r})=>{r({".bg-clip-border":{"background-clip":"border-box"},".bg-clip-padding":{"background-clip":"padding-box"},".bg-clip-content":{"background-clip":"content-box"},".bg-clip-text":{"background-clip":"text"}})},backgroundPosition:P("backgroundPosition",[["bg",["background-position"]]],{type:["lookup",["position",{preferOnConflict:!0}]]}),backgroundRepeat:({addUtilities:r})=>{r({".bg-repeat":{"background-repeat":"repeat"},".bg-no-repeat":{"background-repeat":"no-repeat"},".bg-repeat-x":{"background-repeat":"repeat-x"},".bg-repeat-y":{"background-repeat":"repeat-y"},".bg-repeat-round":{"background-repeat":"round"},".bg-repeat-space":{"background-repeat":"space"}})},backgroundOrigin:({addUtilities:r})=>{r({".bg-origin-border":{"background-origin":"border-box"},".bg-origin-padding":{"background-origin":"padding-box"},".bg-origin-content":{"background-origin":"content-box"}})},fill:({matchUtilities:r,theme:e})=>{r({fill:t=>({fill:N(t)})},{values:re(e("fill")),type:["color","any"]})},stroke:({matchUtilities:r,theme:e})=>{r({stroke:t=>({stroke:N(t)})},{values:re(e("stroke")),type:["color","url","any"]})},strokeWidth:P("strokeWidth",[["stroke",["stroke-width"]]],{type:["length","number","percentage"]}),objectFit:({addUtilities:r})=>{r({".object-contain":{"object-fit":"contain"},".object-cover":{"object-fit":"cover"},".object-fill":{"object-fit":"fill"},".object-none":{"object-fit":"none"},".object-scale-down":{"object-fit":"scale-down"}})},objectPosition:P("objectPosition",[["object",["object-position"]]]),padding:P("padding",[["p",["padding"]],[["px",["padding-left","padding-right"]],["py",["padding-top","padding-bottom"]]],[["ps",["padding-inline-start"]],["pe",["padding-inline-end"]],["pt",["padding-top"]],["pr",["padding-right"]],["pb",["padding-bottom"]],["pl",["padding-left"]]]]),textAlign:({addUtilities:r})=>{r({".text-left":{"text-align":"left"},".text-center":{"text-align":"center"},".text-right":{"text-align":"right"},".text-justify":{"text-align":"justify"},".text-start":{"text-align":"start"},".text-end":{"text-align":"end"}})},textIndent:P("textIndent",[["indent",["text-indent"]]],{supportsNegativeValues:!0}),verticalAlign:({addUtilities:r,matchUtilities:e})=>{r({".align-baseline":{"vertical-align":"baseline"},".align-top":{"vertical-align":"top"},".align-middle":{"vertical-align":"middle"},".align-bottom":{"vertical-align":"bottom"},".align-text-top":{"vertical-align":"text-top"},".align-text-bottom":{"vertical-align":"text-bottom"},".align-sub":{"vertical-align":"sub"},".align-super":{"vertical-align":"super"}}),e({align:t=>({"vertical-align":t})})},fontFamily:({matchUtilities:r,theme:e})=>{r({font:t=>{let[i,n={}]=Array.isArray(t)&&ie(t[1])?t:[t],{fontFeatureSettings:a,fontVariationSettings:s}=n;return{"font-family":Array.isArray(i)?i.join(", "):i,...a===void 0?{}:{"font-feature-settings":a},...s===void 0?{}:{"font-variation-settings":s}}}},{values:e("fontFamily"),type:["lookup","generic-name","family-name"]})},fontSize:({matchUtilities:r,theme:e})=>{r({text:(t,{modifier:i})=>{let[n,a]=Array.isArray(t)?t:[t];if(i)return{"font-size":n,"line-height":i};let{lineHeight:s,letterSpacing:o,fontWeight:u}=ie(a)?a:{lineHeight:a};return{"font-size":n,...s===void 0?{}:{"line-height":s},...o===void 0?{}:{"letter-spacing":o},...u===void 0?{}:{"font-weight":u}}}},{values:e("fontSize"),modifiers:e("lineHeight"),type:["absolute-size","relative-size","length","percentage"]})},fontWeight:P("fontWeight",[["font",["fontWeight"]]],{type:["lookup","number","any"]}),textTransform:({addUtilities:r})=>{r({".uppercase":{"text-transform":"uppercase"},".lowercase":{"text-transform":"lowercase"},".capitalize":{"text-transform":"capitalize"},".normal-case":{"text-transform":"none"}})},fontStyle:({addUtilities:r})=>{r({".italic":{"font-style":"italic"},".not-italic":{"font-style":"normal"}})},fontVariantNumeric:({addDefaults:r,addUtilities:e})=>{let t="var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)";r("font-variant-numeric",{"--tw-ordinal":" ","--tw-slashed-zero":" ","--tw-numeric-figure":" ","--tw-numeric-spacing":" ","--tw-numeric-fraction":" "}),e({".normal-nums":{"font-variant-numeric":"normal"},".ordinal":{"@defaults font-variant-numeric":{},"--tw-ordinal":"ordinal","font-variant-numeric":t},".slashed-zero":{"@defaults font-variant-numeric":{},"--tw-slashed-zero":"slashed-zero","font-variant-numeric":t},".lining-nums":{"@defaults font-variant-numeric":{},"--tw-numeric-figure":"lining-nums","font-variant-numeric":t},".oldstyle-nums":{"@defaults font-variant-numeric":{},"--tw-numeric-figure":"oldstyle-nums","font-variant-numeric":t},".proportional-nums":{"@defaults font-variant-numeric":{},"--tw-numeric-spacing":"proportional-nums","font-variant-numeric":t},".tabular-nums":{"@defaults font-variant-numeric":{},"--tw-numeric-spacing":"tabular-nums","font-variant-numeric":t},".diagonal-fractions":{"@defaults font-variant-numeric":{},"--tw-numeric-fraction":"diagonal-fractions","font-variant-numeric":t},".stacked-fractions":{"@defaults font-variant-numeric":{},"--tw-numeric-fraction":"stacked-fractions","font-variant-numeric":t}})},lineHeight:P("lineHeight",[["leading",["lineHeight"]]]),letterSpacing:P("letterSpacing",[["tracking",["letterSpacing"]]],{supportsNegativeValues:!0}),textColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({text:i=>t("textOpacity")?se({color:i,property:"color",variable:"--tw-text-opacity"}):{color:N(i)}},{values:re(e("textColor")),type:["color","any"]})},textOpacity:P("textOpacity",[["text-opacity",["--tw-text-opacity"]]]),textDecoration:({addUtilities:r})=>{r({".underline":{"text-decoration-line":"underline"},".overline":{"text-decoration-line":"overline"},".line-through":{"text-decoration-line":"line-through"},".no-underline":{"text-decoration-line":"none"}})},textDecorationColor:({matchUtilities:r,theme:e})=>{r({decoration:t=>({"text-decoration-color":N(t)})},{values:re(e("textDecorationColor")),type:["color","any"]})},textDecorationStyle:({addUtilities:r})=>{r({".decoration-solid":{"text-decoration-style":"solid"},".decoration-double":{"text-decoration-style":"double"},".decoration-dotted":{"text-decoration-style":"dotted"},".decoration-dashed":{"text-decoration-style":"dashed"},".decoration-wavy":{"text-decoration-style":"wavy"}})},textDecorationThickness:P("textDecorationThickness",[["decoration",["text-decoration-thickness"]]],{type:["length","percentage"]}),textUnderlineOffset:P("textUnderlineOffset",[["underline-offset",["text-underline-offset"]]],{type:["length","percentage","any"]}),fontSmoothing:({addUtilities:r})=>{r({".antialiased":{"-webkit-font-smoothing":"antialiased","-moz-osx-font-smoothing":"grayscale"},".subpixel-antialiased":{"-webkit-font-smoothing":"auto","-moz-osx-font-smoothing":"auto"}})},placeholderColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({placeholder:i=>t("placeholderOpacity")?{"&::placeholder":se({color:i,property:"color",variable:"--tw-placeholder-opacity"})}:{"&::placeholder":{color:N(i)}}},{values:re(e("placeholderColor")),type:["color","any"]})},placeholderOpacity:({matchUtilities:r,theme:e})=>{r({"placeholder-opacity":t=>({["&::placeholder"]:{"--tw-placeholder-opacity":t}})},{values:e("placeholderOpacity")})},caretColor:({matchUtilities:r,theme:e})=>{r({caret:t=>({"caret-color":N(t)})},{values:re(e("caretColor")),type:["color","any"]})},accentColor:({matchUtilities:r,theme:e})=>{r({accent:t=>({"accent-color":N(t)})},{values:re(e("accentColor")),type:["color","any"]})},opacity:P("opacity",[["opacity",["opacity"]]]),backgroundBlendMode:({addUtilities:r})=>{r({".bg-blend-normal":{"background-blend-mode":"normal"},".bg-blend-multiply":{"background-blend-mode":"multiply"},".bg-blend-screen":{"background-blend-mode":"screen"},".bg-blend-overlay":{"background-blend-mode":"overlay"},".bg-blend-darken":{"background-blend-mode":"darken"},".bg-blend-lighten":{"background-blend-mode":"lighten"},".bg-blend-color-dodge":{"background-blend-mode":"color-dodge"},".bg-blend-color-burn":{"background-blend-mode":"color-burn"},".bg-blend-hard-light":{"background-blend-mode":"hard-light"},".bg-blend-soft-light":{"background-blend-mode":"soft-light"},".bg-blend-difference":{"background-blend-mode":"difference"},".bg-blend-exclusion":{"background-blend-mode":"exclusion"},".bg-blend-hue":{"background-blend-mode":"hue"},".bg-blend-saturation":{"background-blend-mode":"saturation"},".bg-blend-color":{"background-blend-mode":"color"},".bg-blend-luminosity":{"background-blend-mode":"luminosity"}})},mixBlendMode:({addUtilities:r})=>{r({".mix-blend-normal":{"mix-blend-mode":"normal"},".mix-blend-multiply":{"mix-blend-mode":"multiply"},".mix-blend-screen":{"mix-blend-mode":"screen"},".mix-blend-overlay":{"mix-blend-mode":"overlay"},".mix-blend-darken":{"mix-blend-mode":"darken"},".mix-blend-lighten":{"mix-blend-mode":"lighten"},".mix-blend-color-dodge":{"mix-blend-mode":"color-dodge"},".mix-blend-color-burn":{"mix-blend-mode":"color-burn"},".mix-blend-hard-light":{"mix-blend-mode":"hard-light"},".mix-blend-soft-light":{"mix-blend-mode":"soft-light"},".mix-blend-difference":{"mix-blend-mode":"difference"},".mix-blend-exclusion":{"mix-blend-mode":"exclusion"},".mix-blend-hue":{"mix-blend-mode":"hue"},".mix-blend-saturation":{"mix-blend-mode":"saturation"},".mix-blend-color":{"mix-blend-mode":"color"},".mix-blend-luminosity":{"mix-blend-mode":"luminosity"},".mix-blend-plus-darker":{"mix-blend-mode":"plus-darker"},".mix-blend-plus-lighter":{"mix-blend-mode":"plus-lighter"}})},boxShadow:(()=>{let r=Ge("boxShadow"),e=["var(--tw-ring-offset-shadow, 0 0 #0000)","var(--tw-ring-shadow, 0 0 #0000)","var(--tw-shadow)"].join(", ");return function({matchUtilities:t,addDefaults:i,theme:n}){i("box-shadow",{"--tw-ring-offset-shadow":"0 0 #0000","--tw-ring-shadow":"0 0 #0000","--tw-shadow":"0 0 #0000","--tw-shadow-colored":"0 0 #0000"}),t({shadow:a=>{a=r(a);let s=xi(a);for(let o of s)!o.valid||(o.color="var(--tw-shadow-color)");return{"@defaults box-shadow":{},"--tw-shadow":a==="none"?"0 0 #0000":a,"--tw-shadow-colored":a==="none"?"0 0 #0000":Lu(s),"box-shadow":e}}},{values:n("boxShadow"),type:["shadow"]})}})(),boxShadowColor:({matchUtilities:r,theme:e})=>{r({shadow:t=>({"--tw-shadow-color":N(t),"--tw-shadow":"var(--tw-shadow-colored)"})},{values:re(e("boxShadowColor")),type:["color","any"]})},outlineStyle:({addUtilities:r})=>{r({".outline-none":{outline:"2px solid transparent","outline-offset":"2px"},".outline":{"outline-style":"solid"},".outline-dashed":{"outline-style":"dashed"},".outline-dotted":{"outline-style":"dotted"},".outline-double":{"outline-style":"double"}})},outlineWidth:P("outlineWidth",[["outline",["outline-width"]]],{type:["length","number","percentage"]}),outlineOffset:P("outlineOffset",[["outline-offset",["outline-offset"]]],{type:["length","number","percentage","any"],supportsNegativeValues:!0}),outlineColor:({matchUtilities:r,theme:e})=>{r({outline:t=>({"outline-color":N(t)})},{values:re(e("outlineColor")),type:["color","any"]})},ringWidth:({matchUtilities:r,addDefaults:e,addUtilities:t,theme:i,config:n})=>{let a=(()=>{if(K(n(),"respectDefaultRingColorOpacity"))return i("ringColor.DEFAULT");let s=i("ringOpacity.DEFAULT","0.5");return i("ringColor")?.DEFAULT?Ie(i("ringColor")?.DEFAULT,s,`rgb(147 197 253 / ${s})`):`rgb(147 197 253 / ${s})`})();e("ring-width",{"--tw-ring-inset":" ","--tw-ring-offset-width":i("ringOffsetWidth.DEFAULT","0px"),"--tw-ring-offset-color":i("ringOffsetColor.DEFAULT","#fff"),"--tw-ring-color":a,"--tw-ring-offset-shadow":"0 0 #0000","--tw-ring-shadow":"0 0 #0000","--tw-shadow":"0 0 #0000","--tw-shadow-colored":"0 0 #0000"}),r({ring:s=>({"@defaults ring-width":{},"--tw-ring-offset-shadow":"var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)","--tw-ring-shadow":`var(--tw-ring-inset) 0 0 0 calc(${s} + var(--tw-ring-offset-width)) var(--tw-ring-color)`,"box-shadow":["var(--tw-ring-offset-shadow)","var(--tw-ring-shadow)","var(--tw-shadow, 0 0 #0000)"].join(", ")})},{values:i("ringWidth"),type:"length"}),t({".ring-inset":{"@defaults ring-width":{},"--tw-ring-inset":"inset"}})},ringColor:({matchUtilities:r,theme:e,corePlugins:t})=>{r({ring:i=>t("ringOpacity")?se({color:i,property:"--tw-ring-color",variable:"--tw-ring-opacity"}):{"--tw-ring-color":N(i)}},{values:Object.fromEntries(Object.entries(re(e("ringColor"))).filter(([i])=>i!=="DEFAULT")),type:["color","any"]})},ringOpacity:r=>{let{config:e}=r;return P("ringOpacity",[["ring-opacity",["--tw-ring-opacity"]]],{filterDefault:!K(e(),"respectDefaultRingColorOpacity")})(r)},ringOffsetWidth:P("ringOffsetWidth",[["ring-offset",["--tw-ring-offset-width"]]],{type:"length"}),ringOffsetColor:({matchUtilities:r,theme:e})=>{r({"ring-offset":t=>({"--tw-ring-offset-color":N(t)})},{values:re(e("ringOffsetColor")),type:["color","any"]})},blur:({matchUtilities:r,theme:e})=>{r({blur:t=>({"--tw-blur":`blur(${t})`,"@defaults filter":{},filter:Be})},{values:e("blur")})},brightness:({matchUtilities:r,theme:e})=>{r({brightness:t=>({"--tw-brightness":`brightness(${t})`,"@defaults filter":{},filter:Be})},{values:e("brightness")})},contrast:({matchUtilities:r,theme:e})=>{r({contrast:t=>({"--tw-contrast":`contrast(${t})`,"@defaults filter":{},filter:Be})},{values:e("contrast")})},dropShadow:({matchUtilities:r,theme:e})=>{r({"drop-shadow":t=>({"--tw-drop-shadow":Array.isArray(t)?t.map(i=>`drop-shadow(${i})`).join(" "):`drop-shadow(${t})`,"@defaults filter":{},filter:Be})},{values:e("dropShadow")})},grayscale:({matchUtilities:r,theme:e})=>{r({grayscale:t=>({"--tw-grayscale":`grayscale(${t})`,"@defaults filter":{},filter:Be})},{values:e("grayscale")})},hueRotate:({matchUtilities:r,theme:e})=>{r({"hue-rotate":t=>({"--tw-hue-rotate":`hue-rotate(${t})`,"@defaults filter":{},filter:Be})},{values:e("hueRotate"),supportsNegativeValues:!0})},invert:({matchUtilities:r,theme:e})=>{r({invert:t=>({"--tw-invert":`invert(${t})`,"@defaults filter":{},filter:Be})},{values:e("invert")})},saturate:({matchUtilities:r,theme:e})=>{r({saturate:t=>({"--tw-saturate":`saturate(${t})`,"@defaults filter":{},filter:Be})},{values:e("saturate")})},sepia:({matchUtilities:r,theme:e})=>{r({sepia:t=>({"--tw-sepia":`sepia(${t})`,"@defaults filter":{},filter:Be})},{values:e("sepia")})},filter:({addDefaults:r,addUtilities:e})=>{r("filter",{"--tw-blur":" ","--tw-brightness":" ","--tw-contrast":" ","--tw-grayscale":" ","--tw-hue-rotate":" ","--tw-invert":" ","--tw-saturate":" ","--tw-sepia":" ","--tw-drop-shadow":" "}),e({".filter":{"@defaults filter":{},filter:Be},".filter-none":{filter:"none"}})},backdropBlur:({matchUtilities:r,theme:e})=>{r({"backdrop-blur":t=>({"--tw-backdrop-blur":`blur(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropBlur")})},backdropBrightness:({matchUtilities:r,theme:e})=>{r({"backdrop-brightness":t=>({"--tw-backdrop-brightness":`brightness(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropBrightness")})},backdropContrast:({matchUtilities:r,theme:e})=>{r({"backdrop-contrast":t=>({"--tw-backdrop-contrast":`contrast(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropContrast")})},backdropGrayscale:({matchUtilities:r,theme:e})=>{r({"backdrop-grayscale":t=>({"--tw-backdrop-grayscale":`grayscale(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropGrayscale")})},backdropHueRotate:({matchUtilities:r,theme:e})=>{r({"backdrop-hue-rotate":t=>({"--tw-backdrop-hue-rotate":`hue-rotate(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropHueRotate"),supportsNegativeValues:!0})},backdropInvert:({matchUtilities:r,theme:e})=>{r({"backdrop-invert":t=>({"--tw-backdrop-invert":`invert(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropInvert")})},backdropOpacity:({matchUtilities:r,theme:e})=>{r({"backdrop-opacity":t=>({"--tw-backdrop-opacity":`opacity(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropOpacity")})},backdropSaturate:({matchUtilities:r,theme:e})=>{r({"backdrop-saturate":t=>({"--tw-backdrop-saturate":`saturate(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropSaturate")})},backdropSepia:({matchUtilities:r,theme:e})=>{r({"backdrop-sepia":t=>({"--tw-backdrop-sepia":`sepia(${t})`,"@defaults backdrop-filter":{},"backdrop-filter":Fe})},{values:e("backdropSepia")})},backdropFilter:({addDefaults:r,addUtilities:e})=>{r("backdrop-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":" "}),e({".backdrop-filter":{"@defaults backdrop-filter":{},"backdrop-filter":Fe},".backdrop-filter-none":{"backdrop-filter":"none"}})},transitionProperty:({matchUtilities:r,theme:e})=>{let t=e("transitionTimingFunction.DEFAULT"),i=e("transitionDuration.DEFAULT");r({transition:n=>({"transition-property":n,...n==="none"?{}:{"transition-timing-function":t,"transition-duration":i}})},{values:e("transitionProperty")})},transitionDelay:P("transitionDelay",[["delay",["transitionDelay"]]]),transitionDuration:P("transitionDuration",[["duration",["transitionDuration"]]],{filterDefault:!0}),transitionTimingFunction:P("transitionTimingFunction",[["ease",["transitionTimingFunction"]]],{filterDefault:!0}),willChange:P("willChange",[["will-change",["will-change"]]]),contain:({addDefaults:r,addUtilities:e})=>{let t="var(--tw-contain-size) var(--tw-contain-layout) var(--tw-contain-paint) var(--tw-contain-style)";r("contain",{"--tw-contain-size":" ","--tw-contain-layout":" ","--tw-contain-paint":" ","--tw-contain-style":" "}),e({".contain-none":{contain:"none"},".contain-content":{contain:"content"},".contain-strict":{contain:"strict"},".contain-size":{"@defaults contain":{},"--tw-contain-size":"size",contain:t},".contain-inline-size":{"@defaults contain":{},"--tw-contain-size":"inline-size",contain:t},".contain-layout":{"@defaults contain":{},"--tw-contain-layout":"layout",contain:t},".contain-paint":{"@defaults contain":{},"--tw-contain-paint":"paint",contain:t},".contain-style":{"@defaults contain":{},"--tw-contain-style":"style",contain:t}})},content:P("content",[["content",["--tw-content",["content","var(--tw-content)"]]]]),forcedColorAdjust:({addUtilities:r})=>{r({".forced-color-adjust-auto":{"forced-color-adjust":"auto"},".forced-color-adjust-none":{"forced-color-adjust":"none"}})}}});function h2(r){if(r===void 0)return!1;if(r==="true"||r==="1")return!0;if(r==="false"||r==="0")return!1;if(r==="*")return!0;let e=r.split(",").map(t=>t.split(":")[0]);return e.includes("-tailwindcss")?!1:!!e.includes("tailwindcss")}var Pe,Ad,_d,vn,Za,He,ti,lt=C(()=>{l();Pe=typeof h!="undefined"?{NODE_ENV:"production",DEBUG:h2(h.env.DEBUG)}:{NODE_ENV:"production",DEBUG:!1},Ad=new Map,_d=new Map,vn=new Map,Za=new Map,He=new String("*"),ti=Symbol("__NONE__")});function zt(r){let e=[],t=!1;for(let i=0;i0)}var Od,Ed,m2,eo=C(()=>{l();Od=new Map([["{","}"],["[","]"],["(",")"]]),Ed=new Map(Array.from(Od.entries()).map(([r,e])=>[e,r])),m2=new Set(['"',"'","`"])});function jt(r){let[e]=Td(r);return e.forEach(([t,i])=>t.removeChild(i)),r.nodes.push(...e.map(([,t])=>t)),r}function Td(r){let e=[],t=null;for(let i of r.nodes)if(i.type==="combinator")e=e.filter(([,n])=>ro(n).includes("jumpable")),t=null;else if(i.type==="pseudo"){g2(i)?(t=i,e.push([r,i,null])):t&&y2(i,t)?e.push([r,i,t]):t=null;for(let n of i.nodes??[]){let[a,s]=Td(n);t=s||t,e.push(...a)}}return[e,t]}function Pd(r){return r.value.startsWith("::")||to[r.value]!==void 0}function g2(r){return Pd(r)&&ro(r).includes("terminal")}function y2(r,e){return r.type!=="pseudo"||Pd(r)?!1:ro(e).includes("actionable")}function ro(r){return to[r.value]??to.__default__}var to,xn=C(()=>{l();to={"::after":["terminal","jumpable"],"::backdrop":["terminal","jumpable"],"::before":["terminal","jumpable"],"::cue":["terminal"],"::cue-region":["terminal"],"::first-letter":["terminal","jumpable"],"::first-line":["terminal","jumpable"],"::grammar-error":["terminal"],"::marker":["terminal","jumpable"],"::part":["terminal","actionable"],"::placeholder":["terminal","jumpable"],"::selection":["terminal","jumpable"],"::slotted":["terminal"],"::spelling-error":["terminal"],"::target-text":["terminal"],"::file-selector-button":["terminal","actionable"],"::deep":["actionable"],"::v-deep":["actionable"],"::ng-deep":["actionable"],":after":["terminal","jumpable"],":before":["terminal","jumpable"],":first-letter":["terminal","jumpable"],":first-line":["terminal","jumpable"],":where":[],":is":[],":has":[],__default__:["terminal","actionable"]}});function Vt(r,{context:e,candidate:t}){let i=e?.tailwindConfig.prefix??"",n=r.map(s=>{let o=(0,Le.default)().astSync(s.format);return{...s,ast:s.respectPrefix?Nt(i,o):o}}),a=Le.default.root({nodes:[Le.default.selector({nodes:[Le.default.className({value:ce(t)})]})]});for(let{ast:s}of n)[a,s]=b2(a,s),s.walkNesting(o=>o.replaceWith(...a.nodes[0].nodes)),a=s;return a}function Id(r){let e=[];for(;r.prev()&&r.prev().type!=="combinator";)r=r.prev();for(;r&&r.type!=="combinator";)e.push(r),r=r.next();return e}function w2(r){return r.sort((e,t)=>e.type==="tag"&&t.type==="class"?-1:e.type==="class"&&t.type==="tag"?1:e.type==="class"&&t.type==="pseudo"&&t.value.startsWith("::")?-1:e.type==="pseudo"&&e.value.startsWith("::")&&t.type==="class"?1:r.index(e)-r.index(t)),r}function no(r,e){let t=!1;r.walk(i=>{if(i.type==="class"&&i.value===e)return t=!0,!1}),t||r.remove()}function kn(r,e,{context:t,candidate:i,base:n}){let a=t?.tailwindConfig?.separator??":";n=n??ae(i,a).pop();let s=(0,Le.default)().astSync(r);if(s.walkClasses(f=>{f.raws&&f.value.includes(n)&&(f.raws.value=ce((0,Dd.default)(f.raws.value)))}),s.each(f=>no(f,n)),s.length===0)return null;let o=Array.isArray(e)?Vt(e,{context:t,candidate:i}):e;if(o===null)return s.toString();let u=Le.default.comment({value:"/*__simple__*/"}),c=Le.default.comment({value:"/*__simple__*/"});return s.walkClasses(f=>{if(f.value!==n)return;let d=f.parent,p=o.nodes[0].nodes;if(d.nodes.length===1){f.replaceWith(...p);return}let m=Id(f);d.insertBefore(m[0],u),d.insertAfter(m[m.length-1],c);for(let x of p)d.insertBefore(m[0],x.clone());f.remove(),m=Id(u);let b=d.index(u);d.nodes.splice(b,m.length,...w2(Le.default.selector({nodes:m})).nodes),u.remove(),c.remove()}),s.walkPseudos(f=>{f.value===io&&f.replaceWith(f.nodes)}),s.each(f=>jt(f)),s.toString()}function b2(r,e){let t=[];return r.walkPseudos(i=>{i.value===io&&t.push({pseudo:i,value:i.nodes[0].toString()})}),e.walkPseudos(i=>{if(i.value!==io)return;let n=i.nodes[0].toString(),a=t.find(c=>c.value===n);if(!a)return;let s=[],o=i.next();for(;o&&o.type!=="combinator";)s.push(o),o=o.next();let u=o;a.pseudo.parent.insertAfter(a.pseudo,Le.default.selector({nodes:s.map(c=>c.clone())})),i.remove(),s.forEach(c=>c.remove()),u&&u.type==="combinator"&&u.remove()}),[r,e]}var Le,Dd,io,so=C(()=>{l();Le=X(Me()),Dd=X(Ki());$t();dn();xn();_t();io=":merge"});function Sn(r,e){let t=(0,ao.default)().astSync(r);return t.each(i=>{i.nodes[0].type==="pseudo"&&i.nodes[0].value===":is"&&i.nodes.every(a=>a.type!=="combinator")||(i.nodes=[ao.default.pseudo({value:":is",nodes:[i.clone()]})]),jt(i)}),`${e} ${t.toString()}`}var ao,oo=C(()=>{l();ao=X(Me());xn()});function lo(r){return v2.transformSync(r)}function*x2(r){let e=1/0;for(;e>=0;){let t,i=!1;if(e===1/0&&r.endsWith("]")){let s=r.indexOf("[");r[s-1]==="-"?t=s-1:r[s-1]==="/"?(t=s-1,i=!0):t=-1}else e===1/0&&r.includes("/")?(t=r.lastIndexOf("/"),i=!0):t=r.lastIndexOf("-",e);if(t<0)break;let n=r.slice(0,t),a=r.slice(i?t:t+1);e=t-1,!(n===""||a==="/")&&(yield[n,a])}}function k2(r,e){if(r.length===0||e.tailwindConfig.prefix==="")return r;for(let t of r){let[i]=t;if(i.options.respectPrefix){let n=j.root({nodes:[t[1].clone()]}),a=t[1].raws.tailwind.classCandidate;n.walkRules(s=>{let o=a.startsWith("-");s.selector=Nt(e.tailwindConfig.prefix,s.selector,o)}),t[1]=n.nodes[0]}}return r}function S2(r,e){if(r.length===0)return r;let t=[];function i(n){return n.parent&&n.parent.type==="atrule"&&n.parent.name==="keyframes"}for(let[n,a]of r){let s=j.root({nodes:[a.clone()]});s.walkRules(o=>{if(i(o))return;let u=(0,Cn.default)().astSync(o.selector);u.each(c=>no(c,e)),Ju(u,c=>c===e?`!${c}`:c),o.selector=u.toString(),o.walkDecls(c=>c.important=!0)}),t.push([{...n,important:!0},s.nodes[0]])}return t}function C2(r,e,t){if(e.length===0)return e;let i={modifier:null,value:ti};{let[n,...a]=ae(r,"/");if(a.length>1&&(n=n+"/"+a.slice(0,-1).join("/"),a=a.slice(-1)),a.length&&!t.variantMap.has(r)&&(r=n,i.modifier=a[0],!K(t.tailwindConfig,"generalizedModifiers")))return[]}if(r.endsWith("]")&&!r.startsWith("[")){let n=/(.)(-?)\[(.*)\]/g.exec(r);if(n){let[,a,s,o]=n;if(a==="@"&&s==="-")return[];if(a!=="@"&&s==="")return[];r=r.replace(`${s}[${o}]`,""),i.value=o}}if(co(r)&&!t.variantMap.has(r)){let n=t.offsets.recordVariant(r),a=L(r.slice(1,-1)),s=ae(a,",");if(s.length>1)return[];if(!s.every(En))return[];let o=s.map((u,c)=>[t.offsets.applyParallelOffset(n,c),ri(u.trim())]);t.variantMap.set(r,o)}if(t.variantMap.has(r)){let n=co(r),a=t.variantOptions.get(r)?.[Zr]??{},s=t.variantMap.get(r).slice(),o=[],u=(()=>!(n||a.respectPrefix===!1))();for(let[c,f]of e){if(c.layer==="user")continue;let d=j.root({nodes:[f.clone()]});for(let[p,m,b]of s){let w=function(){x.raws.neededBackup||(x.raws.neededBackup=!0,x.walkRules(E=>E.raws.originalSelector=E.selector))},k=function(E){return w(),x.each(I=>{I.type==="rule"&&(I.selectors=I.selectors.map(q=>E({get className(){return lo(q)},selector:q})))}),x},x=(b??d).clone(),y=[],S=m({get container(){return w(),x},separator:t.tailwindConfig.separator,modifySelectors:k,wrap(E){let I=x.nodes;x.removeAll(),E.append(I),x.append(E)},format(E){y.push({format:E,respectPrefix:u})},args:i});if(Array.isArray(S)){for(let[E,I]of S.entries())s.push([t.offsets.applyParallelOffset(p,E),I,x.clone()]);continue}if(typeof S=="string"&&y.push({format:S,respectPrefix:u}),S===null)continue;x.raws.neededBackup&&(delete x.raws.neededBackup,x.walkRules(E=>{let I=E.raws.originalSelector;if(!I||(delete E.raws.originalSelector,I===E.selector))return;let q=E.selector,R=(0,Cn.default)(J=>{J.walkClasses(ue=>{ue.value=`${r}${t.tailwindConfig.separator}${ue.value}`})}).processSync(I);y.push({format:q.replace(R,"&"),respectPrefix:u}),E.selector=I})),x.nodes[0].raws.tailwind={...x.nodes[0].raws.tailwind,parentLayer:c.layer};let _=[{...c,sort:t.offsets.applyVariantOffset(c.sort,p,Object.assign(i,t.variantOptions.get(r))),collectedFormats:(c.collectedFormats??[]).concat(y)},x.nodes[0]];o.push(_)}}return o}return[]}function uo(r,e,t={}){return!ie(r)&&!Array.isArray(r)?[[r],t]:Array.isArray(r)?uo(r[0],e,r[1]):(e.has(r)||e.set(r,Lt(r)),[e.get(r),t])}function _2(r){return A2.test(r)}function O2(r){if(!r.includes("://"))return!1;try{let e=new URL(r);return e.scheme!==""&&e.host!==""}catch(e){return!1}}function qd(r){let e=!0;return r.walkDecls(t=>{if(!Rd(t.prop,t.value))return e=!1,!1}),e}function Rd(r,e){if(O2(`${r}:${e}`))return!1;try{return j.parse(`a{${r}:${e}}`).toResult(),!0}catch(t){return!1}}function E2(r,e){let[,t,i]=r.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/)??[];if(i===void 0||!_2(t)||!zt(i))return null;let n=L(i,{property:t});return Rd(t,n)?[[{sort:e.offsets.arbitraryProperty(r),layer:"utilities",options:{respectImportant:!0}},()=>({[Ja(r)]:{[t]:n}})]]:null}function*T2(r,e){e.candidateRuleMap.has(r)&&(yield[e.candidateRuleMap.get(r),"DEFAULT"]),yield*function*(o){o!==null&&(yield[o,"DEFAULT"])}(E2(r,e));let t=r,i=!1,n=e.tailwindConfig.prefix,a=n.length,s=t.startsWith(n)||t.startsWith(`-${n}`);t[a]==="-"&&s&&(i=!0,t=n+t.slice(a+1)),i&&e.candidateRuleMap.has(t)&&(yield[e.candidateRuleMap.get(t),"-DEFAULT"]);for(let[o,u]of x2(t))e.candidateRuleMap.has(o)&&(yield[e.candidateRuleMap.get(o),i?`-${u}`:u])}function P2(r,e){return r===He?[He]:ae(r,e)}function*D2(r,e){for(let t of r)t[1].raws.tailwind={...t[1].raws.tailwind,classCandidate:e,preserveSource:t[0].options?.preserveSource??!1},yield t}function*fo(r,e){let t=e.tailwindConfig.separator,[i,...n]=P2(r,t).reverse(),a=!1;i.startsWith("!")&&(a=!0,i=i.slice(1));for(let s of T2(i,e)){let o=[],u=new Map,[c,f]=s,d=c.length===1;for(let[p,m]of c){let b=[];if(typeof m=="function")for(let x of[].concat(m(f,{isOnlyPlugin:d}))){let[y,w]=uo(x,e.postCssNodeCache);for(let k of y)b.push([{...p,options:{...p.options,...w}},k])}else if(f==="DEFAULT"||f==="-DEFAULT"){let x=m,[y,w]=uo(x,e.postCssNodeCache);for(let k of y)b.push([{...p,options:{...p.options,...w}},k])}if(b.length>0){let x=Array.from(ys(p.options?.types??[],f,p.options??{},e.tailwindConfig)).map(([y,w])=>w);x.length>0&&u.set(b,x),o.push(b)}}if(co(f)){if(o.length>1){let b=function(y){return y.length===1?y[0]:y.find(w=>{let k=u.get(w);return w.some(([{options:S},_])=>qd(_)?S.types.some(({type:E,preferOnConflict:I})=>k.includes(E)&&I):!1)})},[p,m]=o.reduce((y,w)=>(w.some(([{options:S}])=>S.types.some(({type:_})=>_==="any"))?y[0].push(w):y[1].push(w),y),[[],[]]),x=b(m)??b(p);if(x)o=[x];else{let y=o.map(k=>new Set([...u.get(k)??[]]));for(let k of y)for(let S of k){let _=!1;for(let E of y)k!==E&&E.has(S)&&(E.delete(S),_=!0);_&&k.delete(S)}let w=[];for(let[k,S]of y.entries())for(let _ of S){let E=o[k].map(([,I])=>I).flat().map(I=>I.toString().split(` -`).slice(1,-1).map(q=>q.trim()).map(q=>` ${q}`).join(` -`)).join(` +` + + e + + ` +`), + this.name + ": " + this.message + e + ); + } + }; + mf.exports = Tt; + Tt.default = Tt; + }); + var Oi = v((h3, _s) => { + l(); + ("use strict"); + _s.exports.isClean = Symbol("isClean"); + _s.exports.my = Symbol("my"); + }); + var Os = v((m3, yf) => { + l(); + ("use strict"); + var gf = { + colon: ": ", + indent: " ", + beforeDecl: ` +`, + beforeRule: ` +`, + beforeOpen: " ", + beforeClose: ` +`, + beforeComment: ` +`, + after: ` +`, + emptyBody: "", + commentLeft: " ", + commentRight: " ", + semicolon: !1, + }; + function v0(r) { + return r[0].toUpperCase() + r.slice(1); + } + var Ei = class { + constructor(e) { + this.builder = e; + } + stringify(e, t) { + if (!this[e.type]) + throw new Error( + "Unknown AST node type " + e.type + ". Maybe you need to change PostCSS stringifier." + ); + this[e.type](e, t); + } + document(e) { + this.body(e); + } + root(e) { + (this.body(e), e.raws.after && this.builder(e.raws.after)); + } + comment(e) { + let t = this.raw(e, "left", "commentLeft"), + i = this.raw(e, "right", "commentRight"); + this.builder("/*" + t + e.text + i + "*/", e); + } + decl(e, t) { + let i = this.raw(e, "between", "colon"), + n = e.prop + i + this.rawValue(e, "value"); + (e.important && (n += e.raws.important || " !important"), t && (n += ";"), this.builder(n, e)); + } + rule(e) { + (this.block(e, this.rawValue(e, "selector")), + e.raws.ownSemicolon && this.builder(e.raws.ownSemicolon, e, "end")); + } + atrule(e, t) { + let i = "@" + e.name, + n = e.params ? this.rawValue(e, "params") : ""; + if ((typeof e.raws.afterName != "undefined" ? (i += e.raws.afterName) : n && (i += " "), e.nodes)) + this.block(e, i + n); + else { + let a = (e.raws.between || "") + (t ? ";" : ""); + this.builder(i + n + a, e); + } + } + body(e) { + let t = e.nodes.length - 1; + for (; t > 0 && e.nodes[t].type === "comment"; ) t -= 1; + let i = this.raw(e, "semicolon"); + for (let n = 0; n < e.nodes.length; n++) { + let a = e.nodes[n], + s = this.raw(a, "before"); + (s && this.builder(s), this.stringify(a, t !== n || i)); + } + } + block(e, t) { + let i = this.raw(e, "between", "beforeOpen"); + this.builder(t + i + "{", e, "start"); + let n; + (e.nodes && e.nodes.length + ? (this.body(e), (n = this.raw(e, "after"))) + : (n = this.raw(e, "after", "emptyBody")), + n && this.builder(n), + this.builder("}", e, "end")); + } + raw(e, t, i) { + let n; + if ((i || (i = t), t && ((n = e.raws[t]), typeof n != "undefined"))) return n; + let a = e.parent; + if (i === "before" && (!a || (a.type === "root" && a.first === e) || (a && a.type === "document"))) + return ""; + if (!a) return gf[i]; + let s = e.root(); + if ((s.rawCache || (s.rawCache = {}), typeof s.rawCache[i] != "undefined")) return s.rawCache[i]; + if (i === "before" || i === "after") return this.beforeAfter(e, i); + { + let o = "raw" + v0(i); + this[o] + ? (n = this[o](s, e)) + : s.walk((u) => { + if (((n = u.raws[t]), typeof n != "undefined")) return !1; + }); + } + return (typeof n == "undefined" && (n = gf[i]), (s.rawCache[i] = n), n); + } + rawSemicolon(e) { + let t; + return ( + e.walk((i) => { + if ( + i.nodes && + i.nodes.length && + i.last.type === "decl" && + ((t = i.raws.semicolon), typeof t != "undefined") + ) + return !1; + }), + t + ); + } + rawEmptyBody(e) { + let t; + return ( + e.walk((i) => { + if (i.nodes && i.nodes.length === 0 && ((t = i.raws.after), typeof t != "undefined")) return !1; + }), + t + ); + } + rawIndent(e) { + if (e.raws.indent) return e.raws.indent; + let t; + return ( + e.walk((i) => { + let n = i.parent; + if (n && n !== e && n.parent && n.parent === e && typeof i.raws.before != "undefined") { + let a = i.raws.before.split(` +`); + return ((t = a[a.length - 1]), (t = t.replace(/\S/g, "")), !1); + } + }), + t + ); + } + rawBeforeComment(e, t) { + let i; + return ( + e.walkComments((n) => { + if (typeof n.raws.before != "undefined") + return ( + (i = n.raws.before), + i.includes(` +`) && (i = i.replace(/[^\n]+$/, "")), + !1 + ); + }), + typeof i == "undefined" ? (i = this.raw(t, null, "beforeDecl")) : i && (i = i.replace(/\S/g, "")), + i + ); + } + rawBeforeDecl(e, t) { + let i; + return ( + e.walkDecls((n) => { + if (typeof n.raws.before != "undefined") + return ( + (i = n.raws.before), + i.includes(` +`) && (i = i.replace(/[^\n]+$/, "")), + !1 + ); + }), + typeof i == "undefined" ? (i = this.raw(t, null, "beforeRule")) : i && (i = i.replace(/\S/g, "")), + i + ); + } + rawBeforeRule(e) { + let t; + return ( + e.walk((i) => { + if (i.nodes && (i.parent !== e || e.first !== i) && typeof i.raws.before != "undefined") + return ( + (t = i.raws.before), + t.includes(` +`) && (t = t.replace(/[^\n]+$/, "")), + !1 + ); + }), + t && (t = t.replace(/\S/g, "")), + t + ); + } + rawBeforeClose(e) { + let t; + return ( + e.walk((i) => { + if (i.nodes && i.nodes.length > 0 && typeof i.raws.after != "undefined") + return ( + (t = i.raws.after), + t.includes(` +`) && (t = t.replace(/[^\n]+$/, "")), + !1 + ); + }), + t && (t = t.replace(/\S/g, "")), + t + ); + } + rawBeforeOpen(e) { + let t; + return ( + e.walk((i) => { + if (i.type !== "decl" && ((t = i.raws.between), typeof t != "undefined")) return !1; + }), + t + ); + } + rawColon(e) { + let t; + return ( + e.walkDecls((i) => { + if (typeof i.raws.between != "undefined") + return ((t = i.raws.between.replace(/[^\s:]/g, "")), !1); + }), + t + ); + } + beforeAfter(e, t) { + let i; + e.type === "decl" + ? (i = this.raw(e, null, "beforeDecl")) + : e.type === "comment" + ? (i = this.raw(e, null, "beforeComment")) + : t === "before" + ? (i = this.raw(e, null, "beforeRule")) + : (i = this.raw(e, null, "beforeClose")); + let n = e.parent, + a = 0; + for (; n && n.type !== "root"; ) ((a += 1), (n = n.parent)); + if ( + i.includes(` +`) + ) { + let s = this.raw(e, null, "indent"); + if (s.length) for (let o = 0; o < a; o++) i += s; + } + return i; + } + rawValue(e, t) { + let i = e[t], + n = e.raws[t]; + return n && n.value === i ? n.raw : i; + } + }; + yf.exports = Ei; + Ei.default = Ei; + }); + var yr = v((g3, wf) => { + l(); + ("use strict"); + var x0 = Os(); + function Es(r, e) { + new x0(e).stringify(r); + } + wf.exports = Es; + Es.default = Es; + }); + var wr = v((y3, bf) => { + l(); + ("use strict"); + var { isClean: Ti, my: k0 } = Oi(), + S0 = _i(), + C0 = Os(), + A0 = yr(); + function Ts(r, e) { + let t = new r.constructor(); + for (let i in r) { + if (!Object.prototype.hasOwnProperty.call(r, i) || i === "proxyCache") continue; + let n = r[i], + a = typeof n; + i === "parent" && a === "object" + ? e && (t[i] = e) + : i === "source" + ? (t[i] = n) + : Array.isArray(n) + ? (t[i] = n.map((s) => Ts(s, t))) + : (a === "object" && n !== null && (n = Ts(n)), (t[i] = n)); + } + return t; + } + var Pi = class { + constructor(e = {}) { + ((this.raws = {}), (this[Ti] = !1), (this[k0] = !0)); + for (let t in e) + if (t === "nodes") { + this.nodes = []; + for (let i of e[t]) typeof i.clone == "function" ? this.append(i.clone()) : this.append(i); + } else this[t] = e[t]; + } + error(e, t = {}) { + if (this.source) { + let { start: i, end: n } = this.rangeBy(t); + return this.source.input.error( + e, + { line: i.line, column: i.column }, + { line: n.line, column: n.column }, + t + ); + } + return new S0(e); + } + warn(e, t, i) { + let n = { node: this }; + for (let a in i) n[a] = i[a]; + return e.warn(t, n); + } + remove() { + return (this.parent && this.parent.removeChild(this), (this.parent = void 0), this); + } + toString(e = A0) { + e.stringify && (e = e.stringify); + let t = ""; + return ( + e(this, (i) => { + t += i; + }), + t + ); + } + assign(e = {}) { + for (let t in e) this[t] = e[t]; + return this; + } + clone(e = {}) { + let t = Ts(this); + for (let i in e) t[i] = e[i]; + return t; + } + cloneBefore(e = {}) { + let t = this.clone(e); + return (this.parent.insertBefore(this, t), t); + } + cloneAfter(e = {}) { + let t = this.clone(e); + return (this.parent.insertAfter(this, t), t); + } + replaceWith(...e) { + if (this.parent) { + let t = this, + i = !1; + for (let n of e) + n === this + ? (i = !0) + : i + ? (this.parent.insertAfter(t, n), (t = n)) + : this.parent.insertBefore(t, n); + i || this.remove(); + } + return this; + } + next() { + if (!this.parent) return; + let e = this.parent.index(this); + return this.parent.nodes[e + 1]; + } + prev() { + if (!this.parent) return; + let e = this.parent.index(this); + return this.parent.nodes[e - 1]; + } + before(e) { + return (this.parent.insertBefore(this, e), this); + } + after(e) { + return (this.parent.insertAfter(this, e), this); + } + root() { + let e = this; + for (; e.parent && e.parent.type !== "document"; ) e = e.parent; + return e; + } + raw(e, t) { + return new C0().raw(this, e, t); + } + cleanRaws(e) { + (delete this.raws.before, delete this.raws.after, e || delete this.raws.between); + } + toJSON(e, t) { + let i = {}, + n = t == null; + t = t || new Map(); + let a = 0; + for (let s in this) { + if (!Object.prototype.hasOwnProperty.call(this, s) || s === "parent" || s === "proxyCache") + continue; + let o = this[s]; + if (Array.isArray(o)) + i[s] = o.map((u) => (typeof u == "object" && u.toJSON ? u.toJSON(null, t) : u)); + else if (typeof o == "object" && o.toJSON) i[s] = o.toJSON(null, t); + else if (s === "source") { + let u = t.get(o.input); + (u == null && ((u = a), t.set(o.input, a), a++), + (i[s] = { inputId: u, start: o.start, end: o.end })); + } else i[s] = o; + } + return (n && (i.inputs = [...t.keys()].map((s) => s.toJSON())), i); + } + positionInside(e) { + let t = this.toString(), + i = this.source.start.column, + n = this.source.start.line; + for (let a = 0; a < e; a++) + t[a] === + ` +` + ? ((i = 1), (n += 1)) + : (i += 1); + return { line: n, column: i }; + } + positionBy(e) { + let t = this.source.start; + if (e.index) t = this.positionInside(e.index); + else if (e.word) { + let i = this.toString().indexOf(e.word); + i !== -1 && (t = this.positionInside(i)); + } + return t; + } + rangeBy(e) { + let t = { line: this.source.start.line, column: this.source.start.column }, + i = this.source.end + ? { line: this.source.end.line, column: this.source.end.column + 1 } + : { line: t.line, column: t.column + 1 }; + if (e.word) { + let n = this.toString().indexOf(e.word); + n !== -1 && ((t = this.positionInside(n)), (i = this.positionInside(n + e.word.length))); + } else + (e.start + ? (t = { line: e.start.line, column: e.start.column }) + : e.index && (t = this.positionInside(e.index)), + e.end + ? (i = { line: e.end.line, column: e.end.column }) + : e.endIndex + ? (i = this.positionInside(e.endIndex)) + : e.index && (i = this.positionInside(e.index + 1))); + return ( + (i.line < t.line || (i.line === t.line && i.column <= t.column)) && + (i = { line: t.line, column: t.column + 1 }), + { start: t, end: i } + ); + } + getProxyProcessor() { + return { + set(e, t, i) { + return ( + e[t] === i || + ((e[t] = i), + (t === "prop" || + t === "value" || + t === "name" || + t === "params" || + t === "important" || + t === "text") && + e.markDirty()), + !0 + ); + }, + get(e, t) { + return t === "proxyOf" ? e : t === "root" ? () => e.root().toProxy() : e[t]; + }, + }; + } + toProxy() { + return ( + this.proxyCache || (this.proxyCache = new Proxy(this, this.getProxyProcessor())), + this.proxyCache + ); + } + addToError(e) { + if (((e.postcssNode = this), e.stack && this.source && /\n\s{4}at /.test(e.stack))) { + let t = this.source; + e.stack = e.stack.replace(/\n\s{4}at /, `$&${t.input.from}:${t.start.line}:${t.start.column}$&`); + } + return e; + } + markDirty() { + if (this[Ti]) { + this[Ti] = !1; + let e = this; + for (; (e = e.parent); ) e[Ti] = !1; + } + } + get proxyOf() { + return this; + } + }; + bf.exports = Pi; + Pi.default = Pi; + }); + var br = v((w3, vf) => { + l(); + ("use strict"); + var _0 = wr(), + Di = class extends _0 { + constructor(e) { + e && + typeof e.value != "undefined" && + typeof e.value != "string" && + (e = { ...e, value: String(e.value) }); + super(e); + this.type = "decl"; + } + get variable() { + return this.prop.startsWith("--") || this.prop[0] === "$"; + } + }; + vf.exports = Di; + Di.default = Di; + }); + var Ps = v((b3, xf) => { + l(); + xf.exports = function (r, e) { + return { + generate: () => { + let t = ""; + return ( + r(e, (i) => { + t += i; + }), + [t] + ); + }, + }; + }; + }); + var vr = v((v3, kf) => { + l(); + ("use strict"); + var O0 = wr(), + Ii = class extends O0 { + constructor(e) { + super(e); + this.type = "comment"; + } + }; + kf.exports = Ii; + Ii.default = Ii; + }); + var nt = v((x3, Df) => { + l(); + ("use strict"); + var { isClean: Sf, my: Cf } = Oi(), + Af = br(), + _f = vr(), + E0 = wr(), + Of, + Ds, + Is, + Ef; + function Tf(r) { + return r.map((e) => (e.nodes && (e.nodes = Tf(e.nodes)), delete e.source, e)); + } + function Pf(r) { + if (((r[Sf] = !1), r.proxyOf.nodes)) for (let e of r.proxyOf.nodes) Pf(e); + } + var we = class extends E0 { + push(e) { + return ((e.parent = this), this.proxyOf.nodes.push(e), this); + } + each(e) { + if (!this.proxyOf.nodes) return; + let t = this.getIterator(), + i, + n; + for ( + ; + this.indexes[t] < this.proxyOf.nodes.length && + ((i = this.indexes[t]), (n = e(this.proxyOf.nodes[i], i)), n !== !1); + ) + this.indexes[t] += 1; + return (delete this.indexes[t], n); + } + walk(e) { + return this.each((t, i) => { + let n; + try { + n = e(t, i); + } catch (a) { + throw t.addToError(a); + } + return (n !== !1 && t.walk && (n = t.walk(e)), n); + }); + } + walkDecls(e, t) { + return t + ? e instanceof RegExp + ? this.walk((i, n) => { + if (i.type === "decl" && e.test(i.prop)) return t(i, n); + }) + : this.walk((i, n) => { + if (i.type === "decl" && i.prop === e) return t(i, n); + }) + : ((t = e), + this.walk((i, n) => { + if (i.type === "decl") return t(i, n); + })); + } + walkRules(e, t) { + return t + ? e instanceof RegExp + ? this.walk((i, n) => { + if (i.type === "rule" && e.test(i.selector)) return t(i, n); + }) + : this.walk((i, n) => { + if (i.type === "rule" && i.selector === e) return t(i, n); + }) + : ((t = e), + this.walk((i, n) => { + if (i.type === "rule") return t(i, n); + })); + } + walkAtRules(e, t) { + return t + ? e instanceof RegExp + ? this.walk((i, n) => { + if (i.type === "atrule" && e.test(i.name)) return t(i, n); + }) + : this.walk((i, n) => { + if (i.type === "atrule" && i.name === e) return t(i, n); + }) + : ((t = e), + this.walk((i, n) => { + if (i.type === "atrule") return t(i, n); + })); + } + walkComments(e) { + return this.walk((t, i) => { + if (t.type === "comment") return e(t, i); + }); + } + append(...e) { + for (let t of e) { + let i = this.normalize(t, this.last); + for (let n of i) this.proxyOf.nodes.push(n); + } + return (this.markDirty(), this); + } + prepend(...e) { + e = e.reverse(); + for (let t of e) { + let i = this.normalize(t, this.first, "prepend").reverse(); + for (let n of i) this.proxyOf.nodes.unshift(n); + for (let n in this.indexes) this.indexes[n] = this.indexes[n] + i.length; + } + return (this.markDirty(), this); + } + cleanRaws(e) { + if ((super.cleanRaws(e), this.nodes)) for (let t of this.nodes) t.cleanRaws(e); + } + insertBefore(e, t) { + let i = this.index(e), + n = i === 0 ? "prepend" : !1, + a = this.normalize(t, this.proxyOf.nodes[i], n).reverse(); + i = this.index(e); + for (let o of a) this.proxyOf.nodes.splice(i, 0, o); + let s; + for (let o in this.indexes) ((s = this.indexes[o]), i <= s && (this.indexes[o] = s + a.length)); + return (this.markDirty(), this); + } + insertAfter(e, t) { + let i = this.index(e), + n = this.normalize(t, this.proxyOf.nodes[i]).reverse(); + i = this.index(e); + for (let s of n) this.proxyOf.nodes.splice(i + 1, 0, s); + let a; + for (let s in this.indexes) ((a = this.indexes[s]), i < a && (this.indexes[s] = a + n.length)); + return (this.markDirty(), this); + } + removeChild(e) { + ((e = this.index(e)), (this.proxyOf.nodes[e].parent = void 0), this.proxyOf.nodes.splice(e, 1)); + let t; + for (let i in this.indexes) ((t = this.indexes[i]), t >= e && (this.indexes[i] = t - 1)); + return (this.markDirty(), this); + } + removeAll() { + for (let e of this.proxyOf.nodes) e.parent = void 0; + return ((this.proxyOf.nodes = []), this.markDirty(), this); + } + replaceValues(e, t, i) { + return ( + i || ((i = t), (t = {})), + this.walkDecls((n) => { + (t.props && !t.props.includes(n.prop)) || + (t.fast && !n.value.includes(t.fast)) || + (n.value = n.value.replace(e, i)); + }), + this.markDirty(), + this + ); + } + every(e) { + return this.nodes.every(e); + } + some(e) { + return this.nodes.some(e); + } + index(e) { + return typeof e == "number" ? e : (e.proxyOf && (e = e.proxyOf), this.proxyOf.nodes.indexOf(e)); + } + get first() { + if (!!this.proxyOf.nodes) return this.proxyOf.nodes[0]; + } + get last() { + if (!!this.proxyOf.nodes) return this.proxyOf.nodes[this.proxyOf.nodes.length - 1]; + } + normalize(e, t) { + if (typeof e == "string") e = Tf(Of(e).nodes); + else if (Array.isArray(e)) { + e = e.slice(0); + for (let n of e) n.parent && n.parent.removeChild(n, "ignore"); + } else if (e.type === "root" && this.type !== "document") { + e = e.nodes.slice(0); + for (let n of e) n.parent && n.parent.removeChild(n, "ignore"); + } else if (e.type) e = [e]; + else if (e.prop) { + if (typeof e.value == "undefined") throw new Error("Value field is missed in node creation"); + (typeof e.value != "string" && (e.value = String(e.value)), (e = [new Af(e)])); + } else if (e.selector) e = [new Ds(e)]; + else if (e.name) e = [new Is(e)]; + else if (e.text) e = [new _f(e)]; + else throw new Error("Unknown node type in node creation"); + return e.map( + (n) => ( + n[Cf] || we.rebuild(n), + (n = n.proxyOf), + n.parent && n.parent.removeChild(n), + n[Sf] && Pf(n), + typeof n.raws.before == "undefined" && + t && + typeof t.raws.before != "undefined" && + (n.raws.before = t.raws.before.replace(/\S/g, "")), + (n.parent = this.proxyOf), + n + ) + ); + } + getProxyProcessor() { + return { + set(e, t, i) { + return ( + e[t] === i || + ((e[t] = i), (t === "name" || t === "params" || t === "selector") && e.markDirty()), + !0 + ); + }, + get(e, t) { + return t === "proxyOf" + ? e + : e[t] + ? t === "each" || (typeof t == "string" && t.startsWith("walk")) + ? (...i) => + e[t]( + ...i.map((n) => (typeof n == "function" ? (a, s) => n(a.toProxy(), s) : n)) + ) + : t === "every" || t === "some" + ? (i) => e[t]((n, ...a) => i(n.toProxy(), ...a)) + : t === "root" + ? () => e.root().toProxy() + : t === "nodes" + ? e.nodes.map((i) => i.toProxy()) + : t === "first" || t === "last" + ? e[t].toProxy() + : e[t] + : e[t]; + }, + }; + } + getIterator() { + (this.lastEach || (this.lastEach = 0), this.indexes || (this.indexes = {}), (this.lastEach += 1)); + let e = this.lastEach; + return ((this.indexes[e] = 0), e); + } + }; + we.registerParse = (r) => { + Of = r; + }; + we.registerRule = (r) => { + Ds = r; + }; + we.registerAtRule = (r) => { + Is = r; + }; + we.registerRoot = (r) => { + Ef = r; + }; + Df.exports = we; + we.default = we; + we.rebuild = (r) => { + (r.type === "atrule" + ? Object.setPrototypeOf(r, Is.prototype) + : r.type === "rule" + ? Object.setPrototypeOf(r, Ds.prototype) + : r.type === "decl" + ? Object.setPrototypeOf(r, Af.prototype) + : r.type === "comment" + ? Object.setPrototypeOf(r, _f.prototype) + : r.type === "root" && Object.setPrototypeOf(r, Ef.prototype), + (r[Cf] = !0), + r.nodes && + r.nodes.forEach((e) => { + we.rebuild(e); + })); + }; + }); + var qi = v((k3, Rf) => { + l(); + ("use strict"); + var T0 = nt(), + If, + qf, + Pt = class extends T0 { + constructor(e) { + super({ type: "document", ...e }); + this.nodes || (this.nodes = []); + } + toResult(e = {}) { + return new If(new qf(), this, e).stringify(); + } + }; + Pt.registerLazyResult = (r) => { + If = r; + }; + Pt.registerProcessor = (r) => { + qf = r; + }; + Rf.exports = Pt; + Pt.default = Pt; + }); + var qs = v((S3, Bf) => { + l(); + ("use strict"); + var Mf = {}; + Bf.exports = function (e) { + Mf[e] || ((Mf[e] = !0), typeof console != "undefined" && console.warn && console.warn(e)); + }; + }); + var Rs = v((C3, Ff) => { + l(); + ("use strict"); + var Ri = class { + constructor(e, t = {}) { + if (((this.type = "warning"), (this.text = e), t.node && t.node.source)) { + let i = t.node.rangeBy(t); + ((this.line = i.start.line), + (this.column = i.start.column), + (this.endLine = i.end.line), + (this.endColumn = i.end.column)); + } + for (let i in t) this[i] = t[i]; + } + toString() { + return this.node + ? this.node.error(this.text, { plugin: this.plugin, index: this.index, word: this.word }).message + : this.plugin + ? this.plugin + ": " + this.text + : this.text; + } + }; + Ff.exports = Ri; + Ri.default = Ri; + }); + var Bi = v((A3, Lf) => { + l(); + ("use strict"); + var P0 = Rs(), + Mi = class { + constructor(e, t, i) { + ((this.processor = e), + (this.messages = []), + (this.root = t), + (this.opts = i), + (this.css = void 0), + (this.map = void 0)); + } + toString() { + return this.css; + } + warn(e, t = {}) { + t.plugin || + (this.lastPlugin && + this.lastPlugin.postcssPlugin && + (t.plugin = this.lastPlugin.postcssPlugin)); + let i = new P0(e, t); + return (this.messages.push(i), i); + } + warnings() { + return this.messages.filter((e) => e.type === "warning"); + } + get content() { + return this.css; + } + }; + Lf.exports = Mi; + Mi.default = Mi; + }); + var Vf = v((_3, jf) => { + l(); + ("use strict"); + var Ms = "'".charCodeAt(0), + Nf = '"'.charCodeAt(0), + Fi = "\\".charCodeAt(0), + $f = "/".charCodeAt(0), + Li = ` +`.charCodeAt(0), + xr = " ".charCodeAt(0), + Ni = "\f".charCodeAt(0), + $i = " ".charCodeAt(0), + zi = "\r".charCodeAt(0), + D0 = "[".charCodeAt(0), + I0 = "]".charCodeAt(0), + q0 = "(".charCodeAt(0), + R0 = ")".charCodeAt(0), + M0 = "{".charCodeAt(0), + B0 = "}".charCodeAt(0), + F0 = ";".charCodeAt(0), + L0 = "*".charCodeAt(0), + N0 = ":".charCodeAt(0), + $0 = "@".charCodeAt(0), + ji = /[\t\n\f\r "#'()/;[\\\]{}]/g, + Vi = /[\t\n\f\r !"#'():;@[\\\]{}]|\/(?=\*)/g, + z0 = /.[\n"'(/\\]/, + zf = /[\da-f]/i; + jf.exports = function (e, t = {}) { + let i = e.css.valueOf(), + n = t.ignoreErrors, + a, + s, + o, + u, + c, + f, + d, + p, + m, + b, + x = i.length, + y = 0, + w = [], + k = []; + function S() { + return y; + } + function _(R) { + throw e.error("Unclosed " + R, y); + } + function E() { + return k.length === 0 && y >= x; + } + function I(R) { + if (k.length) return k.pop(); + if (y >= x) return; + let J = R ? R.ignoreUnclosed : !1; + switch (((a = i.charCodeAt(y)), a)) { + case Li: + case xr: + case $i: + case zi: + case Ni: { + s = y; + do ((s += 1), (a = i.charCodeAt(s))); + while (a === xr || a === Li || a === $i || a === zi || a === Ni); + ((b = ["space", i.slice(y, s)]), (y = s - 1)); + break; + } + case D0: + case I0: + case M0: + case B0: + case N0: + case F0: + case R0: { + let ue = String.fromCharCode(a); + b = [ue, ue, y]; + break; + } + case q0: { + if ( + ((p = w.length ? w.pop()[1] : ""), + (m = i.charCodeAt(y + 1)), + p === "url" && + m !== Ms && + m !== Nf && + m !== xr && + m !== Li && + m !== $i && + m !== Ni && + m !== zi) + ) { + s = y; + do { + if (((f = !1), (s = i.indexOf(")", s + 1)), s === -1)) + if (n || J) { + s = y; + break; + } else _("bracket"); + for (d = s; i.charCodeAt(d - 1) === Fi; ) ((d -= 1), (f = !f)); + } while (f); + ((b = ["brackets", i.slice(y, s + 1), y, s]), (y = s)); + } else + ((s = i.indexOf(")", y + 1)), + (u = i.slice(y, s + 1)), + s === -1 || z0.test(u) ? (b = ["(", "(", y]) : ((b = ["brackets", u, y, s]), (y = s))); + break; + } + case Ms: + case Nf: { + ((o = a === Ms ? "'" : '"'), (s = y)); + do { + if (((f = !1), (s = i.indexOf(o, s + 1)), s === -1)) + if (n || J) { + s = y + 1; + break; + } else _("string"); + for (d = s; i.charCodeAt(d - 1) === Fi; ) ((d -= 1), (f = !f)); + } while (f); + ((b = ["string", i.slice(y, s + 1), y, s]), (y = s)); + break; + } + case $0: { + ((ji.lastIndex = y + 1), + ji.test(i), + ji.lastIndex === 0 ? (s = i.length - 1) : (s = ji.lastIndex - 2), + (b = ["at-word", i.slice(y, s + 1), y, s]), + (y = s)); + break; + } + case Fi: { + for (s = y, c = !0; i.charCodeAt(s + 1) === Fi; ) ((s += 1), (c = !c)); + if ( + ((a = i.charCodeAt(s + 1)), + c && + a !== $f && + a !== xr && + a !== Li && + a !== $i && + a !== zi && + a !== Ni && + ((s += 1), zf.test(i.charAt(s)))) + ) { + for (; zf.test(i.charAt(s + 1)); ) s += 1; + i.charCodeAt(s + 1) === xr && (s += 1); + } + ((b = ["word", i.slice(y, s + 1), y, s]), (y = s)); + break; + } + default: { + a === $f && i.charCodeAt(y + 1) === L0 + ? ((s = i.indexOf("*/", y + 2) + 1), + s === 0 && (n || J ? (s = i.length) : _("comment")), + (b = ["comment", i.slice(y, s + 1), y, s]), + (y = s)) + : ((Vi.lastIndex = y + 1), + Vi.test(i), + Vi.lastIndex === 0 ? (s = i.length - 1) : (s = Vi.lastIndex - 2), + (b = ["word", i.slice(y, s + 1), y, s]), + w.push(b), + (y = s)); + break; + } + } + return (y++, b); + } + function q(R) { + k.push(R); + } + return { back: q, nextToken: I, endOfFile: E, position: S }; + }; + }); + var Ui = v((O3, Wf) => { + l(); + ("use strict"); + var Uf = nt(), + kr = class extends Uf { + constructor(e) { + super(e); + this.type = "atrule"; + } + append(...e) { + return (this.proxyOf.nodes || (this.nodes = []), super.append(...e)); + } + prepend(...e) { + return (this.proxyOf.nodes || (this.nodes = []), super.prepend(...e)); + } + }; + Wf.exports = kr; + kr.default = kr; + Uf.registerAtRule(kr); + }); + var Dt = v((E3, Qf) => { + l(); + ("use strict"); + var Gf = nt(), + Hf, + Yf, + vt = class extends Gf { + constructor(e) { + super(e); + ((this.type = "root"), this.nodes || (this.nodes = [])); + } + removeChild(e, t) { + let i = this.index(e); + return ( + !t && + i === 0 && + this.nodes.length > 1 && + (this.nodes[1].raws.before = this.nodes[i].raws.before), + super.removeChild(e) + ); + } + normalize(e, t, i) { + let n = super.normalize(e); + if (t) { + if (i === "prepend") + this.nodes.length > 1 ? (t.raws.before = this.nodes[1].raws.before) : delete t.raws.before; + else if (this.first !== t) for (let a of n) a.raws.before = t.raws.before; + } + return n; + } + toResult(e = {}) { + return new Hf(new Yf(), this, e).stringify(); + } + }; + vt.registerLazyResult = (r) => { + Hf = r; + }; + vt.registerProcessor = (r) => { + Yf = r; + }; + Qf.exports = vt; + vt.default = vt; + Gf.registerRoot(vt); + }); + var Bs = v((T3, Jf) => { + l(); + ("use strict"); + var Sr = { + split(r, e, t) { + let i = [], + n = "", + a = !1, + s = 0, + o = !1, + u = "", + c = !1; + for (let f of r) + (c + ? (c = !1) + : f === "\\" + ? (c = !0) + : o + ? f === u && (o = !1) + : f === '"' || f === "'" + ? ((o = !0), (u = f)) + : f === "(" + ? (s += 1) + : f === ")" + ? s > 0 && (s -= 1) + : s === 0 && e.includes(f) && (a = !0), + a ? (n !== "" && i.push(n.trim()), (n = ""), (a = !1)) : (n += f)); + return ((t || n !== "") && i.push(n.trim()), i); + }, + space(r) { + let e = [ + " ", + ` +`, + " ", + ]; + return Sr.split(r, e); + }, + comma(r) { + return Sr.split(r, [","], !0); + }, + }; + Jf.exports = Sr; + Sr.default = Sr; + }); + var Wi = v((P3, Kf) => { + l(); + ("use strict"); + var Xf = nt(), + j0 = Bs(), + Cr = class extends Xf { + constructor(e) { + super(e); + ((this.type = "rule"), this.nodes || (this.nodes = [])); + } + get selectors() { + return j0.comma(this.selector); + } + set selectors(e) { + let t = this.selector ? this.selector.match(/,\s*/) : null, + i = t ? t[0] : "," + this.raw("between", "beforeOpen"); + this.selector = e.join(i); + } + }; + Kf.exports = Cr; + Cr.default = Cr; + Xf.registerRule(Cr); + }); + var ic = v((D3, rc) => { + l(); + ("use strict"); + var V0 = br(), + U0 = Vf(), + W0 = vr(), + G0 = Ui(), + H0 = Dt(), + Zf = Wi(), + ec = { empty: !0, space: !0 }; + function Y0(r) { + for (let e = r.length - 1; e >= 0; e--) { + let t = r[e], + i = t[3] || t[2]; + if (i) return i; + } + } + var tc = class { + constructor(e) { + ((this.input = e), + (this.root = new H0()), + (this.current = this.root), + (this.spaces = ""), + (this.semicolon = !1), + (this.customProperty = !1), + this.createTokenizer(), + (this.root.source = { input: e, start: { offset: 0, line: 1, column: 1 } })); + } + createTokenizer() { + this.tokenizer = U0(this.input); + } + parse() { + let e; + for (; !this.tokenizer.endOfFile(); ) + switch (((e = this.tokenizer.nextToken()), e[0])) { + case "space": + this.spaces += e[1]; + break; + case ";": + this.freeSemicolon(e); + break; + case "}": + this.end(e); + break; + case "comment": + this.comment(e); + break; + case "at-word": + this.atrule(e); + break; + case "{": + this.emptyRule(e); + break; + default: + this.other(e); + break; + } + this.endFile(); + } + comment(e) { + let t = new W0(); + (this.init(t, e[2]), (t.source.end = this.getPosition(e[3] || e[2]))); + let i = e[1].slice(2, -2); + if (/^\s*$/.test(i)) ((t.text = ""), (t.raws.left = i), (t.raws.right = "")); + else { + let n = i.match(/^(\s*)([^]*\S)(\s*)$/); + ((t.text = n[2]), (t.raws.left = n[1]), (t.raws.right = n[3])); + } + } + emptyRule(e) { + let t = new Zf(); + (this.init(t, e[2]), (t.selector = ""), (t.raws.between = ""), (this.current = t)); + } + other(e) { + let t = !1, + i = null, + n = !1, + a = null, + s = [], + o = e[1].startsWith("--"), + u = [], + c = e; + for (; c; ) { + if (((i = c[0]), u.push(c), i === "(" || i === "[")) (a || (a = c), s.push(i === "(" ? ")" : "]")); + else if (o && n && i === "{") (a || (a = c), s.push("}")); + else if (s.length === 0) + if (i === ";") + if (n) { + this.decl(u, o); + return; + } else break; + else if (i === "{") { + this.rule(u); + return; + } else if (i === "}") { + (this.tokenizer.back(u.pop()), (t = !0)); + break; + } else i === ":" && (n = !0); + else i === s[s.length - 1] && (s.pop(), s.length === 0 && (a = null)); + c = this.tokenizer.nextToken(); + } + if ((this.tokenizer.endOfFile() && (t = !0), s.length > 0 && this.unclosedBracket(a), t && n)) { + if (!o) + for (; u.length && ((c = u[u.length - 1][0]), !(c !== "space" && c !== "comment")); ) + this.tokenizer.back(u.pop()); + this.decl(u, o); + } else this.unknownWord(u); + } + rule(e) { + e.pop(); + let t = new Zf(); + (this.init(t, e[0][2]), + (t.raws.between = this.spacesAndCommentsFromEnd(e)), + this.raw(t, "selector", e), + (this.current = t)); + } + decl(e, t) { + let i = new V0(); + this.init(i, e[0][2]); + let n = e[e.length - 1]; + for ( + n[0] === ";" && ((this.semicolon = !0), e.pop()), + i.source.end = this.getPosition(n[3] || n[2] || Y0(e)); + e[0][0] !== "word"; + ) + (e.length === 1 && this.unknownWord(e), (i.raws.before += e.shift()[1])); + for (i.source.start = this.getPosition(e[0][2]), i.prop = ""; e.length; ) { + let c = e[0][0]; + if (c === ":" || c === "space" || c === "comment") break; + i.prop += e.shift()[1]; + } + i.raws.between = ""; + let a; + for (; e.length; ) + if (((a = e.shift()), a[0] === ":")) { + i.raws.between += a[1]; + break; + } else (a[0] === "word" && /\w/.test(a[1]) && this.unknownWord([a]), (i.raws.between += a[1])); + (i.prop[0] === "_" || i.prop[0] === "*") && ((i.raws.before += i.prop[0]), (i.prop = i.prop.slice(1))); + let s = [], + o; + for (; e.length && ((o = e[0][0]), !(o !== "space" && o !== "comment")); ) s.push(e.shift()); + this.precheckMissedSemicolon(e); + for (let c = e.length - 1; c >= 0; c--) { + if (((a = e[c]), a[1].toLowerCase() === "!important")) { + i.important = !0; + let f = this.stringFrom(e, c); + ((f = this.spacesFromEnd(e) + f), f !== " !important" && (i.raws.important = f)); + break; + } else if (a[1].toLowerCase() === "important") { + let f = e.slice(0), + d = ""; + for (let p = c; p > 0; p--) { + let m = f[p][0]; + if (d.trim().indexOf("!") === 0 && m !== "space") break; + d = f.pop()[1] + d; + } + d.trim().indexOf("!") === 0 && ((i.important = !0), (i.raws.important = d), (e = f)); + } + if (a[0] !== "space" && a[0] !== "comment") break; + } + (e.some((c) => c[0] !== "space" && c[0] !== "comment") && + ((i.raws.between += s.map((c) => c[1]).join("")), (s = [])), + this.raw(i, "value", s.concat(e), t), + i.value.includes(":") && !t && this.checkMissedSemicolon(e)); + } + atrule(e) { + let t = new G0(); + ((t.name = e[1].slice(1)), t.name === "" && this.unnamedAtrule(t, e), this.init(t, e[2])); + let i, + n, + a, + s = !1, + o = !1, + u = [], + c = []; + for (; !this.tokenizer.endOfFile(); ) { + if ( + ((e = this.tokenizer.nextToken()), + (i = e[0]), + i === "(" || i === "[" + ? c.push(i === "(" ? ")" : "]") + : i === "{" && c.length > 0 + ? c.push("}") + : i === c[c.length - 1] && c.pop(), + c.length === 0) + ) + if (i === ";") { + ((t.source.end = this.getPosition(e[2])), (this.semicolon = !0)); + break; + } else if (i === "{") { + o = !0; + break; + } else if (i === "}") { + if (u.length > 0) { + for (a = u.length - 1, n = u[a]; n && n[0] === "space"; ) n = u[--a]; + n && (t.source.end = this.getPosition(n[3] || n[2])); + } + this.end(e); + break; + } else u.push(e); + else u.push(e); + if (this.tokenizer.endOfFile()) { + s = !0; + break; + } + } + ((t.raws.between = this.spacesAndCommentsFromEnd(u)), + u.length + ? ((t.raws.afterName = this.spacesAndCommentsFromStart(u)), + this.raw(t, "params", u), + s && + ((e = u[u.length - 1]), + (t.source.end = this.getPosition(e[3] || e[2])), + (this.spaces = t.raws.between), + (t.raws.between = ""))) + : ((t.raws.afterName = ""), (t.params = "")), + o && ((t.nodes = []), (this.current = t))); + } + end(e) { + (this.current.nodes && this.current.nodes.length && (this.current.raws.semicolon = this.semicolon), + (this.semicolon = !1), + (this.current.raws.after = (this.current.raws.after || "") + this.spaces), + (this.spaces = ""), + this.current.parent + ? ((this.current.source.end = this.getPosition(e[2])), (this.current = this.current.parent)) + : this.unexpectedClose(e)); + } + endFile() { + (this.current.parent && this.unclosedBlock(), + this.current.nodes && this.current.nodes.length && (this.current.raws.semicolon = this.semicolon), + (this.current.raws.after = (this.current.raws.after || "") + this.spaces)); + } + freeSemicolon(e) { + if (((this.spaces += e[1]), this.current.nodes)) { + let t = this.current.nodes[this.current.nodes.length - 1]; + t && + t.type === "rule" && + !t.raws.ownSemicolon && + ((t.raws.ownSemicolon = this.spaces), (this.spaces = "")); + } + } + getPosition(e) { + let t = this.input.fromOffset(e); + return { offset: e, line: t.line, column: t.col }; + } + init(e, t) { + (this.current.push(e), + (e.source = { start: this.getPosition(t), input: this.input }), + (e.raws.before = this.spaces), + (this.spaces = ""), + e.type !== "comment" && (this.semicolon = !1)); + } + raw(e, t, i, n) { + let a, + s, + o = i.length, + u = "", + c = !0, + f, + d; + for (let p = 0; p < o; p += 1) + ((a = i[p]), + (s = a[0]), + s === "space" && p === o - 1 && !n + ? (c = !1) + : s === "comment" + ? ((d = i[p - 1] ? i[p - 1][0] : "empty"), + (f = i[p + 1] ? i[p + 1][0] : "empty"), + !ec[d] && !ec[f] ? (u.slice(-1) === "," ? (c = !1) : (u += a[1])) : (c = !1)) + : (u += a[1])); + if (!c) { + let p = i.reduce((m, b) => m + b[1], ""); + e.raws[t] = { value: u, raw: p }; + } + e[t] = u; + } + spacesAndCommentsFromEnd(e) { + let t, + i = ""; + for (; e.length && ((t = e[e.length - 1][0]), !(t !== "space" && t !== "comment")); ) + i = e.pop()[1] + i; + return i; + } + spacesAndCommentsFromStart(e) { + let t, + i = ""; + for (; e.length && ((t = e[0][0]), !(t !== "space" && t !== "comment")); ) i += e.shift()[1]; + return i; + } + spacesFromEnd(e) { + let t, + i = ""; + for (; e.length && ((t = e[e.length - 1][0]), t === "space"); ) i = e.pop()[1] + i; + return i; + } + stringFrom(e, t) { + let i = ""; + for (let n = t; n < e.length; n++) i += e[n][1]; + return (e.splice(t, e.length - t), i); + } + colon(e) { + let t = 0, + i, + n, + a; + for (let [s, o] of e.entries()) { + if (((i = o), (n = i[0]), n === "(" && (t += 1), n === ")" && (t -= 1), t === 0 && n === ":")) + if (!a) this.doubleColon(i); + else { + if (a[0] === "word" && a[1] === "progid") continue; + return s; + } + a = i; + } + return !1; + } + unclosedBracket(e) { + throw this.input.error("Unclosed bracket", { offset: e[2] }, { offset: e[2] + 1 }); + } + unknownWord(e) { + throw this.input.error("Unknown word", { offset: e[0][2] }, { offset: e[0][2] + e[0][1].length }); + } + unexpectedClose(e) { + throw this.input.error("Unexpected }", { offset: e[2] }, { offset: e[2] + 1 }); + } + unclosedBlock() { + let e = this.current.source.start; + throw this.input.error("Unclosed block", e.line, e.column); + } + doubleColon(e) { + throw this.input.error("Double colon", { offset: e[2] }, { offset: e[2] + e[1].length }); + } + unnamedAtrule(e, t) { + throw this.input.error("At-rule without name", { offset: t[2] }, { offset: t[2] + t[1].length }); + } + precheckMissedSemicolon() {} + checkMissedSemicolon(e) { + let t = this.colon(e); + if (t === !1) return; + let i = 0, + n; + for (let a = t - 1; a >= 0 && ((n = e[a]), !(n[0] !== "space" && ((i += 1), i === 2))); a--); + throw this.input.error("Missed semicolon", n[0] === "word" ? n[3] + 1 : n[2]); + } + }; + rc.exports = tc; + }); + var nc = v(() => { + l(); + }); + var ac = v((R3, sc) => { + l(); + var Q0 = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict", + J0 = + (r, e = 21) => + (t = e) => { + let i = "", + n = t; + for (; n--; ) i += r[(Math.random() * r.length) | 0]; + return i; + }, + X0 = (r = 21) => { + let e = "", + t = r; + for (; t--; ) e += Q0[(Math.random() * 64) | 0]; + return e; + }; + sc.exports = { nanoid: X0, customAlphabet: J0 }; + }); + var Fs = v((M3, oc) => { + l(); + oc.exports = {}; + }); + var Hi = v((B3, cc) => { + l(); + ("use strict"); + var { SourceMapConsumer: K0, SourceMapGenerator: Z0 } = nc(), + { fileURLToPath: lc, pathToFileURL: Gi } = (Cs(), pf), + { resolve: Ls, isAbsolute: Ns } = (bt(), uf), + { nanoid: ev } = ac(), + $s = As(), + uc = _i(), + tv = Fs(), + zs = Symbol("fromOffsetCache"), + rv = Boolean(K0 && Z0), + fc = Boolean(Ls && Ns), + Ar = class { + constructor(e, t = {}) { + if (e === null || typeof e == "undefined" || (typeof e == "object" && !e.toString)) + throw new Error(`PostCSS received ${e} instead of CSS string`); + if ( + ((this.css = e.toString()), + this.css[0] === "\uFEFF" || this.css[0] === "\uFFFE" + ? ((this.hasBOM = !0), (this.css = this.css.slice(1))) + : (this.hasBOM = !1), + t.from && + (!fc || /^\w+:\/\//.test(t.from) || Ns(t.from) + ? (this.file = t.from) + : (this.file = Ls(t.from))), + fc && rv) + ) { + let i = new tv(this.css, t); + if (i.text) { + this.map = i; + let n = i.consumer().file; + !this.file && n && (this.file = this.mapResolve(n)); + } + } + (this.file || (this.id = ""), this.map && (this.map.file = this.from)); + } + fromOffset(e) { + let t, i; + if (this[zs]) i = this[zs]; + else { + let a = this.css.split(` +`); + i = new Array(a.length); + let s = 0; + for (let o = 0, u = a.length; o < u; o++) ((i[o] = s), (s += a[o].length + 1)); + this[zs] = i; + } + t = i[i.length - 1]; + let n = 0; + if (e >= t) n = i.length - 1; + else { + let a = i.length - 2, + s; + for (; n < a; ) + if (((s = n + ((a - n) >> 1)), e < i[s])) a = s - 1; + else if (e >= i[s + 1]) n = s + 1; + else { + n = s; + break; + } + } + return { line: n + 1, col: e - i[n] + 1 }; + } + error(e, t, i, n = {}) { + let a, s, o; + if (t && typeof t == "object") { + let c = t, + f = i; + if (typeof c.offset == "number") { + let d = this.fromOffset(c.offset); + ((t = d.line), (i = d.col)); + } else ((t = c.line), (i = c.column)); + if (typeof f.offset == "number") { + let d = this.fromOffset(f.offset); + ((s = d.line), (o = d.col)); + } else ((s = f.line), (o = f.column)); + } else if (!i) { + let c = this.fromOffset(t); + ((t = c.line), (i = c.col)); + } + let u = this.origin(t, i, s, o); + return ( + u + ? (a = new uc( + e, + u.endLine === void 0 ? u.line : { line: u.line, column: u.column }, + u.endLine === void 0 ? u.column : { line: u.endLine, column: u.endColumn }, + u.source, + u.file, + n.plugin + )) + : (a = new uc( + e, + s === void 0 ? t : { line: t, column: i }, + s === void 0 ? i : { line: s, column: o }, + this.css, + this.file, + n.plugin + )), + (a.input = { line: t, column: i, endLine: s, endColumn: o, source: this.css }), + this.file && (Gi && (a.input.url = Gi(this.file).toString()), (a.input.file = this.file)), + a + ); + } + origin(e, t, i, n) { + if (!this.map) return !1; + let a = this.map.consumer(), + s = a.originalPositionFor({ line: e, column: t }); + if (!s.source) return !1; + let o; + typeof i == "number" && (o = a.originalPositionFor({ line: i, column: n })); + let u; + Ns(s.source) + ? (u = Gi(s.source)) + : (u = new URL(s.source, this.map.consumer().sourceRoot || Gi(this.map.mapFile))); + let c = { + url: u.toString(), + line: s.line, + column: s.column, + endLine: o && o.line, + endColumn: o && o.column, + }; + if (u.protocol === "file:") + if (lc) c.file = lc(u); + else throw new Error("file: protocol is not available in this PostCSS build"); + let f = a.sourceContentFor(s.source); + return (f && (c.source = f), c); + } + mapResolve(e) { + return /^\w+:\/\//.test(e) ? e : Ls(this.map.consumer().sourceRoot || this.map.root || ".", e); + } + get from() { + return this.file || this.id; + } + toJSON() { + let e = {}; + for (let t of ["hasBOM", "css", "file", "id"]) this[t] != null && (e[t] = this[t]); + return ( + this.map && ((e.map = { ...this.map }), e.map.consumerCache && (e.map.consumerCache = void 0)), + e + ); + } + }; + cc.exports = Ar; + Ar.default = Ar; + $s && $s.registerInput && $s.registerInput(Ar); + }); + var Qi = v((F3, pc) => { + l(); + ("use strict"); + var iv = nt(), + nv = ic(), + sv = Hi(); + function Yi(r, e) { + let t = new sv(r, e), + i = new nv(t); + try { + i.parse(); + } catch (n) { + throw n; + } + return i.root; + } + pc.exports = Yi; + Yi.default = Yi; + iv.registerParse(Yi); + }); + var Us = v((N3, gc) => { + l(); + ("use strict"); + var { isClean: qe, my: av } = Oi(), + ov = Ps(), + lv = yr(), + uv = nt(), + fv = qi(), + L3 = qs(), + dc = Bi(), + cv = Qi(), + pv = Dt(), + dv = { + document: "Document", + root: "Root", + atrule: "AtRule", + rule: "Rule", + decl: "Declaration", + comment: "Comment", + }, + hv = { + postcssPlugin: !0, + prepare: !0, + Once: !0, + Document: !0, + Root: !0, + Declaration: !0, + Rule: !0, + AtRule: !0, + Comment: !0, + DeclarationExit: !0, + RuleExit: !0, + AtRuleExit: !0, + CommentExit: !0, + RootExit: !0, + DocumentExit: !0, + OnceExit: !0, + }, + mv = { postcssPlugin: !0, prepare: !0, Once: !0 }, + It = 0; + function _r(r) { + return typeof r == "object" && typeof r.then == "function"; + } + function hc(r) { + let e = !1, + t = dv[r.type]; + return ( + r.type === "decl" ? (e = r.prop.toLowerCase()) : r.type === "atrule" && (e = r.name.toLowerCase()), + e && r.append + ? [t, t + "-" + e, It, t + "Exit", t + "Exit-" + e] + : e + ? [t, t + "-" + e, t + "Exit", t + "Exit-" + e] + : r.append + ? [t, It, t + "Exit"] + : [t, t + "Exit"] + ); + } + function mc(r) { + let e; + return ( + r.type === "document" + ? (e = ["Document", It, "DocumentExit"]) + : r.type === "root" + ? (e = ["Root", It, "RootExit"]) + : (e = hc(r)), + { node: r, events: e, eventIndex: 0, visitors: [], visitorIndex: 0, iterator: 0 } + ); + } + function js(r) { + return ((r[qe] = !1), r.nodes && r.nodes.forEach((e) => js(e)), r); + } + var Vs = {}, + Ve = class { + constructor(e, t, i) { + ((this.stringified = !1), (this.processed = !1)); + let n; + if (typeof t == "object" && t !== null && (t.type === "root" || t.type === "document")) n = js(t); + else if (t instanceof Ve || t instanceof dc) + ((n = js(t.root)), + t.map && + (typeof i.map == "undefined" && (i.map = {}), + i.map.inline || (i.map.inline = !1), + (i.map.prev = t.map))); + else { + let a = cv; + (i.syntax && (a = i.syntax.parse), i.parser && (a = i.parser), a.parse && (a = a.parse)); + try { + n = a(t, i); + } catch (s) { + ((this.processed = !0), (this.error = s)); + } + n && !n[av] && uv.rebuild(n); + } + ((this.result = new dc(e, n, i)), + (this.helpers = { ...Vs, result: this.result, postcss: Vs }), + (this.plugins = this.processor.plugins.map((a) => + typeof a == "object" && a.prepare ? { ...a, ...a.prepare(this.result) } : a + ))); + } + get [Symbol.toStringTag]() { + return "LazyResult"; + } + get processor() { + return this.result.processor; + } + get opts() { + return this.result.opts; + } + get css() { + return this.stringify().css; + } + get content() { + return this.stringify().content; + } + get map() { + return this.stringify().map; + } + get root() { + return this.sync().root; + } + get messages() { + return this.sync().messages; + } + warnings() { + return this.sync().warnings(); + } + toString() { + return this.css; + } + then(e, t) { + return this.async().then(e, t); + } + catch(e) { + return this.async().catch(e); + } + finally(e) { + return this.async().then(e, e); + } + async() { + return this.error + ? Promise.reject(this.error) + : this.processed + ? Promise.resolve(this.result) + : (this.processing || (this.processing = this.runAsync()), this.processing); + } + sync() { + if (this.error) throw this.error; + if (this.processed) return this.result; + if (((this.processed = !0), this.processing)) throw this.getAsyncError(); + for (let e of this.plugins) { + let t = this.runOnRoot(e); + if (_r(t)) throw this.getAsyncError(); + } + if ((this.prepareVisitors(), this.hasListener)) { + let e = this.result.root; + for (; !e[qe]; ) ((e[qe] = !0), this.walkSync(e)); + if (this.listeners.OnceExit) + if (e.type === "document") + for (let t of e.nodes) this.visitSync(this.listeners.OnceExit, t); + else this.visitSync(this.listeners.OnceExit, e); + } + return this.result; + } + stringify() { + if (this.error) throw this.error; + if (this.stringified) return this.result; + ((this.stringified = !0), this.sync()); + let e = this.result.opts, + t = lv; + (e.syntax && (t = e.syntax.stringify), + e.stringifier && (t = e.stringifier), + t.stringify && (t = t.stringify)); + let n = new ov(t, this.result.root, this.result.opts).generate(); + return ((this.result.css = n[0]), (this.result.map = n[1]), this.result); + } + walkSync(e) { + e[qe] = !0; + let t = hc(e); + for (let i of t) + if (i === It) + e.nodes && + e.each((n) => { + n[qe] || this.walkSync(n); + }); + else { + let n = this.listeners[i]; + if (n && this.visitSync(n, e.toProxy())) return; + } + } + visitSync(e, t) { + for (let [i, n] of e) { + this.result.lastPlugin = i; + let a; + try { + a = n(t, this.helpers); + } catch (s) { + throw this.handleError(s, t.proxyOf); + } + if (t.type !== "root" && t.type !== "document" && !t.parent) return !0; + if (_r(a)) throw this.getAsyncError(); + } + } + runOnRoot(e) { + this.result.lastPlugin = e; + try { + if (typeof e == "object" && e.Once) { + if (this.result.root.type === "document") { + let t = this.result.root.nodes.map((i) => e.Once(i, this.helpers)); + return _r(t[0]) ? Promise.all(t) : t; + } + return e.Once(this.result.root, this.helpers); + } else if (typeof e == "function") return e(this.result.root, this.result); + } catch (t) { + throw this.handleError(t); + } + } + getAsyncError() { + throw new Error("Use process(css).then(cb) to work with async plugins"); + } + handleError(e, t) { + let i = this.result.lastPlugin; + try { + (t && t.addToError(e), + (this.error = e), + e.name === "CssSyntaxError" && !e.plugin + ? ((e.plugin = i.postcssPlugin), e.setMessage()) + : i.postcssVersion); + } catch (n) { + console && console.error && console.error(n); + } + return e; + } + async runAsync() { + this.plugin = 0; + for (let e = 0; e < this.plugins.length; e++) { + let t = this.plugins[e], + i = this.runOnRoot(t); + if (_r(i)) + try { + await i; + } catch (n) { + throw this.handleError(n); + } + } + if ((this.prepareVisitors(), this.hasListener)) { + let e = this.result.root; + for (; !e[qe]; ) { + e[qe] = !0; + let t = [mc(e)]; + for (; t.length > 0; ) { + let i = this.visitTick(t); + if (_r(i)) + try { + await i; + } catch (n) { + let a = t[t.length - 1].node; + throw this.handleError(n, a); + } + } + } + if (this.listeners.OnceExit) + for (let [t, i] of this.listeners.OnceExit) { + this.result.lastPlugin = t; + try { + if (e.type === "document") { + let n = e.nodes.map((a) => i(a, this.helpers)); + await Promise.all(n); + } else await i(e, this.helpers); + } catch (n) { + throw this.handleError(n); + } + } + } + return ((this.processed = !0), this.stringify()); + } + prepareVisitors() { + this.listeners = {}; + let e = (t, i, n) => { + (this.listeners[i] || (this.listeners[i] = []), this.listeners[i].push([t, n])); + }; + for (let t of this.plugins) + if (typeof t == "object") + for (let i in t) { + if (!hv[i] && /^[A-Z]/.test(i)) + throw new Error( + `Unknown event ${i} in ${t.postcssPlugin}. Try to update PostCSS (${this.processor.version} now).` + ); + if (!mv[i]) + if (typeof t[i] == "object") + for (let n in t[i]) + n === "*" ? e(t, i, t[i][n]) : e(t, i + "-" + n.toLowerCase(), t[i][n]); + else typeof t[i] == "function" && e(t, i, t[i]); + } + this.hasListener = Object.keys(this.listeners).length > 0; + } + visitTick(e) { + let t = e[e.length - 1], + { node: i, visitors: n } = t; + if (i.type !== "root" && i.type !== "document" && !i.parent) { + e.pop(); + return; + } + if (n.length > 0 && t.visitorIndex < n.length) { + let [s, o] = n[t.visitorIndex]; + ((t.visitorIndex += 1), + t.visitorIndex === n.length && ((t.visitors = []), (t.visitorIndex = 0)), + (this.result.lastPlugin = s)); + try { + return o(i.toProxy(), this.helpers); + } catch (u) { + throw this.handleError(u, i); + } + } + if (t.iterator !== 0) { + let s = t.iterator, + o; + for (; (o = i.nodes[i.indexes[s]]); ) + if (((i.indexes[s] += 1), !o[qe])) { + ((o[qe] = !0), e.push(mc(o))); + return; + } + ((t.iterator = 0), delete i.indexes[s]); + } + let a = t.events; + for (; t.eventIndex < a.length; ) { + let s = a[t.eventIndex]; + if (((t.eventIndex += 1), s === It)) { + i.nodes && i.nodes.length && ((i[qe] = !0), (t.iterator = i.getIterator())); + return; + } else if (this.listeners[s]) { + t.visitors = this.listeners[s]; + return; + } + } + e.pop(); + } + }; + Ve.registerPostcss = (r) => { + Vs = r; + }; + gc.exports = Ve; + Ve.default = Ve; + pv.registerLazyResult(Ve); + fv.registerLazyResult(Ve); + }); + var wc = v((z3, yc) => { + l(); + ("use strict"); + var gv = Ps(), + yv = yr(), + $3 = qs(), + wv = Qi(), + bv = Bi(), + Ji = class { + constructor(e, t, i) { + ((t = t.toString()), + (this.stringified = !1), + (this._processor = e), + (this._css = t), + (this._opts = i), + (this._map = void 0)); + let n, + a = yv; + ((this.result = new bv(this._processor, n, this._opts)), (this.result.css = t)); + let s = this; + Object.defineProperty(this.result, "root", { + get() { + return s.root; + }, + }); + let o = new gv(a, n, this._opts, t); + if (o.isMap()) { + let [u, c] = o.generate(); + (u && (this.result.css = u), c && (this.result.map = c)); + } + } + get [Symbol.toStringTag]() { + return "NoWorkResult"; + } + get processor() { + return this.result.processor; + } + get opts() { + return this.result.opts; + } + get css() { + return this.result.css; + } + get content() { + return this.result.css; + } + get map() { + return this.result.map; + } + get root() { + if (this._root) return this._root; + let e, + t = wv; + try { + e = t(this._css, this._opts); + } catch (i) { + this.error = i; + } + if (this.error) throw this.error; + return ((this._root = e), e); + } + get messages() { + return []; + } + warnings() { + return []; + } + toString() { + return this._css; + } + then(e, t) { + return this.async().then(e, t); + } + catch(e) { + return this.async().catch(e); + } + finally(e) { + return this.async().then(e, e); + } + async() { + return this.error ? Promise.reject(this.error) : Promise.resolve(this.result); + } + sync() { + if (this.error) throw this.error; + return this.result; + } + }; + yc.exports = Ji; + Ji.default = Ji; + }); + var vc = v((j3, bc) => { + l(); + ("use strict"); + var vv = wc(), + xv = Us(), + kv = qi(), + Sv = Dt(), + qt = class { + constructor(e = []) { + ((this.version = "8.4.24"), (this.plugins = this.normalize(e))); + } + use(e) { + return ((this.plugins = this.plugins.concat(this.normalize([e]))), this); + } + process(e, t = {}) { + return this.plugins.length === 0 && + typeof t.parser == "undefined" && + typeof t.stringifier == "undefined" && + typeof t.syntax == "undefined" + ? new vv(this, e, t) + : new xv(this, e, t); + } + normalize(e) { + let t = []; + for (let i of e) + if ( + (i.postcss === !0 ? (i = i()) : i.postcss && (i = i.postcss), + typeof i == "object" && Array.isArray(i.plugins)) + ) + t = t.concat(i.plugins); + else if (typeof i == "object" && i.postcssPlugin) t.push(i); + else if (typeof i == "function") t.push(i); + else if (!(typeof i == "object" && (i.parse || i.stringify))) + throw new Error(i + " is not a PostCSS plugin"); + return t; + } + }; + bc.exports = qt; + qt.default = qt; + Sv.registerProcessor(qt); + kv.registerProcessor(qt); + }); + var kc = v((V3, xc) => { + l(); + ("use strict"); + var Cv = br(), + Av = Fs(), + _v = vr(), + Ov = Ui(), + Ev = Hi(), + Tv = Dt(), + Pv = Wi(); + function Or(r, e) { + if (Array.isArray(r)) return r.map((n) => Or(n)); + let { inputs: t, ...i } = r; + if (t) { + e = []; + for (let n of t) { + let a = { ...n, __proto__: Ev.prototype }; + (a.map && (a.map = { ...a.map, __proto__: Av.prototype }), e.push(a)); + } + } + if ((i.nodes && (i.nodes = r.nodes.map((n) => Or(n, e))), i.source)) { + let { inputId: n, ...a } = i.source; + ((i.source = a), n != null && (i.source.input = e[n])); + } + if (i.type === "root") return new Tv(i); + if (i.type === "decl") return new Cv(i); + if (i.type === "rule") return new Pv(i); + if (i.type === "comment") return new _v(i); + if (i.type === "atrule") return new Ov(i); + throw new Error("Unknown node type: " + r.type); + } + xc.exports = Or; + Or.default = Or; + }); + var ge = v((U3, Tc) => { + l(); + ("use strict"); + var Dv = _i(), + Sc = br(), + Iv = Us(), + qv = nt(), + Ws = vc(), + Rv = yr(), + Mv = kc(), + Cc = qi(), + Bv = Rs(), + Ac = vr(), + _c = Ui(), + Fv = Bi(), + Lv = Hi(), + Nv = Qi(), + $v = Bs(), + Oc = Wi(), + Ec = Dt(), + zv = wr(); + function z(...r) { + return (r.length === 1 && Array.isArray(r[0]) && (r = r[0]), new Ws(r)); + } + z.plugin = function (e, t) { + let i = !1; + function n(...s) { + console && + console.warn && + !i && + ((i = !0), + console.warn( + e + + `: postcss.plugin was deprecated. Migration guide: +https://evilmartians.com/chronicles/postcss-8-plugin-migration` + ), + h.env.LANG && + h.env.LANG.startsWith("cn") && + console.warn( + e + + `: \u91CC\u9762 postcss.plugin \u88AB\u5F03\u7528. \u8FC1\u79FB\u6307\u5357: +https://www.w3ctech.com/topic/2226` + )); + let o = t(...s); + return ((o.postcssPlugin = e), (o.postcssVersion = new Ws().version), o); + } + let a; + return ( + Object.defineProperty(n, "postcss", { + get() { + return (a || (a = n()), a); + }, + }), + (n.process = function (s, o, u) { + return z([n(u)]).process(s, o); + }), + n + ); + }; + z.stringify = Rv; + z.parse = Nv; + z.fromJSON = Mv; + z.list = $v; + z.comment = (r) => new Ac(r); + z.atRule = (r) => new _c(r); + z.decl = (r) => new Sc(r); + z.rule = (r) => new Oc(r); + z.root = (r) => new Ec(r); + z.document = (r) => new Cc(r); + z.CssSyntaxError = Dv; + z.Declaration = Sc; + z.Container = qv; + z.Processor = Ws; + z.Document = Cc; + z.Comment = Ac; + z.Warning = Bv; + z.AtRule = _c; + z.Result = Fv; + z.Input = Lv; + z.Rule = Oc; + z.Root = Ec; + z.Node = zv; + Iv.registerPostcss(z); + Tc.exports = z; + z.default = z; + }); + var U, + j, + W3, + G3, + H3, + Y3, + Q3, + J3, + X3, + K3, + Z3, + eT, + tT, + rT, + iT, + nT, + sT, + aT, + oT, + lT, + uT, + fT, + cT, + pT, + dT, + hT, + st = C(() => { + l(); + ((U = X(ge())), + (j = U.default), + (W3 = U.default.stringify), + (G3 = U.default.fromJSON), + (H3 = U.default.plugin), + (Y3 = U.default.parse), + (Q3 = U.default.list), + (J3 = U.default.document), + (X3 = U.default.comment), + (K3 = U.default.atRule), + (Z3 = U.default.rule), + (eT = U.default.decl), + (tT = U.default.root), + (rT = U.default.CssSyntaxError), + (iT = U.default.Declaration), + (nT = U.default.Container), + (sT = U.default.Processor), + (aT = U.default.Document), + (oT = U.default.Comment), + (lT = U.default.Warning), + (uT = U.default.AtRule), + (fT = U.default.Result), + (cT = U.default.Input), + (pT = U.default.Rule), + (dT = U.default.Root), + (hT = U.default.Node)); + }); + var Gs = v((gT, Pc) => { + l(); + Pc.exports = function (r, e, t, i, n) { + for (e = e.split ? e.split(".") : e, i = 0; i < e.length; i++) r = r ? r[e[i]] : n; + return r === n ? t : r; + }; + }); + var Ki = v((Xi, Dc) => { + l(); + ("use strict"); + Xi.__esModule = !0; + Xi.default = Uv; + function jv(r) { + for (var e = r.toLowerCase(), t = "", i = !1, n = 0; n < 6 && e[n] !== void 0; n++) { + var a = e.charCodeAt(n), + s = (a >= 97 && a <= 102) || (a >= 48 && a <= 57); + if (((i = a === 32), !s)) break; + t += e[n]; + } + if (t.length !== 0) { + var o = parseInt(t, 16), + u = o >= 55296 && o <= 57343; + return u || o === 0 || o > 1114111 + ? ["\uFFFD", t.length + (i ? 1 : 0)] + : [String.fromCodePoint(o), t.length + (i ? 1 : 0)]; + } + } + var Vv = /\\/; + function Uv(r) { + var e = Vv.test(r); + if (!e) return r; + for (var t = "", i = 0; i < r.length; i++) { + if (r[i] === "\\") { + var n = jv(r.slice(i + 1, i + 7)); + if (n !== void 0) { + ((t += n[0]), (i += n[1])); + continue; + } + if (r[i + 1] === "\\") { + ((t += "\\"), i++); + continue; + } + r.length === i + 1 && (t += r[i]); + continue; + } + t += r[i]; + } + return t; + } + Dc.exports = Xi.default; + }); + var qc = v((Zi, Ic) => { + l(); + ("use strict"); + Zi.__esModule = !0; + Zi.default = Wv; + function Wv(r) { + for (var e = arguments.length, t = new Array(e > 1 ? e - 1 : 0), i = 1; i < e; i++) t[i - 1] = arguments[i]; + for (; t.length > 0; ) { + var n = t.shift(); + if (!r[n]) return; + r = r[n]; + } + return r; + } + Ic.exports = Zi.default; + }); + var Mc = v((en, Rc) => { + l(); + ("use strict"); + en.__esModule = !0; + en.default = Gv; + function Gv(r) { + for (var e = arguments.length, t = new Array(e > 1 ? e - 1 : 0), i = 1; i < e; i++) t[i - 1] = arguments[i]; + for (; t.length > 0; ) { + var n = t.shift(); + (r[n] || (r[n] = {}), (r = r[n])); + } + } + Rc.exports = en.default; + }); + var Fc = v((tn, Bc) => { + l(); + ("use strict"); + tn.__esModule = !0; + tn.default = Hv; + function Hv(r) { + for (var e = "", t = r.indexOf("/*"), i = 0; t >= 0; ) { + e = e + r.slice(i, t); + var n = r.indexOf("*/", t + 2); + if (n < 0) return e; + ((i = n + 2), (t = r.indexOf("/*", i))); + } + return ((e = e + r.slice(i)), e); + } + Bc.exports = tn.default; + }); + var Er = v((Re) => { + l(); + ("use strict"); + Re.__esModule = !0; + Re.unesc = Re.stripComments = Re.getProp = Re.ensureObject = void 0; + var Yv = rn(Ki()); + Re.unesc = Yv.default; + var Qv = rn(qc()); + Re.getProp = Qv.default; + var Jv = rn(Mc()); + Re.ensureObject = Jv.default; + var Xv = rn(Fc()); + Re.stripComments = Xv.default; + function rn(r) { + return r && r.__esModule ? r : { default: r }; + } + }); + var Ue = v((Tr, $c) => { + l(); + ("use strict"); + Tr.__esModule = !0; + Tr.default = void 0; + var Lc = Er(); + function Nc(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function Kv(r, e, t) { + return (e && Nc(r.prototype, e), t && Nc(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + var Zv = function r(e, t) { + if (typeof e != "object" || e === null) return e; + var i = new e.constructor(); + for (var n in e) + if (!!e.hasOwnProperty(n)) { + var a = e[n], + s = typeof a; + n === "parent" && s === "object" + ? t && (i[n] = t) + : a instanceof Array + ? (i[n] = a.map(function (o) { + return r(o, i); + })) + : (i[n] = r(a, i)); + } + return i; + }, + ex = (function () { + function r(t) { + (t === void 0 && (t = {}), + Object.assign(this, t), + (this.spaces = this.spaces || {}), + (this.spaces.before = this.spaces.before || ""), + (this.spaces.after = this.spaces.after || "")); + } + var e = r.prototype; + return ( + (e.remove = function () { + return (this.parent && this.parent.removeChild(this), (this.parent = void 0), this); + }), + (e.replaceWith = function () { + if (this.parent) { + for (var i in arguments) this.parent.insertBefore(this, arguments[i]); + this.remove(); + } + return this; + }), + (e.next = function () { + return this.parent.at(this.parent.index(this) + 1); + }), + (e.prev = function () { + return this.parent.at(this.parent.index(this) - 1); + }), + (e.clone = function (i) { + i === void 0 && (i = {}); + var n = Zv(this); + for (var a in i) n[a] = i[a]; + return n; + }), + (e.appendToPropertyAndEscape = function (i, n, a) { + this.raws || (this.raws = {}); + var s = this[i], + o = this.raws[i]; + ((this[i] = s + n), o || a !== n ? (this.raws[i] = (o || s) + a) : delete this.raws[i]); + }), + (e.setPropertyAndEscape = function (i, n, a) { + (this.raws || (this.raws = {}), (this[i] = n), (this.raws[i] = a)); + }), + (e.setPropertyWithoutEscape = function (i, n) { + ((this[i] = n), this.raws && delete this.raws[i]); + }), + (e.isAtPosition = function (i, n) { + if (this.source && this.source.start && this.source.end) + return !( + this.source.start.line > i || + this.source.end.line < i || + (this.source.start.line === i && this.source.start.column > n) || + (this.source.end.line === i && this.source.end.column < n) + ); + }), + (e.stringifyProperty = function (i) { + return (this.raws && this.raws[i]) || this[i]; + }), + (e.valueToString = function () { + return String(this.stringifyProperty("value")); + }), + (e.toString = function () { + return [this.rawSpaceBefore, this.valueToString(), this.rawSpaceAfter].join(""); + }), + Kv(r, [ + { + key: "rawSpaceBefore", + get: function () { + var i = this.raws && this.raws.spaces && this.raws.spaces.before; + return (i === void 0 && (i = this.spaces && this.spaces.before), i || ""); + }, + set: function (i) { + ((0, Lc.ensureObject)(this, "raws", "spaces"), (this.raws.spaces.before = i)); + }, + }, + { + key: "rawSpaceAfter", + get: function () { + var i = this.raws && this.raws.spaces && this.raws.spaces.after; + return (i === void 0 && (i = this.spaces.after), i || ""); + }, + set: function (i) { + ((0, Lc.ensureObject)(this, "raws", "spaces"), (this.raws.spaces.after = i)); + }, + }, + ]), + r + ); + })(); + Tr.default = ex; + $c.exports = Tr.default; + }); + var ne = v((W) => { + l(); + ("use strict"); + W.__esModule = !0; + W.UNIVERSAL = + W.TAG = + W.STRING = + W.SELECTOR = + W.ROOT = + W.PSEUDO = + W.NESTING = + W.ID = + W.COMMENT = + W.COMBINATOR = + W.CLASS = + W.ATTRIBUTE = + void 0; + var tx = "tag"; + W.TAG = tx; + var rx = "string"; + W.STRING = rx; + var ix = "selector"; + W.SELECTOR = ix; + var nx = "root"; + W.ROOT = nx; + var sx = "pseudo"; + W.PSEUDO = sx; + var ax = "nesting"; + W.NESTING = ax; + var ox = "id"; + W.ID = ox; + var lx = "comment"; + W.COMMENT = lx; + var ux = "combinator"; + W.COMBINATOR = ux; + var fx = "class"; + W.CLASS = fx; + var cx = "attribute"; + W.ATTRIBUTE = cx; + var px = "universal"; + W.UNIVERSAL = px; + }); + var nn = v((Pr, Uc) => { + l(); + ("use strict"); + Pr.__esModule = !0; + Pr.default = void 0; + var dx = mx(Ue()), + We = hx(ne()); + function zc(r) { + if (typeof WeakMap != "function") return null; + var e = new WeakMap(), + t = new WeakMap(); + return (zc = function (n) { + return n ? t : e; + })(r); + } + function hx(r, e) { + if (!e && r && r.__esModule) return r; + if (r === null || (typeof r != "object" && typeof r != "function")) return { default: r }; + var t = zc(e); + if (t && t.has(r)) return t.get(r); + var i = {}, + n = Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var a in r) + if (a !== "default" && Object.prototype.hasOwnProperty.call(r, a)) { + var s = n ? Object.getOwnPropertyDescriptor(r, a) : null; + s && (s.get || s.set) ? Object.defineProperty(i, a, s) : (i[a] = r[a]); + } + return ((i.default = r), t && t.set(r, i), i); + } + function mx(r) { + return r && r.__esModule ? r : { default: r }; + } + function gx(r, e) { + var t = (typeof Symbol != "undefined" && r[Symbol.iterator]) || r["@@iterator"]; + if (t) return (t = t.call(r)).next.bind(t); + if (Array.isArray(r) || (t = yx(r)) || (e && r && typeof r.length == "number")) { + t && (r = t); + var i = 0; + return function () { + return i >= r.length ? { done: !0 } : { done: !1, value: r[i++] }; + }; + } + throw new TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`); + } + function yx(r, e) { + if (!!r) { + if (typeof r == "string") return jc(r, e); + var t = Object.prototype.toString.call(r).slice(8, -1); + if ((t === "Object" && r.constructor && (t = r.constructor.name), t === "Map" || t === "Set")) + return Array.from(r); + if (t === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)) return jc(r, e); + } + } + function jc(r, e) { + (e == null || e > r.length) && (e = r.length); + for (var t = 0, i = new Array(e); t < e; t++) i[t] = r[t]; + return i; + } + function Vc(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function wx(r, e, t) { + return (e && Vc(r.prototype, e), t && Vc(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + function bx(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), Hs(r, e)); + } + function Hs(r, e) { + return ( + (Hs = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + Hs(r, e) + ); + } + var vx = (function (r) { + bx(e, r); + function e(i) { + var n; + return ((n = r.call(this, i) || this), n.nodes || (n.nodes = []), n); + } + var t = e.prototype; + return ( + (t.append = function (n) { + return ((n.parent = this), this.nodes.push(n), this); + }), + (t.prepend = function (n) { + return ((n.parent = this), this.nodes.unshift(n), this); + }), + (t.at = function (n) { + return this.nodes[n]; + }), + (t.index = function (n) { + return typeof n == "number" ? n : this.nodes.indexOf(n); + }), + (t.removeChild = function (n) { + ((n = this.index(n)), (this.at(n).parent = void 0), this.nodes.splice(n, 1)); + var a; + for (var s in this.indexes) ((a = this.indexes[s]), a >= n && (this.indexes[s] = a - 1)); + return this; + }), + (t.removeAll = function () { + for (var n = gx(this.nodes), a; !(a = n()).done; ) { + var s = a.value; + s.parent = void 0; + } + return ((this.nodes = []), this); + }), + (t.empty = function () { + return this.removeAll(); + }), + (t.insertAfter = function (n, a) { + a.parent = this; + var s = this.index(n); + (this.nodes.splice(s + 1, 0, a), (a.parent = this)); + var o; + for (var u in this.indexes) ((o = this.indexes[u]), s <= o && (this.indexes[u] = o + 1)); + return this; + }), + (t.insertBefore = function (n, a) { + a.parent = this; + var s = this.index(n); + (this.nodes.splice(s, 0, a), (a.parent = this)); + var o; + for (var u in this.indexes) ((o = this.indexes[u]), o <= s && (this.indexes[u] = o + 1)); + return this; + }), + (t._findChildAtPosition = function (n, a) { + var s = void 0; + return ( + this.each(function (o) { + if (o.atPosition) { + var u = o.atPosition(n, a); + if (u) return ((s = u), !1); + } else if (o.isAtPosition(n, a)) return ((s = o), !1); + }), + s + ); + }), + (t.atPosition = function (n, a) { + if (this.isAtPosition(n, a)) return this._findChildAtPosition(n, a) || this; + }), + (t._inferEndPosition = function () { + this.last && + this.last.source && + this.last.source.end && + ((this.source = this.source || {}), + (this.source.end = this.source.end || {}), + Object.assign(this.source.end, this.last.source.end)); + }), + (t.each = function (n) { + (this.lastEach || (this.lastEach = 0), this.indexes || (this.indexes = {}), this.lastEach++); + var a = this.lastEach; + if (((this.indexes[a] = 0), !!this.length)) { + for ( + var s, o; + this.indexes[a] < this.length && ((s = this.indexes[a]), (o = n(this.at(s), s)), o !== !1); + ) + this.indexes[a] += 1; + if ((delete this.indexes[a], o === !1)) return !1; + } + }), + (t.walk = function (n) { + return this.each(function (a, s) { + var o = n(a, s); + if ((o !== !1 && a.length && (o = a.walk(n)), o === !1)) return !1; + }); + }), + (t.walkAttributes = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.ATTRIBUTE) return n.call(a, s); + }); + }), + (t.walkClasses = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.CLASS) return n.call(a, s); + }); + }), + (t.walkCombinators = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.COMBINATOR) return n.call(a, s); + }); + }), + (t.walkComments = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.COMMENT) return n.call(a, s); + }); + }), + (t.walkIds = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.ID) return n.call(a, s); + }); + }), + (t.walkNesting = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.NESTING) return n.call(a, s); + }); + }), + (t.walkPseudos = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.PSEUDO) return n.call(a, s); + }); + }), + (t.walkTags = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.TAG) return n.call(a, s); + }); + }), + (t.walkUniversals = function (n) { + var a = this; + return this.walk(function (s) { + if (s.type === We.UNIVERSAL) return n.call(a, s); + }); + }), + (t.split = function (n) { + var a = this, + s = []; + return this.reduce(function (o, u, c) { + var f = n.call(a, u); + return (s.push(u), f ? (o.push(s), (s = [])) : c === a.length - 1 && o.push(s), o); + }, []); + }), + (t.map = function (n) { + return this.nodes.map(n); + }), + (t.reduce = function (n, a) { + return this.nodes.reduce(n, a); + }), + (t.every = function (n) { + return this.nodes.every(n); + }), + (t.some = function (n) { + return this.nodes.some(n); + }), + (t.filter = function (n) { + return this.nodes.filter(n); + }), + (t.sort = function (n) { + return this.nodes.sort(n); + }), + (t.toString = function () { + return this.map(String).join(""); + }), + wx(e, [ + { + key: "first", + get: function () { + return this.at(0); + }, + }, + { + key: "last", + get: function () { + return this.at(this.length - 1); + }, + }, + { + key: "length", + get: function () { + return this.nodes.length; + }, + }, + ]), + e + ); + })(dx.default); + Pr.default = vx; + Uc.exports = Pr.default; + }); + var Qs = v((Dr, Gc) => { + l(); + ("use strict"); + Dr.__esModule = !0; + Dr.default = void 0; + var xx = Sx(nn()), + kx = ne(); + function Sx(r) { + return r && r.__esModule ? r : { default: r }; + } + function Wc(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function Cx(r, e, t) { + return (e && Wc(r.prototype, e), t && Wc(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + function Ax(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), Ys(r, e)); + } + function Ys(r, e) { + return ( + (Ys = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + Ys(r, e) + ); + } + var _x = (function (r) { + Ax(e, r); + function e(i) { + var n; + return ((n = r.call(this, i) || this), (n.type = kx.ROOT), n); + } + var t = e.prototype; + return ( + (t.toString = function () { + var n = this.reduce(function (a, s) { + return (a.push(String(s)), a); + }, []).join(","); + return this.trailingComma ? n + "," : n; + }), + (t.error = function (n, a) { + return this._error ? this._error(n, a) : new Error(n); + }), + Cx(e, [ + { + key: "errorGenerator", + set: function (n) { + this._error = n; + }, + }, + ]), + e + ); + })(xx.default); + Dr.default = _x; + Gc.exports = Dr.default; + }); + var Xs = v((Ir, Hc) => { + l(); + ("use strict"); + Ir.__esModule = !0; + Ir.default = void 0; + var Ox = Tx(nn()), + Ex = ne(); + function Tx(r) { + return r && r.__esModule ? r : { default: r }; + } + function Px(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), Js(r, e)); + } + function Js(r, e) { + return ( + (Js = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + Js(r, e) + ); + } + var Dx = (function (r) { + Px(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = Ex.SELECTOR), i); + } + return e; + })(Ox.default); + Ir.default = Dx; + Hc.exports = Ir.default; + }); + var sn = v((bT, Yc) => { + l(); + ("use strict"); + var Ix = {}, + qx = Ix.hasOwnProperty, + Rx = function (e, t) { + if (!e) return t; + var i = {}; + for (var n in t) i[n] = qx.call(e, n) ? e[n] : t[n]; + return i; + }, + Mx = /[ -,\.\/:-@\[-\^`\{-~]/, + Bx = /[ -,\.\/:-@\[\]\^`\{-~]/, + Fx = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g, + Ks = function r(e, t) { + ((t = Rx(t, r.options)), t.quotes != "single" && t.quotes != "double" && (t.quotes = "single")); + for ( + var i = t.quotes == "double" ? '"' : "'", + n = t.isIdentifier, + a = e.charAt(0), + s = "", + o = 0, + u = e.length; + o < u; + ) { + var c = e.charAt(o++), + f = c.charCodeAt(), + d = void 0; + if (f < 32 || f > 126) { + if (f >= 55296 && f <= 56319 && o < u) { + var p = e.charCodeAt(o++); + (p & 64512) == 56320 ? (f = ((f & 1023) << 10) + (p & 1023) + 65536) : o--; + } + d = "\\" + f.toString(16).toUpperCase() + " "; + } else + t.escapeEverything + ? Mx.test(c) + ? (d = "\\" + c) + : (d = "\\" + f.toString(16).toUpperCase() + " ") + : /[\t\n\f\r\x0B]/.test(c) + ? (d = "\\" + f.toString(16).toUpperCase() + " ") + : c == "\\" || (!n && ((c == '"' && i == c) || (c == "'" && i == c))) || (n && Bx.test(c)) + ? (d = "\\" + c) + : (d = c); + s += d; + } + return ( + n && + (/^-[-\d]/.test(s) + ? (s = "\\-" + s.slice(1)) + : /\d/.test(a) && (s = "\\3" + a + " " + s.slice(1))), + (s = s.replace(Fx, function (m, b, x) { + return b && b.length % 2 ? m : (b || "") + x; + })), + !n && t.wrap ? i + s + i : s + ); + }; + Ks.options = { escapeEverything: !1, isIdentifier: !1, quotes: "single", wrap: !1 }; + Ks.version = "3.0.0"; + Yc.exports = Ks; + }); + var ea = v((qr, Xc) => { + l(); + ("use strict"); + qr.__esModule = !0; + qr.default = void 0; + var Lx = Qc(sn()), + Nx = Er(), + $x = Qc(Ue()), + zx = ne(); + function Qc(r) { + return r && r.__esModule ? r : { default: r }; + } + function Jc(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function jx(r, e, t) { + return (e && Jc(r.prototype, e), t && Jc(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + function Vx(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), Zs(r, e)); + } + function Zs(r, e) { + return ( + (Zs = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + Zs(r, e) + ); + } + var Ux = (function (r) { + Vx(e, r); + function e(i) { + var n; + return ((n = r.call(this, i) || this), (n.type = zx.CLASS), (n._constructed = !0), n); + } + var t = e.prototype; + return ( + (t.valueToString = function () { + return "." + r.prototype.valueToString.call(this); + }), + jx(e, [ + { + key: "value", + get: function () { + return this._value; + }, + set: function (n) { + if (this._constructed) { + var a = (0, Lx.default)(n, { isIdentifier: !0 }); + a !== n + ? ((0, Nx.ensureObject)(this, "raws"), (this.raws.value = a)) + : this.raws && delete this.raws.value; + } + this._value = n; + }, + }, + ]), + e + ); + })($x.default); + qr.default = Ux; + Xc.exports = qr.default; + }); + var ra = v((Rr, Kc) => { + l(); + ("use strict"); + Rr.__esModule = !0; + Rr.default = void 0; + var Wx = Hx(Ue()), + Gx = ne(); + function Hx(r) { + return r && r.__esModule ? r : { default: r }; + } + function Yx(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), ta(r, e)); + } + function ta(r, e) { + return ( + (ta = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + ta(r, e) + ); + } + var Qx = (function (r) { + Yx(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = Gx.COMMENT), i); + } + return e; + })(Wx.default); + Rr.default = Qx; + Kc.exports = Rr.default; + }); + var na = v((Mr, Zc) => { + l(); + ("use strict"); + Mr.__esModule = !0; + Mr.default = void 0; + var Jx = Kx(Ue()), + Xx = ne(); + function Kx(r) { + return r && r.__esModule ? r : { default: r }; + } + function Zx(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), ia(r, e)); + } + function ia(r, e) { + return ( + (ia = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + ia(r, e) + ); + } + var e1 = (function (r) { + Zx(e, r); + function e(i) { + var n; + return ((n = r.call(this, i) || this), (n.type = Xx.ID), n); + } + var t = e.prototype; + return ( + (t.valueToString = function () { + return "#" + r.prototype.valueToString.call(this); + }), + e + ); + })(Jx.default); + Mr.default = e1; + Zc.exports = Mr.default; + }); + var an = v((Br, rp) => { + l(); + ("use strict"); + Br.__esModule = !0; + Br.default = void 0; + var t1 = ep(sn()), + r1 = Er(), + i1 = ep(Ue()); + function ep(r) { + return r && r.__esModule ? r : { default: r }; + } + function tp(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function n1(r, e, t) { + return (e && tp(r.prototype, e), t && tp(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + function s1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), sa(r, e)); + } + function sa(r, e) { + return ( + (sa = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + sa(r, e) + ); + } + var a1 = (function (r) { + s1(e, r); + function e() { + return r.apply(this, arguments) || this; + } + var t = e.prototype; + return ( + (t.qualifiedName = function (n) { + return this.namespace ? this.namespaceString + "|" + n : n; + }), + (t.valueToString = function () { + return this.qualifiedName(r.prototype.valueToString.call(this)); + }), + n1(e, [ + { + key: "namespace", + get: function () { + return this._namespace; + }, + set: function (n) { + if (n === !0 || n === "*" || n === "&") { + ((this._namespace = n), this.raws && delete this.raws.namespace); + return; + } + var a = (0, t1.default)(n, { isIdentifier: !0 }); + ((this._namespace = n), + a !== n + ? ((0, r1.ensureObject)(this, "raws"), (this.raws.namespace = a)) + : this.raws && delete this.raws.namespace); + }, + }, + { + key: "ns", + get: function () { + return this._namespace; + }, + set: function (n) { + this.namespace = n; + }, + }, + { + key: "namespaceString", + get: function () { + if (this.namespace) { + var n = this.stringifyProperty("namespace"); + return n === !0 ? "" : n; + } else return ""; + }, + }, + ]), + e + ); + })(i1.default); + Br.default = a1; + rp.exports = Br.default; + }); + var oa = v((Fr, ip) => { + l(); + ("use strict"); + Fr.__esModule = !0; + Fr.default = void 0; + var o1 = u1(an()), + l1 = ne(); + function u1(r) { + return r && r.__esModule ? r : { default: r }; + } + function f1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), aa(r, e)); + } + function aa(r, e) { + return ( + (aa = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + aa(r, e) + ); + } + var c1 = (function (r) { + f1(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = l1.TAG), i); + } + return e; + })(o1.default); + Fr.default = c1; + ip.exports = Fr.default; + }); + var ua = v((Lr, np) => { + l(); + ("use strict"); + Lr.__esModule = !0; + Lr.default = void 0; + var p1 = h1(Ue()), + d1 = ne(); + function h1(r) { + return r && r.__esModule ? r : { default: r }; + } + function m1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), la(r, e)); + } + function la(r, e) { + return ( + (la = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + la(r, e) + ); + } + var g1 = (function (r) { + m1(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = d1.STRING), i); + } + return e; + })(p1.default); + Lr.default = g1; + np.exports = Lr.default; + }); + var ca = v((Nr, sp) => { + l(); + ("use strict"); + Nr.__esModule = !0; + Nr.default = void 0; + var y1 = b1(nn()), + w1 = ne(); + function b1(r) { + return r && r.__esModule ? r : { default: r }; + } + function v1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), fa(r, e)); + } + function fa(r, e) { + return ( + (fa = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + fa(r, e) + ); + } + var x1 = (function (r) { + v1(e, r); + function e(i) { + var n; + return ((n = r.call(this, i) || this), (n.type = w1.PSEUDO), n); + } + var t = e.prototype; + return ( + (t.toString = function () { + var n = this.length ? "(" + this.map(String).join(",") + ")" : ""; + return [this.rawSpaceBefore, this.stringifyProperty("value"), n, this.rawSpaceAfter].join(""); + }), + e + ); + })(y1.default); + Nr.default = x1; + sp.exports = Nr.default; + }); + var ap = {}; + Ae(ap, { deprecate: () => k1 }); + function k1(r) { + return r; + } + var op = C(() => { + l(); + }); + var up = v((vT, lp) => { + l(); + lp.exports = (op(), ap).deprecate; + }); + var ya = v((jr) => { + l(); + ("use strict"); + jr.__esModule = !0; + jr.default = void 0; + jr.unescapeValue = ma; + var $r = da(sn()), + S1 = da(Ki()), + C1 = da(an()), + A1 = ne(), + pa; + function da(r) { + return r && r.__esModule ? r : { default: r }; + } + function fp(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function _1(r, e, t) { + return (e && fp(r.prototype, e), t && fp(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + function O1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), ha(r, e)); + } + function ha(r, e) { + return ( + (ha = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + ha(r, e) + ); + } + var zr = up(), + E1 = /^('|")([^]*)\1$/, + T1 = zr( + function () {}, + "Assigning an attribute a value containing characters that might need to be escaped is deprecated. Call attribute.setValue() instead." + ), + P1 = zr( + function () {}, + "Assigning attr.quoted is deprecated and has no effect. Assign to attr.quoteMark instead." + ), + D1 = zr( + function () {}, + "Constructing an Attribute selector with a value without specifying quoteMark is deprecated. Note: The value should be unescaped now." + ); + function ma(r) { + var e = !1, + t = null, + i = r, + n = i.match(E1); + return ( + n && ((t = n[1]), (i = n[2])), + (i = (0, S1.default)(i)), + i !== r && (e = !0), + { deprecatedUsage: e, unescaped: i, quoteMark: t } + ); + } + function I1(r) { + if (r.quoteMark !== void 0 || r.value === void 0) return r; + D1(); + var e = ma(r.value), + t = e.quoteMark, + i = e.unescaped; + return ( + r.raws || (r.raws = {}), + r.raws.value === void 0 && (r.raws.value = r.value), + (r.value = i), + (r.quoteMark = t), + r + ); + } + var on = (function (r) { + O1(e, r); + function e(i) { + var n; + return ( + i === void 0 && (i = {}), + (n = r.call(this, I1(i)) || this), + (n.type = A1.ATTRIBUTE), + (n.raws = n.raws || {}), + Object.defineProperty(n.raws, "unquoted", { + get: zr(function () { + return n.value; + }, "attr.raws.unquoted is deprecated. Call attr.value instead."), + set: zr(function () { + return n.value; + }, "Setting attr.raws.unquoted is deprecated and has no effect. attr.value is unescaped by default now."), + }), + (n._constructed = !0), + n + ); + } + var t = e.prototype; + return ( + (t.getQuotedValue = function (n) { + n === void 0 && (n = {}); + var a = this._determineQuoteMark(n), + s = ga[a], + o = (0, $r.default)(this._value, s); + return o; + }), + (t._determineQuoteMark = function (n) { + return n.smart ? this.smartQuoteMark(n) : this.preferredQuoteMark(n); + }), + (t.setValue = function (n, a) { + (a === void 0 && (a = {}), + (this._value = n), + (this._quoteMark = this._determineQuoteMark(a)), + this._syncRawValue()); + }), + (t.smartQuoteMark = function (n) { + var a = this.value, + s = a.replace(/[^']/g, "").length, + o = a.replace(/[^"]/g, "").length; + if (s + o === 0) { + var u = (0, $r.default)(a, { isIdentifier: !0 }); + if (u === a) return e.NO_QUOTE; + var c = this.preferredQuoteMark(n); + if (c === e.NO_QUOTE) { + var f = this.quoteMark || n.quoteMark || e.DOUBLE_QUOTE, + d = ga[f], + p = (0, $r.default)(a, d); + if (p.length < u.length) return f; + } + return c; + } else return o === s ? this.preferredQuoteMark(n) : o < s ? e.DOUBLE_QUOTE : e.SINGLE_QUOTE; + }), + (t.preferredQuoteMark = function (n) { + var a = n.preferCurrentQuoteMark ? this.quoteMark : n.quoteMark; + return ( + a === void 0 && (a = n.preferCurrentQuoteMark ? n.quoteMark : this.quoteMark), + a === void 0 && (a = e.DOUBLE_QUOTE), + a + ); + }), + (t._syncRawValue = function () { + var n = (0, $r.default)(this._value, ga[this.quoteMark]); + n === this._value ? this.raws && delete this.raws.value : (this.raws.value = n); + }), + (t._handleEscapes = function (n, a) { + if (this._constructed) { + var s = (0, $r.default)(a, { isIdentifier: !0 }); + s !== a ? (this.raws[n] = s) : delete this.raws[n]; + } + }), + (t._spacesFor = function (n) { + var a = { before: "", after: "" }, + s = this.spaces[n] || {}, + o = (this.raws.spaces && this.raws.spaces[n]) || {}; + return Object.assign(a, s, o); + }), + (t._stringFor = function (n, a, s) { + (a === void 0 && (a = n), s === void 0 && (s = cp)); + var o = this._spacesFor(a); + return s(this.stringifyProperty(n), o); + }), + (t.offsetOf = function (n) { + var a = 1, + s = this._spacesFor("attribute"); + if (((a += s.before.length), n === "namespace" || n === "ns")) return this.namespace ? a : -1; + if ( + n === "attributeNS" || + ((a += this.namespaceString.length), this.namespace && (a += 1), n === "attribute") + ) + return a; + ((a += this.stringifyProperty("attribute").length), (a += s.after.length)); + var o = this._spacesFor("operator"); + a += o.before.length; + var u = this.stringifyProperty("operator"); + if (n === "operator") return u ? a : -1; + ((a += u.length), (a += o.after.length)); + var c = this._spacesFor("value"); + a += c.before.length; + var f = this.stringifyProperty("value"); + if (n === "value") return f ? a : -1; + ((a += f.length), (a += c.after.length)); + var d = this._spacesFor("insensitive"); + return ((a += d.before.length), n === "insensitive" && this.insensitive ? a : -1); + }), + (t.toString = function () { + var n = this, + a = [this.rawSpaceBefore, "["]; + return ( + a.push(this._stringFor("qualifiedAttribute", "attribute")), + this.operator && + (this.value || this.value === "") && + (a.push(this._stringFor("operator")), + a.push(this._stringFor("value")), + a.push( + this._stringFor("insensitiveFlag", "insensitive", function (s, o) { + return ( + s.length > 0 && + !n.quoted && + o.before.length === 0 && + !(n.spaces.value && n.spaces.value.after) && + (o.before = " "), + cp(s, o) + ); + }) + )), + a.push("]"), + a.push(this.rawSpaceAfter), + a.join("") + ); + }), + _1(e, [ + { + key: "quoted", + get: function () { + var n = this.quoteMark; + return n === "'" || n === '"'; + }, + set: function (n) { + P1(); + }, + }, + { + key: "quoteMark", + get: function () { + return this._quoteMark; + }, + set: function (n) { + if (!this._constructed) { + this._quoteMark = n; + return; + } + this._quoteMark !== n && ((this._quoteMark = n), this._syncRawValue()); + }, + }, + { + key: "qualifiedAttribute", + get: function () { + return this.qualifiedName(this.raws.attribute || this.attribute); + }, + }, + { + key: "insensitiveFlag", + get: function () { + return this.insensitive ? "i" : ""; + }, + }, + { + key: "value", + get: function () { + return this._value; + }, + set: function (n) { + if (this._constructed) { + var a = ma(n), + s = a.deprecatedUsage, + o = a.unescaped, + u = a.quoteMark; + if ((s && T1(), o === this._value && u === this._quoteMark)) return; + ((this._value = o), (this._quoteMark = u), this._syncRawValue()); + } else this._value = n; + }, + }, + { + key: "insensitive", + get: function () { + return this._insensitive; + }, + set: function (n) { + (n || + ((this._insensitive = !1), + this.raws && + (this.raws.insensitiveFlag === "I" || this.raws.insensitiveFlag === "i") && + (this.raws.insensitiveFlag = void 0)), + (this._insensitive = n)); + }, + }, + { + key: "attribute", + get: function () { + return this._attribute; + }, + set: function (n) { + (this._handleEscapes("attribute", n), (this._attribute = n)); + }, + }, + ]), + e + ); + })(C1.default); + jr.default = on; + on.NO_QUOTE = null; + on.SINGLE_QUOTE = "'"; + on.DOUBLE_QUOTE = '"'; + var ga = + ((pa = { "'": { quotes: "single", wrap: !0 }, '"': { quotes: "double", wrap: !0 } }), + (pa[null] = { isIdentifier: !0 }), + pa); + function cp(r, e) { + return "" + e.before + r + e.after; + } + }); + var ba = v((Vr, pp) => { + l(); + ("use strict"); + Vr.__esModule = !0; + Vr.default = void 0; + var q1 = M1(an()), + R1 = ne(); + function M1(r) { + return r && r.__esModule ? r : { default: r }; + } + function B1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), wa(r, e)); + } + function wa(r, e) { + return ( + (wa = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + wa(r, e) + ); + } + var F1 = (function (r) { + B1(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = R1.UNIVERSAL), (i.value = "*"), i); + } + return e; + })(q1.default); + Vr.default = F1; + pp.exports = Vr.default; + }); + var xa = v((Ur, dp) => { + l(); + ("use strict"); + Ur.__esModule = !0; + Ur.default = void 0; + var L1 = $1(Ue()), + N1 = ne(); + function $1(r) { + return r && r.__esModule ? r : { default: r }; + } + function z1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), va(r, e)); + } + function va(r, e) { + return ( + (va = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + va(r, e) + ); + } + var j1 = (function (r) { + z1(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = N1.COMBINATOR), i); + } + return e; + })(L1.default); + Ur.default = j1; + dp.exports = Ur.default; + }); + var Sa = v((Wr, hp) => { + l(); + ("use strict"); + Wr.__esModule = !0; + Wr.default = void 0; + var V1 = W1(Ue()), + U1 = ne(); + function W1(r) { + return r && r.__esModule ? r : { default: r }; + } + function G1(r, e) { + ((r.prototype = Object.create(e.prototype)), (r.prototype.constructor = r), ka(r, e)); + } + function ka(r, e) { + return ( + (ka = Object.setPrototypeOf + ? Object.setPrototypeOf.bind() + : function (i, n) { + return ((i.__proto__ = n), i); + }), + ka(r, e) + ); + } + var H1 = (function (r) { + G1(e, r); + function e(t) { + var i; + return ((i = r.call(this, t) || this), (i.type = U1.NESTING), (i.value = "&"), i); + } + return e; + })(V1.default); + Wr.default = H1; + hp.exports = Wr.default; + }); + var gp = v((ln, mp) => { + l(); + ("use strict"); + ln.__esModule = !0; + ln.default = Y1; + function Y1(r) { + return r.sort(function (e, t) { + return e - t; + }); + } + mp.exports = ln.default; + }); + var Ca = v((D) => { + l(); + ("use strict"); + D.__esModule = !0; + D.word = + D.tilde = + D.tab = + D.str = + D.space = + D.slash = + D.singleQuote = + D.semicolon = + D.plus = + D.pipe = + D.openSquare = + D.openParenthesis = + D.newline = + D.greaterThan = + D.feed = + D.equals = + D.doubleQuote = + D.dollar = + D.cr = + D.comment = + D.comma = + D.combinator = + D.colon = + D.closeSquare = + D.closeParenthesis = + D.caret = + D.bang = + D.backslash = + D.at = + D.asterisk = + D.ampersand = + void 0; + var Q1 = 38; + D.ampersand = Q1; + var J1 = 42; + D.asterisk = J1; + var X1 = 64; + D.at = X1; + var K1 = 44; + D.comma = K1; + var Z1 = 58; + D.colon = Z1; + var ek = 59; + D.semicolon = ek; + var tk = 40; + D.openParenthesis = tk; + var rk = 41; + D.closeParenthesis = rk; + var ik = 91; + D.openSquare = ik; + var nk = 93; + D.closeSquare = nk; + var sk = 36; + D.dollar = sk; + var ak = 126; + D.tilde = ak; + var ok = 94; + D.caret = ok; + var lk = 43; + D.plus = lk; + var uk = 61; + D.equals = uk; + var fk = 124; + D.pipe = fk; + var ck = 62; + D.greaterThan = ck; + var pk = 32; + D.space = pk; + var yp = 39; + D.singleQuote = yp; + var dk = 34; + D.doubleQuote = dk; + var hk = 47; + D.slash = hk; + var mk = 33; + D.bang = mk; + var gk = 92; + D.backslash = gk; + var yk = 13; + D.cr = yk; + var wk = 12; + D.feed = wk; + var bk = 10; + D.newline = bk; + var vk = 9; + D.tab = vk; + var xk = yp; + D.str = xk; + var kk = -1; + D.comment = kk; + var Sk = -2; + D.word = Sk; + var Ck = -3; + D.combinator = Ck; + }); + var vp = v((Gr) => { + l(); + ("use strict"); + Gr.__esModule = !0; + Gr.FIELDS = void 0; + Gr.default = Dk; + var O = Ak(Ca()), + Rt, + V; + function wp(r) { + if (typeof WeakMap != "function") return null; + var e = new WeakMap(), + t = new WeakMap(); + return (wp = function (n) { + return n ? t : e; + })(r); + } + function Ak(r, e) { + if (!e && r && r.__esModule) return r; + if (r === null || (typeof r != "object" && typeof r != "function")) return { default: r }; + var t = wp(e); + if (t && t.has(r)) return t.get(r); + var i = {}, + n = Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var a in r) + if (a !== "default" && Object.prototype.hasOwnProperty.call(r, a)) { + var s = n ? Object.getOwnPropertyDescriptor(r, a) : null; + s && (s.get || s.set) ? Object.defineProperty(i, a, s) : (i[a] = r[a]); + } + return ((i.default = r), t && t.set(r, i), i); + } + var _k = ((Rt = {}), (Rt[O.tab] = !0), (Rt[O.newline] = !0), (Rt[O.cr] = !0), (Rt[O.feed] = !0), Rt), + Ok = + ((V = {}), + (V[O.space] = !0), + (V[O.tab] = !0), + (V[O.newline] = !0), + (V[O.cr] = !0), + (V[O.feed] = !0), + (V[O.ampersand] = !0), + (V[O.asterisk] = !0), + (V[O.bang] = !0), + (V[O.comma] = !0), + (V[O.colon] = !0), + (V[O.semicolon] = !0), + (V[O.openParenthesis] = !0), + (V[O.closeParenthesis] = !0), + (V[O.openSquare] = !0), + (V[O.closeSquare] = !0), + (V[O.singleQuote] = !0), + (V[O.doubleQuote] = !0), + (V[O.plus] = !0), + (V[O.pipe] = !0), + (V[O.tilde] = !0), + (V[O.greaterThan] = !0), + (V[O.equals] = !0), + (V[O.dollar] = !0), + (V[O.caret] = !0), + (V[O.slash] = !0), + V), + Aa = {}, + bp = "0123456789abcdefABCDEF"; + for (un = 0; un < bp.length; un++) Aa[bp.charCodeAt(un)] = !0; + var un; + function Ek(r, e) { + var t = e, + i; + do { + if (((i = r.charCodeAt(t)), Ok[i])) return t - 1; + i === O.backslash ? (t = Tk(r, t) + 1) : t++; + } while (t < r.length); + return t - 1; + } + function Tk(r, e) { + var t = e, + i = r.charCodeAt(t + 1); + if (!_k[i]) + if (Aa[i]) { + var n = 0; + do (t++, n++, (i = r.charCodeAt(t + 1))); + while (Aa[i] && n < 6); + n < 6 && i === O.space && t++; + } else t++; + return t; + } + var Pk = { TYPE: 0, START_LINE: 1, START_COL: 2, END_LINE: 3, END_COL: 4, START_POS: 5, END_POS: 6 }; + Gr.FIELDS = Pk; + function Dk(r) { + var e = [], + t = r.css.valueOf(), + i = t, + n = i.length, + a = -1, + s = 1, + o = 0, + u = 0, + c, + f, + d, + p, + m, + b, + x, + y, + w, + k, + S, + _, + E; + function I(q, R) { + if (r.safe) ((t += R), (w = t.length - 1)); + else throw r.error("Unclosed " + q, s, o - a, o); + } + for (; o < n; ) { + switch (((c = t.charCodeAt(o)), c === O.newline && ((a = o), (s += 1)), c)) { + case O.space: + case O.tab: + case O.newline: + case O.cr: + case O.feed: + w = o; + do ((w += 1), (c = t.charCodeAt(w)), c === O.newline && ((a = w), (s += 1))); + while (c === O.space || c === O.newline || c === O.tab || c === O.cr || c === O.feed); + ((E = O.space), (p = s), (d = w - a - 1), (u = w)); + break; + case O.plus: + case O.greaterThan: + case O.tilde: + case O.pipe: + w = o; + do ((w += 1), (c = t.charCodeAt(w))); + while (c === O.plus || c === O.greaterThan || c === O.tilde || c === O.pipe); + ((E = O.combinator), (p = s), (d = o - a), (u = w)); + break; + case O.asterisk: + case O.ampersand: + case O.bang: + case O.comma: + case O.equals: + case O.dollar: + case O.caret: + case O.openSquare: + case O.closeSquare: + case O.colon: + case O.semicolon: + case O.openParenthesis: + case O.closeParenthesis: + ((w = o), (E = c), (p = s), (d = o - a), (u = w + 1)); + break; + case O.singleQuote: + case O.doubleQuote: + ((_ = c === O.singleQuote ? "'" : '"'), (w = o)); + do + for ( + m = !1, w = t.indexOf(_, w + 1), w === -1 && I("quote", _), b = w; + t.charCodeAt(b - 1) === O.backslash; + ) + ((b -= 1), (m = !m)); + while (m); + ((E = O.str), (p = s), (d = o - a), (u = w + 1)); + break; + default: + (c === O.slash && t.charCodeAt(o + 1) === O.asterisk + ? ((w = t.indexOf("*/", o + 2) + 1), + w === 0 && I("comment", "*/"), + (f = t.slice(o, w + 1)), + (y = f.split(` +`)), + (x = y.length - 1), + x > 0 ? ((k = s + x), (S = w - y[x].length)) : ((k = s), (S = a)), + (E = O.comment), + (s = k), + (p = k), + (d = w - S)) + : c === O.slash + ? ((w = o), (E = c), (p = s), (d = o - a), (u = w + 1)) + : ((w = Ek(t, o)), (E = O.word), (p = s), (d = w - a)), + (u = w + 1)); + break; + } + (e.push([E, s, o - a, p, d, o, u]), S && ((a = S), (S = null)), (o = u)); + } + return e; + } + }); + var Ep = v((Hr, Op) => { + l(); + ("use strict"); + Hr.__esModule = !0; + Hr.default = void 0; + var Ik = be(Qs()), + _a = be(Xs()), + qk = be(ea()), + xp = be(ra()), + Rk = be(na()), + Mk = be(oa()), + Oa = be(ua()), + Bk = be(ca()), + kp = fn(ya()), + Fk = be(ba()), + Ea = be(xa()), + Lk = be(Sa()), + Nk = be(gp()), + A = fn(vp()), + T = fn(Ca()), + $k = fn(ne()), + Y = Er(), + xt, + Ta; + function Sp(r) { + if (typeof WeakMap != "function") return null; + var e = new WeakMap(), + t = new WeakMap(); + return (Sp = function (n) { + return n ? t : e; + })(r); + } + function fn(r, e) { + if (!e && r && r.__esModule) return r; + if (r === null || (typeof r != "object" && typeof r != "function")) return { default: r }; + var t = Sp(e); + if (t && t.has(r)) return t.get(r); + var i = {}, + n = Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var a in r) + if (a !== "default" && Object.prototype.hasOwnProperty.call(r, a)) { + var s = n ? Object.getOwnPropertyDescriptor(r, a) : null; + s && (s.get || s.set) ? Object.defineProperty(i, a, s) : (i[a] = r[a]); + } + return ((i.default = r), t && t.set(r, i), i); + } + function be(r) { + return r && r.__esModule ? r : { default: r }; + } + function Cp(r, e) { + for (var t = 0; t < e.length; t++) { + var i = e[t]; + ((i.enumerable = i.enumerable || !1), + (i.configurable = !0), + "value" in i && (i.writable = !0), + Object.defineProperty(r, i.key, i)); + } + } + function zk(r, e, t) { + return (e && Cp(r.prototype, e), t && Cp(r, t), Object.defineProperty(r, "prototype", { writable: !1 }), r); + } + var Pa = + ((xt = {}), + (xt[T.space] = !0), + (xt[T.cr] = !0), + (xt[T.feed] = !0), + (xt[T.newline] = !0), + (xt[T.tab] = !0), + xt), + jk = Object.assign({}, Pa, ((Ta = {}), (Ta[T.comment] = !0), Ta)); + function Ap(r) { + return { line: r[A.FIELDS.START_LINE], column: r[A.FIELDS.START_COL] }; + } + function _p(r) { + return { line: r[A.FIELDS.END_LINE], column: r[A.FIELDS.END_COL] }; + } + function kt(r, e, t, i) { + return { start: { line: r, column: e }, end: { line: t, column: i } }; + } + function Mt(r) { + return kt(r[A.FIELDS.START_LINE], r[A.FIELDS.START_COL], r[A.FIELDS.END_LINE], r[A.FIELDS.END_COL]); + } + function Da(r, e) { + if (!!r) + return kt(r[A.FIELDS.START_LINE], r[A.FIELDS.START_COL], e[A.FIELDS.END_LINE], e[A.FIELDS.END_COL]); + } + function Bt(r, e) { + var t = r[e]; + if (typeof t == "string") + return ( + t.indexOf("\\") !== -1 && + ((0, Y.ensureObject)(r, "raws"), + (r[e] = (0, Y.unesc)(t)), + r.raws[e] === void 0 && (r.raws[e] = t)), + r + ); + } + function Ia(r, e) { + for (var t = -1, i = []; (t = r.indexOf(e, t + 1)) !== -1; ) i.push(t); + return i; + } + function Vk() { + var r = Array.prototype.concat.apply([], arguments); + return r.filter(function (e, t) { + return t === r.indexOf(e); + }); + } + var Uk = (function () { + function r(t, i) { + (i === void 0 && (i = {}), + (this.rule = t), + (this.options = Object.assign({ lossy: !1, safe: !1 }, i)), + (this.position = 0), + (this.css = typeof this.rule == "string" ? this.rule : this.rule.selector), + (this.tokens = (0, A.default)({ + css: this.css, + error: this._errorGenerator(), + safe: this.options.safe, + }))); + var n = Da(this.tokens[0], this.tokens[this.tokens.length - 1]); + ((this.root = new Ik.default({ source: n })), (this.root.errorGenerator = this._errorGenerator())); + var a = new _a.default({ source: { start: { line: 1, column: 1 } } }); + (this.root.append(a), (this.current = a), this.loop()); + } + var e = r.prototype; + return ( + (e._errorGenerator = function () { + var i = this; + return function (n, a) { + return typeof i.rule == "string" ? new Error(n) : i.rule.error(n, a); + }; + }), + (e.attribute = function () { + var i = [], + n = this.currToken; + for ( + this.position++; + this.position < this.tokens.length && this.currToken[A.FIELDS.TYPE] !== T.closeSquare; + ) + (i.push(this.currToken), this.position++); + if (this.currToken[A.FIELDS.TYPE] !== T.closeSquare) + return this.expected("closing square bracket", this.currToken[A.FIELDS.START_POS]); + var a = i.length, + s = { + source: kt(n[1], n[2], this.currToken[3], this.currToken[4]), + sourceIndex: n[A.FIELDS.START_POS], + }; + if (a === 1 && !~[T.word].indexOf(i[0][A.FIELDS.TYPE])) + return this.expected("attribute", i[0][A.FIELDS.START_POS]); + for (var o = 0, u = "", c = "", f = null, d = !1; o < a; ) { + var p = i[o], + m = this.content(p), + b = i[o + 1]; + switch (p[A.FIELDS.TYPE]) { + case T.space: + if (((d = !0), this.options.lossy)) break; + if (f) { + (0, Y.ensureObject)(s, "spaces", f); + var x = s.spaces[f].after || ""; + s.spaces[f].after = x + m; + var y = (0, Y.getProp)(s, "raws", "spaces", f, "after") || null; + y && (s.raws.spaces[f].after = y + m); + } else ((u = u + m), (c = c + m)); + break; + case T.asterisk: + if (b[A.FIELDS.TYPE] === T.equals) ((s.operator = m), (f = "operator")); + else if ((!s.namespace || (f === "namespace" && !d)) && b) { + (u && + ((0, Y.ensureObject)(s, "spaces", "attribute"), + (s.spaces.attribute.before = u), + (u = "")), + c && + ((0, Y.ensureObject)(s, "raws", "spaces", "attribute"), + (s.raws.spaces.attribute.before = u), + (c = "")), + (s.namespace = (s.namespace || "") + m)); + var w = (0, Y.getProp)(s, "raws", "namespace") || null; + (w && (s.raws.namespace += m), (f = "namespace")); + } + d = !1; + break; + case T.dollar: + if (f === "value") { + var k = (0, Y.getProp)(s, "raws", "value"); + ((s.value += "$"), k && (s.raws.value = k + "$")); + break; + } + case T.caret: + (b[A.FIELDS.TYPE] === T.equals && ((s.operator = m), (f = "operator")), (d = !1)); + break; + case T.combinator: + if ( + (m === "~" && b[A.FIELDS.TYPE] === T.equals && ((s.operator = m), (f = "operator")), + m !== "|") + ) { + d = !1; + break; + } + (b[A.FIELDS.TYPE] === T.equals + ? ((s.operator = m), (f = "operator")) + : !s.namespace && !s.attribute && (s.namespace = !0), + (d = !1)); + break; + case T.word: + if ( + b && + this.content(b) === "|" && + i[o + 2] && + i[o + 2][A.FIELDS.TYPE] !== T.equals && + !s.operator && + !s.namespace + ) + ((s.namespace = m), (f = "namespace")); + else if (!s.attribute || (f === "attribute" && !d)) { + (u && + ((0, Y.ensureObject)(s, "spaces", "attribute"), + (s.spaces.attribute.before = u), + (u = "")), + c && + ((0, Y.ensureObject)(s, "raws", "spaces", "attribute"), + (s.raws.spaces.attribute.before = c), + (c = "")), + (s.attribute = (s.attribute || "") + m)); + var S = (0, Y.getProp)(s, "raws", "attribute") || null; + (S && (s.raws.attribute += m), (f = "attribute")); + } else if ((!s.value && s.value !== "") || (f === "value" && !(d || s.quoteMark))) { + var _ = (0, Y.unesc)(m), + E = (0, Y.getProp)(s, "raws", "value") || "", + I = s.value || ""; + ((s.value = I + _), + (s.quoteMark = null), + (_ !== m || E) && + ((0, Y.ensureObject)(s, "raws"), (s.raws.value = (E || I) + m)), + (f = "value")); + } else { + var q = m === "i" || m === "I"; + (s.value || s.value === "") && (s.quoteMark || d) + ? ((s.insensitive = q), + (!q || m === "I") && + ((0, Y.ensureObject)(s, "raws"), (s.raws.insensitiveFlag = m)), + (f = "insensitive"), + u && + ((0, Y.ensureObject)(s, "spaces", "insensitive"), + (s.spaces.insensitive.before = u), + (u = "")), + c && + ((0, Y.ensureObject)(s, "raws", "spaces", "insensitive"), + (s.raws.spaces.insensitive.before = c), + (c = ""))) + : (s.value || s.value === "") && + ((f = "value"), (s.value += m), s.raws.value && (s.raws.value += m)); + } + d = !1; + break; + case T.str: + if (!s.attribute || !s.operator) + return this.error( + "Expected an attribute followed by an operator preceding the string.", + { index: p[A.FIELDS.START_POS] } + ); + var R = (0, kp.unescapeValue)(m), + J = R.unescaped, + ue = R.quoteMark; + ((s.value = J), + (s.quoteMark = ue), + (f = "value"), + (0, Y.ensureObject)(s, "raws"), + (s.raws.value = m), + (d = !1)); + break; + case T.equals: + if (!s.attribute) return this.expected("attribute", p[A.FIELDS.START_POS], m); + if (s.value) + return this.error('Unexpected "=" found; an operator was already defined.', { + index: p[A.FIELDS.START_POS], + }); + ((s.operator = s.operator ? s.operator + m : m), (f = "operator"), (d = !1)); + break; + case T.comment: + if (f) + if (d || (b && b[A.FIELDS.TYPE] === T.space) || f === "insensitive") { + var de = (0, Y.getProp)(s, "spaces", f, "after") || "", + De = (0, Y.getProp)(s, "raws", "spaces", f, "after") || de; + ((0, Y.ensureObject)(s, "raws", "spaces", f), + (s.raws.spaces[f].after = De + m)); + } else { + var ee = s[f] || "", + oe = (0, Y.getProp)(s, "raws", f) || ee; + ((0, Y.ensureObject)(s, "raws"), (s.raws[f] = oe + m)); + } + else c = c + m; + break; + default: + return this.error('Unexpected "' + m + '" found.', { index: p[A.FIELDS.START_POS] }); + } + o++; + } + (Bt(s, "attribute"), Bt(s, "namespace"), this.newNode(new kp.default(s)), this.position++); + }), + (e.parseWhitespaceEquivalentTokens = function (i) { + i < 0 && (i = this.tokens.length); + var n = this.position, + a = [], + s = "", + o = void 0; + do + if (Pa[this.currToken[A.FIELDS.TYPE]]) this.options.lossy || (s += this.content()); + else if (this.currToken[A.FIELDS.TYPE] === T.comment) { + var u = {}; + (s && ((u.before = s), (s = "")), + (o = new xp.default({ + value: this.content(), + source: Mt(this.currToken), + sourceIndex: this.currToken[A.FIELDS.START_POS], + spaces: u, + })), + a.push(o)); + } + while (++this.position < i); + if (s) { + if (o) o.spaces.after = s; + else if (!this.options.lossy) { + var c = this.tokens[n], + f = this.tokens[this.position - 1]; + a.push( + new Oa.default({ + value: "", + source: kt( + c[A.FIELDS.START_LINE], + c[A.FIELDS.START_COL], + f[A.FIELDS.END_LINE], + f[A.FIELDS.END_COL] + ), + sourceIndex: c[A.FIELDS.START_POS], + spaces: { before: s, after: "" }, + }) + ); + } + } + return a; + }), + (e.convertWhitespaceNodesToSpace = function (i, n) { + var a = this; + n === void 0 && (n = !1); + var s = "", + o = ""; + (i.forEach(function (c) { + var f = a.lossySpace(c.spaces.before, n), + d = a.lossySpace(c.rawSpaceBefore, n); + ((s += f + a.lossySpace(c.spaces.after, n && f.length === 0)), + (o += f + c.value + a.lossySpace(c.rawSpaceAfter, n && d.length === 0))); + }), + o === s && (o = void 0)); + var u = { space: s, rawSpace: o }; + return u; + }), + (e.isNamedCombinator = function (i) { + return ( + i === void 0 && (i = this.position), + this.tokens[i + 0] && + this.tokens[i + 0][A.FIELDS.TYPE] === T.slash && + this.tokens[i + 1] && + this.tokens[i + 1][A.FIELDS.TYPE] === T.word && + this.tokens[i + 2] && + this.tokens[i + 2][A.FIELDS.TYPE] === T.slash + ); + }), + (e.namedCombinator = function () { + if (this.isNamedCombinator()) { + var i = this.content(this.tokens[this.position + 1]), + n = (0, Y.unesc)(i).toLowerCase(), + a = {}; + n !== i && (a.value = "/" + i + "/"); + var s = new Ea.default({ + value: "/" + n + "/", + source: kt( + this.currToken[A.FIELDS.START_LINE], + this.currToken[A.FIELDS.START_COL], + this.tokens[this.position + 2][A.FIELDS.END_LINE], + this.tokens[this.position + 2][A.FIELDS.END_COL] + ), + sourceIndex: this.currToken[A.FIELDS.START_POS], + raws: a, + }); + return ((this.position = this.position + 3), s); + } else this.unexpected(); + }), + (e.combinator = function () { + var i = this; + if (this.content() === "|") return this.namespace(); + var n = this.locateNextMeaningfulToken(this.position); + if (n < 0 || this.tokens[n][A.FIELDS.TYPE] === T.comma) { + var a = this.parseWhitespaceEquivalentTokens(n); + if (a.length > 0) { + var s = this.current.last; + if (s) { + var o = this.convertWhitespaceNodesToSpace(a), + u = o.space, + c = o.rawSpace; + (c !== void 0 && (s.rawSpaceAfter += c), (s.spaces.after += u)); + } else + a.forEach(function (E) { + return i.newNode(E); + }); + } + return; + } + var f = this.currToken, + d = void 0; + n > this.position && (d = this.parseWhitespaceEquivalentTokens(n)); + var p; + if ( + (this.isNamedCombinator() + ? (p = this.namedCombinator()) + : this.currToken[A.FIELDS.TYPE] === T.combinator + ? ((p = new Ea.default({ + value: this.content(), + source: Mt(this.currToken), + sourceIndex: this.currToken[A.FIELDS.START_POS], + })), + this.position++) + : Pa[this.currToken[A.FIELDS.TYPE]] || d || this.unexpected(), + p) + ) { + if (d) { + var m = this.convertWhitespaceNodesToSpace(d), + b = m.space, + x = m.rawSpace; + ((p.spaces.before = b), (p.rawSpaceBefore = x)); + } + } else { + var y = this.convertWhitespaceNodesToSpace(d, !0), + w = y.space, + k = y.rawSpace; + k || (k = w); + var S = {}, + _ = { spaces: {} }; + (w.endsWith(" ") && k.endsWith(" ") + ? ((S.before = w.slice(0, w.length - 1)), (_.spaces.before = k.slice(0, k.length - 1))) + : w.startsWith(" ") && k.startsWith(" ") + ? ((S.after = w.slice(1)), (_.spaces.after = k.slice(1))) + : (_.value = k), + (p = new Ea.default({ + value: " ", + source: Da(f, this.tokens[this.position - 1]), + sourceIndex: f[A.FIELDS.START_POS], + spaces: S, + raws: _, + }))); + } + return ( + this.currToken && + this.currToken[A.FIELDS.TYPE] === T.space && + ((p.spaces.after = this.optionalSpace(this.content())), this.position++), + this.newNode(p) + ); + }), + (e.comma = function () { + if (this.position === this.tokens.length - 1) { + ((this.root.trailingComma = !0), this.position++); + return; + } + this.current._inferEndPosition(); + var i = new _a.default({ source: { start: Ap(this.tokens[this.position + 1]) } }); + (this.current.parent.append(i), (this.current = i), this.position++); + }), + (e.comment = function () { + var i = this.currToken; + (this.newNode( + new xp.default({ value: this.content(), source: Mt(i), sourceIndex: i[A.FIELDS.START_POS] }) + ), + this.position++); + }), + (e.error = function (i, n) { + throw this.root.error(i, n); + }), + (e.missingBackslash = function () { + return this.error("Expected a backslash preceding the semicolon.", { + index: this.currToken[A.FIELDS.START_POS], + }); + }), + (e.missingParenthesis = function () { + return this.expected("opening parenthesis", this.currToken[A.FIELDS.START_POS]); + }), + (e.missingSquareBracket = function () { + return this.expected("opening square bracket", this.currToken[A.FIELDS.START_POS]); + }), + (e.unexpected = function () { + return this.error( + "Unexpected '" + this.content() + "'. Escaping special characters with \\ may help.", + this.currToken[A.FIELDS.START_POS] + ); + }), + (e.unexpectedPipe = function () { + return this.error("Unexpected '|'.", this.currToken[A.FIELDS.START_POS]); + }), + (e.namespace = function () { + var i = (this.prevToken && this.content(this.prevToken)) || !0; + if (this.nextToken[A.FIELDS.TYPE] === T.word) return (this.position++, this.word(i)); + if (this.nextToken[A.FIELDS.TYPE] === T.asterisk) return (this.position++, this.universal(i)); + this.unexpectedPipe(); + }), + (e.nesting = function () { + if (this.nextToken) { + var i = this.content(this.nextToken); + if (i === "|") { + this.position++; + return; + } + } + var n = this.currToken; + (this.newNode( + new Lk.default({ value: this.content(), source: Mt(n), sourceIndex: n[A.FIELDS.START_POS] }) + ), + this.position++); + }), + (e.parentheses = function () { + var i = this.current.last, + n = 1; + if ((this.position++, i && i.type === $k.PSEUDO)) { + var a = new _a.default({ source: { start: Ap(this.tokens[this.position - 1]) } }), + s = this.current; + for (i.append(a), this.current = a; this.position < this.tokens.length && n; ) + (this.currToken[A.FIELDS.TYPE] === T.openParenthesis && n++, + this.currToken[A.FIELDS.TYPE] === T.closeParenthesis && n--, + n + ? this.parse() + : ((this.current.source.end = _p(this.currToken)), + (this.current.parent.source.end = _p(this.currToken)), + this.position++)); + this.current = s; + } else { + for (var o = this.currToken, u = "(", c; this.position < this.tokens.length && n; ) + (this.currToken[A.FIELDS.TYPE] === T.openParenthesis && n++, + this.currToken[A.FIELDS.TYPE] === T.closeParenthesis && n--, + (c = this.currToken), + (u += this.parseParenthesisToken(this.currToken)), + this.position++); + i + ? i.appendToPropertyAndEscape("value", u, u) + : this.newNode( + new Oa.default({ + value: u, + source: kt( + o[A.FIELDS.START_LINE], + o[A.FIELDS.START_COL], + c[A.FIELDS.END_LINE], + c[A.FIELDS.END_COL] + ), + sourceIndex: o[A.FIELDS.START_POS], + }) + ); + } + if (n) return this.expected("closing parenthesis", this.currToken[A.FIELDS.START_POS]); + }), + (e.pseudo = function () { + for ( + var i = this, n = "", a = this.currToken; + this.currToken && this.currToken[A.FIELDS.TYPE] === T.colon; + ) + ((n += this.content()), this.position++); + if (!this.currToken) return this.expected(["pseudo-class", "pseudo-element"], this.position - 1); + if (this.currToken[A.FIELDS.TYPE] === T.word) + this.splitWord(!1, function (s, o) { + ((n += s), + i.newNode( + new Bk.default({ + value: n, + source: Da(a, i.currToken), + sourceIndex: a[A.FIELDS.START_POS], + }) + ), + o > 1 && + i.nextToken && + i.nextToken[A.FIELDS.TYPE] === T.openParenthesis && + i.error("Misplaced parenthesis.", { index: i.nextToken[A.FIELDS.START_POS] })); + }); + else return this.expected(["pseudo-class", "pseudo-element"], this.currToken[A.FIELDS.START_POS]); + }), + (e.space = function () { + var i = this.content(); + this.position === 0 || + this.prevToken[A.FIELDS.TYPE] === T.comma || + this.prevToken[A.FIELDS.TYPE] === T.openParenthesis || + this.current.nodes.every(function (n) { + return n.type === "comment"; + }) + ? ((this.spaces = this.optionalSpace(i)), this.position++) + : this.position === this.tokens.length - 1 || + this.nextToken[A.FIELDS.TYPE] === T.comma || + this.nextToken[A.FIELDS.TYPE] === T.closeParenthesis + ? ((this.current.last.spaces.after = this.optionalSpace(i)), this.position++) + : this.combinator(); + }), + (e.string = function () { + var i = this.currToken; + (this.newNode( + new Oa.default({ value: this.content(), source: Mt(i), sourceIndex: i[A.FIELDS.START_POS] }) + ), + this.position++); + }), + (e.universal = function (i) { + var n = this.nextToken; + if (n && this.content(n) === "|") return (this.position++, this.namespace()); + var a = this.currToken; + (this.newNode( + new Fk.default({ value: this.content(), source: Mt(a), sourceIndex: a[A.FIELDS.START_POS] }), + i + ), + this.position++); + }), + (e.splitWord = function (i, n) { + for ( + var a = this, s = this.nextToken, o = this.content(); + s && ~[T.dollar, T.caret, T.equals, T.word].indexOf(s[A.FIELDS.TYPE]); + ) { + this.position++; + var u = this.content(); + if (((o += u), u.lastIndexOf("\\") === u.length - 1)) { + var c = this.nextToken; + c && + c[A.FIELDS.TYPE] === T.space && + ((o += this.requiredSpace(this.content(c))), this.position++); + } + s = this.nextToken; + } + var f = Ia(o, ".").filter(function (b) { + var x = o[b - 1] === "\\", + y = /^\d+\.\d+%$/.test(o); + return !x && !y; + }), + d = Ia(o, "#").filter(function (b) { + return o[b - 1] !== "\\"; + }), + p = Ia(o, "#{"); + p.length && + (d = d.filter(function (b) { + return !~p.indexOf(b); + })); + var m = (0, Nk.default)(Vk([0].concat(f, d))); + (m.forEach(function (b, x) { + var y = m[x + 1] || o.length, + w = o.slice(b, y); + if (x === 0 && n) return n.call(a, w, m.length); + var k, + S = a.currToken, + _ = S[A.FIELDS.START_POS] + m[x], + E = kt(S[1], S[2] + b, S[3], S[2] + (y - 1)); + if (~f.indexOf(b)) { + var I = { value: w.slice(1), source: E, sourceIndex: _ }; + k = new qk.default(Bt(I, "value")); + } else if (~d.indexOf(b)) { + var q = { value: w.slice(1), source: E, sourceIndex: _ }; + k = new Rk.default(Bt(q, "value")); + } else { + var R = { value: w, source: E, sourceIndex: _ }; + (Bt(R, "value"), (k = new Mk.default(R))); + } + (a.newNode(k, i), (i = null)); + }), + this.position++); + }), + (e.word = function (i) { + var n = this.nextToken; + return n && this.content(n) === "|" ? (this.position++, this.namespace()) : this.splitWord(i); + }), + (e.loop = function () { + for (; this.position < this.tokens.length; ) this.parse(!0); + return (this.current._inferEndPosition(), this.root); + }), + (e.parse = function (i) { + switch (this.currToken[A.FIELDS.TYPE]) { + case T.space: + this.space(); + break; + case T.comment: + this.comment(); + break; + case T.openParenthesis: + this.parentheses(); + break; + case T.closeParenthesis: + i && this.missingParenthesis(); + break; + case T.openSquare: + this.attribute(); + break; + case T.dollar: + case T.caret: + case T.equals: + case T.word: + this.word(); + break; + case T.colon: + this.pseudo(); + break; + case T.comma: + this.comma(); + break; + case T.asterisk: + this.universal(); + break; + case T.ampersand: + this.nesting(); + break; + case T.slash: + case T.combinator: + this.combinator(); + break; + case T.str: + this.string(); + break; + case T.closeSquare: + this.missingSquareBracket(); + case T.semicolon: + this.missingBackslash(); + default: + this.unexpected(); + } + }), + (e.expected = function (i, n, a) { + if (Array.isArray(i)) { + var s = i.pop(); + i = i.join(", ") + " or " + s; + } + var o = /^[aeiou]/.test(i[0]) ? "an" : "a"; + return a + ? this.error("Expected " + o + " " + i + ', found "' + a + '" instead.', { index: n }) + : this.error("Expected " + o + " " + i + ".", { index: n }); + }), + (e.requiredSpace = function (i) { + return this.options.lossy ? " " : i; + }), + (e.optionalSpace = function (i) { + return this.options.lossy ? "" : i; + }), + (e.lossySpace = function (i, n) { + return this.options.lossy ? (n ? " " : "") : i; + }), + (e.parseParenthesisToken = function (i) { + var n = this.content(i); + return i[A.FIELDS.TYPE] === T.space ? this.requiredSpace(n) : n; + }), + (e.newNode = function (i, n) { + return ( + n && + (/^ +$/.test(n) && + (this.options.lossy || (this.spaces = (this.spaces || "") + n), (n = !0)), + (i.namespace = n), + Bt(i, "namespace")), + this.spaces && ((i.spaces.before = this.spaces), (this.spaces = "")), + this.current.append(i) + ); + }), + (e.content = function (i) { + return ( + i === void 0 && (i = this.currToken), + this.css.slice(i[A.FIELDS.START_POS], i[A.FIELDS.END_POS]) + ); + }), + (e.locateNextMeaningfulToken = function (i) { + i === void 0 && (i = this.position + 1); + for (var n = i; n < this.tokens.length; ) + if (jk[this.tokens[n][A.FIELDS.TYPE]]) { + n++; + continue; + } else return n; + return -1; + }), + zk(r, [ + { + key: "currToken", + get: function () { + return this.tokens[this.position]; + }, + }, + { + key: "nextToken", + get: function () { + return this.tokens[this.position + 1]; + }, + }, + { + key: "prevToken", + get: function () { + return this.tokens[this.position - 1]; + }, + }, + ]), + r + ); + })(); + Hr.default = Uk; + Op.exports = Hr.default; + }); + var Pp = v((Yr, Tp) => { + l(); + ("use strict"); + Yr.__esModule = !0; + Yr.default = void 0; + var Wk = Gk(Ep()); + function Gk(r) { + return r && r.__esModule ? r : { default: r }; + } + var Hk = (function () { + function r(t, i) { + ((this.func = t || function () {}), (this.funcRes = null), (this.options = i)); + } + var e = r.prototype; + return ( + (e._shouldUpdateSelector = function (i, n) { + n === void 0 && (n = {}); + var a = Object.assign({}, this.options, n); + return a.updateSelector === !1 ? !1 : typeof i != "string"; + }), + (e._isLossy = function (i) { + i === void 0 && (i = {}); + var n = Object.assign({}, this.options, i); + return n.lossless === !1; + }), + (e._root = function (i, n) { + n === void 0 && (n = {}); + var a = new Wk.default(i, this._parseOptions(n)); + return a.root; + }), + (e._parseOptions = function (i) { + return { lossy: this._isLossy(i) }; + }), + (e._run = function (i, n) { + var a = this; + return ( + n === void 0 && (n = {}), + new Promise(function (s, o) { + try { + var u = a._root(i, n); + Promise.resolve(a.func(u)) + .then(function (c) { + var f = void 0; + return ( + a._shouldUpdateSelector(i, n) && ((f = u.toString()), (i.selector = f)), + { transform: c, root: u, string: f } + ); + }) + .then(s, o); + } catch (c) { + o(c); + return; + } + }) + ); + }), + (e._runSync = function (i, n) { + n === void 0 && (n = {}); + var a = this._root(i, n), + s = this.func(a); + if (s && typeof s.then == "function") + throw new Error("Selector processor returned a promise to a synchronous call."); + var o = void 0; + return ( + n.updateSelector && typeof i != "string" && ((o = a.toString()), (i.selector = o)), + { transform: s, root: a, string: o } + ); + }), + (e.ast = function (i, n) { + return this._run(i, n).then(function (a) { + return a.root; + }); + }), + (e.astSync = function (i, n) { + return this._runSync(i, n).root; + }), + (e.transform = function (i, n) { + return this._run(i, n).then(function (a) { + return a.transform; + }); + }), + (e.transformSync = function (i, n) { + return this._runSync(i, n).transform; + }), + (e.process = function (i, n) { + return this._run(i, n).then(function (a) { + return a.string || a.root.toString(); + }); + }), + (e.processSync = function (i, n) { + var a = this._runSync(i, n); + return a.string || a.root.toString(); + }), + r + ); + })(); + Yr.default = Hk; + Tp.exports = Yr.default; + }); + var Dp = v((G) => { + l(); + ("use strict"); + G.__esModule = !0; + G.universal = + G.tag = + G.string = + G.selector = + G.root = + G.pseudo = + G.nesting = + G.id = + G.comment = + G.combinator = + G.className = + G.attribute = + void 0; + var Yk = ve(ya()), + Qk = ve(ea()), + Jk = ve(xa()), + Xk = ve(ra()), + Kk = ve(na()), + Zk = ve(Sa()), + eS = ve(ca()), + tS = ve(Qs()), + rS = ve(Xs()), + iS = ve(ua()), + nS = ve(oa()), + sS = ve(ba()); + function ve(r) { + return r && r.__esModule ? r : { default: r }; + } + var aS = function (e) { + return new Yk.default(e); + }; + G.attribute = aS; + var oS = function (e) { + return new Qk.default(e); + }; + G.className = oS; + var lS = function (e) { + return new Jk.default(e); + }; + G.combinator = lS; + var uS = function (e) { + return new Xk.default(e); + }; + G.comment = uS; + var fS = function (e) { + return new Kk.default(e); + }; + G.id = fS; + var cS = function (e) { + return new Zk.default(e); + }; + G.nesting = cS; + var pS = function (e) { + return new eS.default(e); + }; + G.pseudo = pS; + var dS = function (e) { + return new tS.default(e); + }; + G.root = dS; + var hS = function (e) { + return new rS.default(e); + }; + G.selector = hS; + var mS = function (e) { + return new iS.default(e); + }; + G.string = mS; + var gS = function (e) { + return new nS.default(e); + }; + G.tag = gS; + var yS = function (e) { + return new sS.default(e); + }; + G.universal = yS; + }); + var Mp = v(($) => { + l(); + ("use strict"); + $.__esModule = !0; + $.isComment = $.isCombinator = $.isClassName = $.isAttribute = void 0; + $.isContainer = TS; + $.isIdentifier = void 0; + $.isNamespace = PS; + $.isNesting = void 0; + $.isNode = qa; + $.isPseudo = void 0; + $.isPseudoClass = ES; + $.isPseudoElement = Rp; + $.isUniversal = $.isTag = $.isString = $.isSelector = $.isRoot = void 0; + var Q = ne(), + fe, + wS = + ((fe = {}), + (fe[Q.ATTRIBUTE] = !0), + (fe[Q.CLASS] = !0), + (fe[Q.COMBINATOR] = !0), + (fe[Q.COMMENT] = !0), + (fe[Q.ID] = !0), + (fe[Q.NESTING] = !0), + (fe[Q.PSEUDO] = !0), + (fe[Q.ROOT] = !0), + (fe[Q.SELECTOR] = !0), + (fe[Q.STRING] = !0), + (fe[Q.TAG] = !0), + (fe[Q.UNIVERSAL] = !0), + fe); + function qa(r) { + return typeof r == "object" && wS[r.type]; + } + function xe(r, e) { + return qa(e) && e.type === r; + } + var Ip = xe.bind(null, Q.ATTRIBUTE); + $.isAttribute = Ip; + var bS = xe.bind(null, Q.CLASS); + $.isClassName = bS; + var vS = xe.bind(null, Q.COMBINATOR); + $.isCombinator = vS; + var xS = xe.bind(null, Q.COMMENT); + $.isComment = xS; + var kS = xe.bind(null, Q.ID); + $.isIdentifier = kS; + var SS = xe.bind(null, Q.NESTING); + $.isNesting = SS; + var Ra = xe.bind(null, Q.PSEUDO); + $.isPseudo = Ra; + var CS = xe.bind(null, Q.ROOT); + $.isRoot = CS; + var AS = xe.bind(null, Q.SELECTOR); + $.isSelector = AS; + var _S = xe.bind(null, Q.STRING); + $.isString = _S; + var qp = xe.bind(null, Q.TAG); + $.isTag = qp; + var OS = xe.bind(null, Q.UNIVERSAL); + $.isUniversal = OS; + function Rp(r) { + return ( + Ra(r) && + r.value && + (r.value.startsWith("::") || + r.value.toLowerCase() === ":before" || + r.value.toLowerCase() === ":after" || + r.value.toLowerCase() === ":first-letter" || + r.value.toLowerCase() === ":first-line") + ); + } + function ES(r) { + return Ra(r) && !Rp(r); + } + function TS(r) { + return !!(qa(r) && r.walk); + } + function PS(r) { + return Ip(r) || qp(r); + } + }); + var Bp = v((Ee) => { + l(); + ("use strict"); + Ee.__esModule = !0; + var Ma = ne(); + Object.keys(Ma).forEach(function (r) { + r === "default" || r === "__esModule" || (r in Ee && Ee[r] === Ma[r]) || (Ee[r] = Ma[r]); + }); + var Ba = Dp(); + Object.keys(Ba).forEach(function (r) { + r === "default" || r === "__esModule" || (r in Ee && Ee[r] === Ba[r]) || (Ee[r] = Ba[r]); + }); + var Fa = Mp(); + Object.keys(Fa).forEach(function (r) { + r === "default" || r === "__esModule" || (r in Ee && Ee[r] === Fa[r]) || (Ee[r] = Fa[r]); + }); + }); + var Me = v((Qr, Lp) => { + l(); + ("use strict"); + Qr.__esModule = !0; + Qr.default = void 0; + var DS = RS(Pp()), + IS = qS(Bp()); + function Fp(r) { + if (typeof WeakMap != "function") return null; + var e = new WeakMap(), + t = new WeakMap(); + return (Fp = function (n) { + return n ? t : e; + })(r); + } + function qS(r, e) { + if (!e && r && r.__esModule) return r; + if (r === null || (typeof r != "object" && typeof r != "function")) return { default: r }; + var t = Fp(e); + if (t && t.has(r)) return t.get(r); + var i = {}, + n = Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var a in r) + if (a !== "default" && Object.prototype.hasOwnProperty.call(r, a)) { + var s = n ? Object.getOwnPropertyDescriptor(r, a) : null; + s && (s.get || s.set) ? Object.defineProperty(i, a, s) : (i[a] = r[a]); + } + return ((i.default = r), t && t.set(r, i), i); + } + function RS(r) { + return r && r.__esModule ? r : { default: r }; + } + var La = function (e) { + return new DS.default(e); + }; + Object.assign(La, IS); + delete La.__esModule; + var MS = La; + Qr.default = MS; + Lp.exports = Qr.default; + }); + function Ge(r) { + return ["fontSize", "outline"].includes(r) + ? (e) => (typeof e == "function" && (e = e({})), Array.isArray(e) && (e = e[0]), e) + : r === "fontFamily" + ? (e) => { + typeof e == "function" && (e = e({})); + let t = Array.isArray(e) && ie(e[1]) ? e[0] : e; + return Array.isArray(t) ? t.join(", ") : t; + } + : [ + "boxShadow", + "transitionProperty", + "transitionDuration", + "transitionDelay", + "transitionTimingFunction", + "backgroundImage", + "backgroundSize", + "backgroundColor", + "cursor", + "animation", + ].includes(r) + ? (e) => (typeof e == "function" && (e = e({})), Array.isArray(e) && (e = e.join(", ")), e) + : ["gridTemplateColumns", "gridTemplateRows", "objectPosition"].includes(r) + ? (e) => ( + typeof e == "function" && (e = e({})), + typeof e == "string" && (e = j.list.comma(e).join(" ")), + e + ) + : (e, t = {}) => (typeof e == "function" && (e = e(t)), e); + } + var Jr = C(() => { + l(); + st(); + At(); + }); + var Wp = v((PT, Va) => { + l(); + var { Rule: Np, AtRule: BS } = ge(), + $p = Me(); + function Na(r, e) { + let t; + try { + $p((i) => { + t = i; + }).processSync(r); + } catch (i) { + throw r.includes(":") ? (e ? e.error("Missed semicolon") : i) : e ? e.error(i.message) : i; + } + return t.at(0); + } + function zp(r, e) { + let t = !1; + return ( + r.each((i) => { + if (i.type === "nesting") { + let n = e.clone({}); + (i.value !== "&" ? i.replaceWith(Na(i.value.replace("&", n.toString()))) : i.replaceWith(n), + (t = !0)); + } else "nodes" in i && i.nodes && zp(i, e) && (t = !0); + }), + t + ); + } + function jp(r, e) { + let t = []; + return ( + r.selectors.forEach((i) => { + let n = Na(i, r); + e.selectors.forEach((a) => { + if (!a) return; + let s = Na(a, e); + (zp(s, n) || (s.prepend($p.combinator({ value: " " })), s.prepend(n.clone({}))), + t.push(s.toString())); + }); + }), + t + ); + } + function cn(r, e) { + let t = r.prev(); + for (e.after(r); t && t.type === "comment"; ) { + let i = t.prev(); + (e.after(t), (t = i)); + } + return r; + } + function FS(r) { + return function e(t, i, n, a = n) { + let s = []; + if ( + (i.each((o) => { + o.type === "rule" && n + ? a && (o.selectors = jp(t, o)) + : o.type === "atrule" && o.nodes + ? r[o.name] + ? e(t, o, a) + : i[za] !== !1 && s.push(o) + : s.push(o); + }), + n && s.length) + ) { + let o = t.clone({ nodes: [] }); + for (let u of s) o.append(u); + i.prepend(o); + } + }; + } + function $a(r, e, t) { + let i = new Np({ selector: r, nodes: [] }); + return (i.append(e), t.after(i), i); + } + function Vp(r, e) { + let t = {}; + for (let i of r) t[i] = !0; + if (e) for (let i of e) t[i.replace(/^@/, "")] = !0; + return t; + } + function LS(r) { + r = r.trim(); + let e = r.match(/^\((.*)\)$/); + if (!e) return { type: "basic", selector: r }; + let t = e[1].match(/^(with(?:out)?):(.+)$/); + if (t) { + let i = t[1] === "with", + n = Object.fromEntries( + t[2] + .trim() + .split(/\s+/) + .map((s) => [s, !0]) + ); + if (i && n.all) return { type: "noop" }; + let a = (s) => !!n[s]; + return ( + n.all ? (a = () => !0) : i && (a = (s) => (s === "all" ? !1 : !n[s])), + { type: "withrules", escapes: a } + ); + } + return { type: "unknown" }; + } + function NS(r) { + let e = [], + t = r.parent; + for (; t && t instanceof BS; ) (e.push(t), (t = t.parent)); + return e; + } + function $S(r) { + let e = r[Up]; + if (!e) r.after(r.nodes); + else { + let t = r.nodes, + i, + n = -1, + a, + s, + o, + u = NS(r); + if ( + (u.forEach((c, f) => { + if (e(c.name)) ((i = c), (n = f), (s = o)); + else { + let d = o; + ((o = c.clone({ nodes: [] })), d && o.append(d), (a = a || o)); + } + }), + i ? (s ? (a.append(t), i.after(s)) : i.after(t)) : r.after(t), + r.next() && i) + ) { + let c; + (u.slice(0, n + 1).forEach((f, d, p) => { + let m = c; + ((c = f.clone({ nodes: [] })), m && c.append(m)); + let b = [], + y = (p[d - 1] || r).next(); + for (; y; ) (b.push(y), (y = y.next())); + c.append(b); + }), + c && (s || t[t.length - 1]).after(c)); + } + } + r.remove(); + } + var za = Symbol("rootRuleMergeSel"), + Up = Symbol("rootRuleEscapes"); + function zS(r) { + let { params: e } = r, + { type: t, selector: i, escapes: n } = LS(e); + if (t === "unknown") throw r.error(`Unknown @${r.name} parameter ${JSON.stringify(e)}`); + if (t === "basic" && i) { + let a = new Np({ selector: i, nodes: r.nodes }); + (r.removeAll(), r.append(a)); + } + ((r[Up] = n), (r[za] = n ? !n("all") : t === "noop")); + } + var ja = Symbol("hasRootRule"); + Va.exports = (r = {}) => { + let e = Vp(["media", "supports", "layer", "container"], r.bubble), + t = FS(e), + i = Vp(["document", "font-face", "keyframes", "-webkit-keyframes", "-moz-keyframes"], r.unwrap), + n = (r.rootRuleName || "at-root").replace(/^@/, ""), + a = r.preserveEmpty; + return { + postcssPlugin: "postcss-nested", + Once(s) { + s.walkAtRules(n, (o) => { + (zS(o), (s[ja] = !0)); + }); + }, + Rule(s) { + let o = !1, + u = s, + c = !1, + f = []; + (s.each((d) => { + d.type === "rule" + ? (f.length && ((u = $a(s.selector, f, u)), (f = [])), + (c = !0), + (o = !0), + (d.selectors = jp(s, d)), + (u = cn(d, u))) + : d.type === "atrule" + ? (f.length && ((u = $a(s.selector, f, u)), (f = [])), + d.name === n + ? ((o = !0), t(s, d, !0, d[za]), (u = cn(d, u))) + : e[d.name] + ? ((c = !0), (o = !0), t(s, d, !0), (u = cn(d, u))) + : i[d.name] + ? ((c = !0), (o = !0), t(s, d, !1), (u = cn(d, u))) + : c && f.push(d)) + : d.type === "decl" && c && f.push(d); + }), + f.length && (u = $a(s.selector, f, u)), + o && a !== !0 && ((s.raws.semicolon = !0), s.nodes.length === 0 && s.remove())); + }, + RootExit(s) { + s[ja] && (s.walkAtRules(n, $S), (s[ja] = !1)); + }, + }; + }; + Va.exports.postcss = !0; + }); + var Qp = v((DT, Yp) => { + l(); + ("use strict"); + var Gp = /-(\w|$)/g, + Hp = (r, e) => e.toUpperCase(), + jS = (r) => ( + (r = r.toLowerCase()), + r === "float" ? "cssFloat" : r.startsWith("-ms-") ? r.substr(1).replace(Gp, Hp) : r.replace(Gp, Hp) + ); + Yp.exports = jS; + }); + var Ga = v((IT, Jp) => { + l(); + var VS = Qp(), + US = { + boxFlex: !0, + boxFlexGroup: !0, + columnCount: !0, + flex: !0, + flexGrow: !0, + flexPositive: !0, + flexShrink: !0, + flexNegative: !0, + fontWeight: !0, + lineClamp: !0, + lineHeight: !0, + opacity: !0, + order: !0, + orphans: !0, + tabSize: !0, + widows: !0, + zIndex: !0, + zoom: !0, + fillOpacity: !0, + strokeDashoffset: !0, + strokeOpacity: !0, + strokeWidth: !0, + }; + function Ua(r) { + return typeof r.nodes == "undefined" ? !0 : Wa(r); + } + function Wa(r) { + let e, + t = {}; + return ( + r.each((i) => { + if (i.type === "atrule") + ((e = "@" + i.name), + i.params && (e += " " + i.params), + typeof t[e] == "undefined" + ? (t[e] = Ua(i)) + : Array.isArray(t[e]) + ? t[e].push(Ua(i)) + : (t[e] = [t[e], Ua(i)])); + else if (i.type === "rule") { + let n = Wa(i); + if (t[i.selector]) for (let a in n) t[i.selector][a] = n[a]; + else t[i.selector] = n; + } else if (i.type === "decl") { + (i.prop[0] === "-" && i.prop[1] === "-") || (i.parent && i.parent.selector === ":export") + ? (e = i.prop) + : (e = VS(i.prop)); + let n = i.value; + (!isNaN(i.value) && US[e] && (n = parseFloat(i.value)), + i.important && (n += " !important"), + typeof t[e] == "undefined" + ? (t[e] = n) + : Array.isArray(t[e]) + ? t[e].push(n) + : (t[e] = [t[e], n])); + } + }), + t + ); + } + Jp.exports = Wa; + }); + var pn = v((qT, ed) => { + l(); + var Xr = ge(), + Xp = /\s*!important\s*$/i, + WS = { + "box-flex": !0, + "box-flex-group": !0, + "column-count": !0, + flex: !0, + "flex-grow": !0, + "flex-positive": !0, + "flex-shrink": !0, + "flex-negative": !0, + "font-weight": !0, + "line-clamp": !0, + "line-height": !0, + opacity: !0, + order: !0, + orphans: !0, + "tab-size": !0, + widows: !0, + "z-index": !0, + zoom: !0, + "fill-opacity": !0, + "stroke-dashoffset": !0, + "stroke-opacity": !0, + "stroke-width": !0, + }; + function GS(r) { + return r + .replace(/([A-Z])/g, "-$1") + .replace(/^ms-/, "-ms-") + .toLowerCase(); + } + function Kp(r, e, t) { + t === !1 || + t === null || + (e.startsWith("--") || (e = GS(e)), + typeof t == "number" && (t === 0 || WS[e] ? (t = t.toString()) : (t += "px")), + e === "css-float" && (e = "float"), + Xp.test(t) + ? ((t = t.replace(Xp, "")), r.push(Xr.decl({ prop: e, value: t, important: !0 }))) + : r.push(Xr.decl({ prop: e, value: t }))); + } + function Zp(r, e, t) { + let i = Xr.atRule({ name: e[1], params: e[3] || "" }); + (typeof t == "object" && ((i.nodes = []), Ha(t, i)), r.push(i)); + } + function Ha(r, e) { + let t, i, n; + for (t in r) + if (((i = r[t]), !(i === null || typeof i == "undefined"))) + if (t[0] === "@") { + let a = t.match(/@(\S+)(\s+([\W\w]*)\s*)?/); + if (Array.isArray(i)) for (let s of i) Zp(e, a, s); + else Zp(e, a, i); + } else if (Array.isArray(i)) for (let a of i) Kp(e, t, a); + else typeof i == "object" ? ((n = Xr.rule({ selector: t })), Ha(i, n), e.push(n)) : Kp(e, t, i); + } + ed.exports = function (r) { + let e = Xr.root(); + return (Ha(r, e), e); + }; + }); + var Ya = v((RT, td) => { + l(); + var HS = Ga(); + td.exports = function (e) { + return ( + console && + console.warn && + e.warnings().forEach((t) => { + let i = t.plugin || "PostCSS"; + console.warn(i + ": " + t.text); + }), + HS(e.root) + ); + }; + }); + var id = v((MT, rd) => { + l(); + var YS = ge(), + QS = Ya(), + JS = pn(); + rd.exports = function (e) { + let t = YS(e); + return async (i) => { + let n = await t.process(i, { parser: JS, from: void 0 }); + return QS(n); + }; + }; + }); + var sd = v((BT, nd) => { + l(); + var XS = ge(), + KS = Ya(), + ZS = pn(); + nd.exports = function (r) { + let e = XS(r); + return (t) => { + let i = e.process(t, { parser: ZS, from: void 0 }); + return KS(i); + }; + }; + }); + var od = v((FT, ad) => { + l(); + var e2 = Ga(), + t2 = pn(), + r2 = id(), + i2 = sd(); + ad.exports = { objectify: e2, parse: t2, async: r2, sync: i2 }; + }); + var Ft, + ld, + LT, + NT, + $T, + zT, + ud = C(() => { + l(); + ((Ft = X(od())), + (ld = Ft.default), + (LT = Ft.default.objectify), + (NT = Ft.default.parse), + ($T = Ft.default.async), + (zT = Ft.default.sync)); + }); + function Lt(r) { + return Array.isArray(r) + ? r.flatMap((e) => j([(0, fd.default)({ bubble: ["screen"] })]).process(e, { parser: ld }).root.nodes) + : Lt([r]); + } + var fd, + Qa = C(() => { + l(); + st(); + fd = X(Wp()); + ud(); + }); + function Nt(r, e, t = !1) { + if (r === "") return e; + let i = typeof e == "string" ? (0, cd.default)().astSync(e) : e; + return ( + i.walkClasses((n) => { + let a = n.value, + s = t && a.startsWith("-"); + n.value = s ? `-${r}${a.slice(1)}` : `${r}${a}`; + }), + typeof e == "string" ? i.toString() : i + ); + } + var cd, + dn = C(() => { + l(); + cd = X(Me()); + }); + function ce(r) { + let e = pd.default.className(); + return ((e.value = r), wt(e?.raws?.value ?? e.value)); + } + var pd, + $t = C(() => { + l(); + pd = X(Me()); + bi(); + }); + function Ja(r) { + return wt(`.${ce(r)}`); + } + function hn(r, e) { + return Ja(Kr(r, e)); + } + function Kr(r, e) { + return e === "DEFAULT" + ? r + : e === "-" || e === "-DEFAULT" + ? `-${r}` + : e.startsWith("-") + ? `-${r}${e}` + : e.startsWith("/") + ? `${r}${e}` + : `${r}-${e}`; + } + var Xa = C(() => { + l(); + $t(); + bi(); + }); + function P(r, e = [[r, [r]]], { filterDefault: t = !1, ...i } = {}) { + let n = Ge(r); + return function ({ matchUtilities: a, theme: s }) { + for (let o of e) { + let u = Array.isArray(o[0]) ? o : [o]; + a( + u.reduce( + (c, [f, d]) => + Object.assign(c, { + [f]: (p) => + d.reduce( + (m, b) => + Array.isArray(b) + ? Object.assign(m, { [b[0]]: b[1] }) + : Object.assign(m, { [b]: n(p) }), + {} + ), + }), + {} + ), + { + ...i, + values: t + ? Object.fromEntries(Object.entries(s(r) ?? {}).filter(([c]) => c !== "DEFAULT")) + : s(r), + } + ); + } + }; + } + var dd = C(() => { + l(); + Jr(); + }); + function at(r) { + return ( + (r = Array.isArray(r) ? r : [r]), + r + .map((e) => { + let t = e.values.map((i) => + i.raw !== void 0 + ? i.raw + : [i.min && `(min-width: ${i.min})`, i.max && `(max-width: ${i.max})`] + .filter(Boolean) + .join(" and ") + ); + return e.not ? `not all and ${t}` : t; + }) + .join(", ") + ); + } + var mn = C(() => { + l(); + }); + function Ka(r) { + return r.split(f2).map((t) => { + let i = t.trim(), + n = { value: i }, + a = i.split(c2), + s = new Set(); + for (let o of a) + !s.has("DIRECTIONS") && n2.has(o) + ? ((n.direction = o), s.add("DIRECTIONS")) + : !s.has("PLAY_STATES") && s2.has(o) + ? ((n.playState = o), s.add("PLAY_STATES")) + : !s.has("FILL_MODES") && a2.has(o) + ? ((n.fillMode = o), s.add("FILL_MODES")) + : !s.has("ITERATION_COUNTS") && (o2.has(o) || p2.test(o)) + ? ((n.iterationCount = o), s.add("ITERATION_COUNTS")) + : (!s.has("TIMING_FUNCTION") && l2.has(o)) || + (!s.has("TIMING_FUNCTION") && u2.some((u) => o.startsWith(`${u}(`))) + ? ((n.timingFunction = o), s.add("TIMING_FUNCTION")) + : !s.has("DURATION") && hd.test(o) + ? ((n.duration = o), s.add("DURATION")) + : !s.has("DELAY") && hd.test(o) + ? ((n.delay = o), s.add("DELAY")) + : s.has("NAME") + ? (n.unknown || (n.unknown = []), n.unknown.push(o)) + : ((n.name = o), s.add("NAME")); + return n; + }); + } + var n2, + s2, + a2, + o2, + l2, + u2, + f2, + c2, + hd, + p2, + md = C(() => { + l(); + ((n2 = new Set(["normal", "reverse", "alternate", "alternate-reverse"])), + (s2 = new Set(["running", "paused"])), + (a2 = new Set(["none", "forwards", "backwards", "both"])), + (o2 = new Set(["infinite"])), + (l2 = new Set(["linear", "ease", "ease-in", "ease-out", "ease-in-out", "step-start", "step-end"])), + (u2 = ["cubic-bezier", "steps"]), + (f2 = /\,(?![^(]*\))/g), + (c2 = /\ +(?![^(]*\))/g), + (hd = /^(-?[\d.]+m?s)$/), + (p2 = /^(\d+)$/)); + }); + var gd, + re, + yd = C(() => { + l(); + ((gd = (r) => + Object.assign( + {}, + ...Object.entries(r ?? {}).flatMap(([e, t]) => + typeof t == "object" + ? Object.entries(gd(t)).map(([i, n]) => ({ [e + (i === "DEFAULT" ? "" : `-${i}`)]: n })) + : [{ [`${e}`]: t }] + ) + )), + (re = gd)); + }); + var bd, + wd = C(() => { + bd = "3.4.3"; + }); + function ot(r, e = !0) { + return Array.isArray(r) + ? r.map((t) => { + if (e && Array.isArray(t)) throw new Error("The tuple syntax is not supported for `screens`."); + if (typeof t == "string") return { name: t.toString(), not: !1, values: [{ min: t, max: void 0 }] }; + let [i, n] = t; + return ( + (i = i.toString()), + typeof n == "string" + ? { name: i, not: !1, values: [{ min: n, max: void 0 }] } + : Array.isArray(n) + ? { name: i, not: !1, values: n.map((a) => xd(a)) } + : { name: i, not: !1, values: [xd(n)] } + ); + }) + : ot(Object.entries(r ?? {}), !1); + } + function gn(r) { + return r.values.length !== 1 + ? { result: !1, reason: "multiple-values" } + : r.values[0].raw !== void 0 + ? { result: !1, reason: "raw-values" } + : r.values[0].min !== void 0 && r.values[0].max !== void 0 + ? { result: !1, reason: "min-and-max" } + : { result: !0, reason: null }; + } + function vd(r, e, t) { + let i = yn(e, r), + n = yn(t, r), + a = gn(i), + s = gn(n); + if (a.reason === "multiple-values" || s.reason === "multiple-values") + throw new Error( + "Attempted to sort a screen with multiple values. This should never happen. Please open a bug report." + ); + if (a.reason === "raw-values" || s.reason === "raw-values") + throw new Error( + "Attempted to sort a screen with raw values. This should never happen. Please open a bug report." + ); + if (a.reason === "min-and-max" || s.reason === "min-and-max") + throw new Error( + "Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report." + ); + let { min: o, max: u } = i.values[0], + { min: c, max: f } = n.values[0]; + (e.not && ([o, u] = [u, o]), + t.not && ([c, f] = [f, c]), + (o = o === void 0 ? o : parseFloat(o)), + (u = u === void 0 ? u : parseFloat(u)), + (c = c === void 0 ? c : parseFloat(c)), + (f = f === void 0 ? f : parseFloat(f))); + let [d, p] = r === "min" ? [o, c] : [f, u]; + return d - p; + } + function yn(r, e) { + return typeof r == "object" ? r : { name: "arbitrary-screen", values: [{ [e]: r }] }; + } + function xd({ "min-width": r, min: e = r, max: t, raw: i } = {}) { + return { min: e, max: t, raw: i }; + } + var wn = C(() => { + l(); + }); + function bn(r, e) { + r.walkDecls((t) => { + if (e.includes(t.prop)) { + t.remove(); + return; + } + for (let i of e) t.value.includes(`/ var(${i})`) && (t.value = t.value.replace(`/ var(${i})`, "")); + }); + } + var kd = C(() => { + l(); + }); + var H, + Te, + Be, + Fe, + Sd, + Cd = C(() => { + l(); + ze(); + bt(); + st(); + dd(); + mn(); + $t(); + md(); + yd(); + fr(); + ws(); + At(); + Jr(); + wd(); + Oe(); + wn(); + cs(); + kd(); + je(); + dr(); + ei(); + ((H = { + childVariant: ({ addVariant: r }) => { + r("*", "& > *"); + }, + pseudoElementVariants: ({ addVariant: r }) => { + (r("first-letter", "&::first-letter"), + r("first-line", "&::first-line"), + r("marker", [ + ({ container: e }) => (bn(e, ["--tw-text-opacity"]), "& *::marker"), + ({ container: e }) => (bn(e, ["--tw-text-opacity"]), "&::marker"), + ]), + r("selection", ["& *::selection", "&::selection"]), + r("file", "&::file-selector-button"), + r("placeholder", "&::placeholder"), + r("backdrop", "&::backdrop"), + r( + "before", + ({ container: e }) => ( + e.walkRules((t) => { + let i = !1; + (t.walkDecls("content", () => { + i = !0; + }), + i || t.prepend(j.decl({ prop: "content", value: "var(--tw-content)" }))); + }), + "&::before" + ) + ), + r( + "after", + ({ container: e }) => ( + e.walkRules((t) => { + let i = !1; + (t.walkDecls("content", () => { + i = !0; + }), + i || t.prepend(j.decl({ prop: "content", value: "var(--tw-content)" }))); + }), + "&::after" + ) + )); + }, + pseudoClassVariants: ({ addVariant: r, matchVariant: e, config: t, prefix: i }) => { + let n = [ + ["first", "&:first-child"], + ["last", "&:last-child"], + ["only", "&:only-child"], + ["odd", "&:nth-child(odd)"], + ["even", "&:nth-child(even)"], + "first-of-type", + "last-of-type", + "only-of-type", + [ + "visited", + ({ container: s }) => ( + bn(s, ["--tw-text-opacity", "--tw-border-opacity", "--tw-bg-opacity"]), + "&:visited" + ), + ], + "target", + ["open", "&[open]"], + "default", + "checked", + "indeterminate", + "placeholder-shown", + "autofill", + "optional", + "required", + "valid", + "invalid", + "in-range", + "out-of-range", + "read-only", + "empty", + "focus-within", + [ + "hover", + K(t(), "hoverOnlyWhenSupported") + ? "@media (hover: hover) and (pointer: fine) { &:hover }" + : "&:hover", + ], + "focus", + "focus-visible", + "active", + "enabled", + "disabled", + ].map((s) => (Array.isArray(s) ? s : [s, `&:${s}`])); + for (let [s, o] of n) r(s, (u) => (typeof o == "function" ? o(u) : o)); + let a = { + group: (s, { modifier: o }) => + o ? [`:merge(${i(".group")}\\/${ce(o)})`, " &"] : [`:merge(${i(".group")})`, " &"], + peer: (s, { modifier: o }) => + o ? [`:merge(${i(".peer")}\\/${ce(o)})`, " ~ &"] : [`:merge(${i(".peer")})`, " ~ &"], + }; + for (let [s, o] of Object.entries(a)) + e( + s, + (u = "", c) => { + let f = L(typeof u == "function" ? u(c) : u); + f.includes("&") || (f = "&" + f); + let [d, p] = o("", c), + m = null, + b = null, + x = 0; + for (let y = 0; y < f.length; ++y) { + let w = f[y]; + w === "&" + ? (m = y) + : w === "'" || w === '"' + ? (x += 1) + : m !== null && w === " " && !x && (b = y); + } + return ( + m !== null && b === null && (b = f.length), + f.slice(0, m) + d + f.slice(m + 1, b) + p + f.slice(b) + ); + }, + { values: Object.fromEntries(n), [Zr]: { respectPrefix: !1 } } + ); + }, + directionVariants: ({ addVariant: r }) => { + (r("ltr", '&:where([dir="ltr"], [dir="ltr"] *)'), r("rtl", '&:where([dir="rtl"], [dir="rtl"] *)')); + }, + reducedMotionVariants: ({ addVariant: r }) => { + (r("motion-safe", "@media (prefers-reduced-motion: no-preference)"), + r("motion-reduce", "@media (prefers-reduced-motion: reduce)")); + }, + darkVariants: ({ config: r, addVariant: e }) => { + let [t, i = ".dark"] = [].concat(r("darkMode", "media")); + if ( + (t === !1 && + ((t = "media"), + F.warn("darkmode-false", [ + "The `darkMode` option in your Tailwind CSS configuration is set to `false`, which now behaves the same as `media`.", + "Change `darkMode` to `media` or remove it entirely.", + "https://tailwindcss.com/docs/upgrade-guide#remove-dark-mode-configuration", + ])), + t === "variant") + ) { + let n; + if ( + (Array.isArray(i) || typeof i == "function" ? (n = i) : typeof i == "string" && (n = [i]), + Array.isArray(n)) + ) + for (let a of n) + a === ".dark" + ? ((t = !1), + F.warn("darkmode-variant-without-selector", [ + "When using `variant` for `darkMode`, you must provide a selector.", + 'Example: `darkMode: ["variant", ".your-selector &"]`', + ])) + : a.includes("&") || + ((t = !1), + F.warn("darkmode-variant-without-ampersand", [ + "When using `variant` for `darkMode`, your selector must contain `&`.", + 'Example `darkMode: ["variant", ".your-selector &"]`', + ])); + i = n; + } + t === "selector" + ? e("dark", `&:where(${i}, ${i} *)`) + : t === "media" + ? e("dark", "@media (prefers-color-scheme: dark)") + : t === "variant" + ? e("dark", i) + : t === "class" && e("dark", `&:is(${i} *)`); + }, + printVariant: ({ addVariant: r }) => { + r("print", "@media print"); + }, + screenVariants: ({ theme: r, addVariant: e, matchVariant: t }) => { + let i = r("screens") ?? {}, + n = Object.values(i).every((w) => typeof w == "string"), + a = ot(r("screens")), + s = new Set([]); + function o(w) { + return w.match(/(\D+)$/)?.[1] ?? "(none)"; + } + function u(w) { + w !== void 0 && s.add(o(w)); + } + function c(w) { + return (u(w), s.size === 1); + } + for (let w of a) for (let k of w.values) (u(k.min), u(k.max)); + let f = s.size <= 1; + function d(w) { + return Object.fromEntries( + a + .filter((k) => gn(k).result) + .map((k) => { + let { min: S, max: _ } = k.values[0]; + if (w === "min" && S !== void 0) return k; + if (w === "min" && _ !== void 0) return { ...k, not: !k.not }; + if (w === "max" && _ !== void 0) return k; + if (w === "max" && S !== void 0) return { ...k, not: !k.not }; + }) + .map((k) => [k.name, k]) + ); + } + function p(w) { + return (k, S) => vd(w, k.value, S.value); + } + let m = p("max"), + b = p("min"); + function x(w) { + return (k) => { + if (n) + if (f) { + if (typeof k == "string" && !c(k)) + return ( + F.warn("minmax-have-mixed-units", [ + "The `min-*` and `max-*` variants are not supported with a `screens` configuration containing mixed units.", + ]), + [] + ); + } else + return ( + F.warn("mixed-screen-units", [ + "The `min-*` and `max-*` variants are not supported with a `screens` configuration containing mixed units.", + ]), + [] + ); + else + return ( + F.warn("complex-screen-config", [ + "The `min-*` and `max-*` variants are not supported with a `screens` configuration containing objects.", + ]), + [] + ); + return [`@media ${at(yn(k, w))}`]; + }; + } + t("max", x("max"), { sort: m, values: n ? d("max") : {} }); + let y = "min-screens"; + for (let w of a) e(w.name, `@media ${at(w)}`, { id: y, sort: n && f ? b : void 0, value: w }); + t("min", x("min"), { id: y, sort: b }); + }, + supportsVariants: ({ matchVariant: r, theme: e }) => { + r( + "supports", + (t = "") => { + let i = L(t), + n = /^\w*\s*\(/.test(i); + return ( + (i = n ? i.replace(/\b(and|or|not)\b/g, " $1 ") : i), + n + ? `@supports ${i}` + : (i.includes(":") || (i = `${i}: var(--tw)`), + (i.startsWith("(") && i.endsWith(")")) || (i = `(${i})`), + `@supports ${i}`) + ); + }, + { values: e("supports") ?? {} } + ); + }, + hasVariants: ({ matchVariant: r }) => { + (r("has", (e) => `&:has(${L(e)})`, { values: {} }), + r( + "group-has", + (e, { modifier: t }) => + t ? `:merge(.group\\/${t}):has(${L(e)}) &` : `:merge(.group):has(${L(e)}) &`, + { values: {} } + ), + r( + "peer-has", + (e, { modifier: t }) => + t ? `:merge(.peer\\/${t}):has(${L(e)}) ~ &` : `:merge(.peer):has(${L(e)}) ~ &`, + { values: {} } + )); + }, + ariaVariants: ({ matchVariant: r, theme: e }) => { + (r("aria", (t) => `&[aria-${L(t)}]`, { values: e("aria") ?? {} }), + r( + "group-aria", + (t, { modifier: i }) => + i ? `:merge(.group\\/${i})[aria-${L(t)}] &` : `:merge(.group)[aria-${L(t)}] &`, + { values: e("aria") ?? {} } + ), + r( + "peer-aria", + (t, { modifier: i }) => + i ? `:merge(.peer\\/${i})[aria-${L(t)}] ~ &` : `:merge(.peer)[aria-${L(t)}] ~ &`, + { values: e("aria") ?? {} } + )); + }, + dataVariants: ({ matchVariant: r, theme: e }) => { + (r("data", (t) => `&[data-${L(t)}]`, { values: e("data") ?? {} }), + r( + "group-data", + (t, { modifier: i }) => + i ? `:merge(.group\\/${i})[data-${L(t)}] &` : `:merge(.group)[data-${L(t)}] &`, + { values: e("data") ?? {} } + ), + r( + "peer-data", + (t, { modifier: i }) => + i ? `:merge(.peer\\/${i})[data-${L(t)}] ~ &` : `:merge(.peer)[data-${L(t)}] ~ &`, + { values: e("data") ?? {} } + )); + }, + orientationVariants: ({ addVariant: r }) => { + (r("portrait", "@media (orientation: portrait)"), + r("landscape", "@media (orientation: landscape)")); + }, + prefersContrastVariants: ({ addVariant: r }) => { + (r("contrast-more", "@media (prefers-contrast: more)"), + r("contrast-less", "@media (prefers-contrast: less)")); + }, + forcedColorsVariants: ({ addVariant: r }) => { + r("forced-colors", "@media (forced-colors: active)"); + }, + }), + (Te = [ + "translate(var(--tw-translate-x), var(--tw-translate-y))", + "rotate(var(--tw-rotate))", + "skewX(var(--tw-skew-x))", + "skewY(var(--tw-skew-y))", + "scaleX(var(--tw-scale-x))", + "scaleY(var(--tw-scale-y))", + ].join(" ")), + (Be = [ + "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(" ")), + (Fe = [ + "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(" ")), + (Sd = { + preflight: ({ addBase: r }) => { + let e = j.parse( + `*,::after,::before{box-sizing:border-box;border-width:0;border-style:solid;border-color:theme('borderColor.DEFAULT', currentColor)}::after,::before{--tw-content:''}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:theme('fontFamily.sans', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:theme('fontFamily.sans[1].fontFeatureSettings', normal);font-variation-settings:theme('fontFamily.sans[1].fontVariationSettings', normal);-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:theme('fontFamily.mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:theme('fontFamily.mono[1].fontFeatureSettings', normal);font-variation-settings:theme('fontFamily.mono[1].fontVariationSettings', normal);font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:theme('colors.gray.4', #9ca3af)}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}` + ); + r([ + j.comment({ text: `! tailwindcss v${bd} | MIT License | https://tailwindcss.com` }), + ...e.nodes, + ]); + }, + container: (() => { + function r(t = []) { + return t.flatMap((i) => i.values.map((n) => n.min)).filter((i) => i !== void 0); + } + function e(t, i, n) { + if (typeof n == "undefined") return []; + if (!(typeof n == "object" && n !== null)) + return [{ screen: "DEFAULT", minWidth: 0, padding: n }]; + let a = []; + n.DEFAULT && a.push({ screen: "DEFAULT", minWidth: 0, padding: n.DEFAULT }); + for (let s of t) + for (let o of i) + for (let { min: u } of o.values) + u === s && a.push({ minWidth: s, padding: n[o.name] }); + return a; + } + return function ({ addComponents: t, theme: i }) { + let n = ot(i("container.screens", i("screens"))), + a = r(n), + s = e(a, n, i("container.padding")), + o = (c) => { + let f = s.find((d) => d.minWidth === c); + return f ? { paddingRight: f.padding, paddingLeft: f.padding } : {}; + }, + u = Array.from(new Set(a.slice().sort((c, f) => parseInt(c) - parseInt(f)))).map( + (c) => ({ + [`@media (min-width: ${c})`]: { ".container": { "max-width": c, ...o(c) } }, + }) + ); + t([ + { + ".container": Object.assign( + { width: "100%" }, + i("container.center", !1) ? { marginRight: "auto", marginLeft: "auto" } : {}, + o(0) + ), + }, + ...u, + ]); + }; + })(), + accessibility: ({ addUtilities: r }) => { + r({ + ".sr-only": { + position: "absolute", + width: "1px", + height: "1px", + padding: "0", + margin: "-1px", + overflow: "hidden", + clip: "rect(0, 0, 0, 0)", + whiteSpace: "nowrap", + borderWidth: "0", + }, + ".not-sr-only": { + position: "static", + width: "auto", + height: "auto", + padding: "0", + margin: "0", + overflow: "visible", + clip: "auto", + whiteSpace: "normal", + }, + }); + }, + pointerEvents: ({ addUtilities: r }) => { + r({ + ".pointer-events-none": { "pointer-events": "none" }, + ".pointer-events-auto": { "pointer-events": "auto" }, + }); + }, + visibility: ({ addUtilities: r }) => { + r({ + ".visible": { visibility: "visible" }, + ".invisible": { visibility: "hidden" }, + ".collapse": { visibility: "collapse" }, + }); + }, + position: ({ addUtilities: r }) => { + r({ + ".static": { position: "static" }, + ".fixed": { position: "fixed" }, + ".absolute": { position: "absolute" }, + ".relative": { position: "relative" }, + ".sticky": { position: "sticky" }, + }); + }, + inset: P( + "inset", + [ + ["inset", ["inset"]], + [ + ["inset-x", ["left", "right"]], + ["inset-y", ["top", "bottom"]], + ], + [ + ["start", ["inset-inline-start"]], + ["end", ["inset-inline-end"]], + ["top", ["top"]], + ["right", ["right"]], + ["bottom", ["bottom"]], + ["left", ["left"]], + ], + ], + { supportsNegativeValues: !0 } + ), + isolation: ({ addUtilities: r }) => { + r({ ".isolate": { isolation: "isolate" }, ".isolation-auto": { isolation: "auto" } }); + }, + zIndex: P("zIndex", [["z", ["zIndex"]]], { supportsNegativeValues: !0 }), + order: P("order", void 0, { supportsNegativeValues: !0 }), + gridColumn: P("gridColumn", [["col", ["gridColumn"]]]), + gridColumnStart: P("gridColumnStart", [["col-start", ["gridColumnStart"]]]), + gridColumnEnd: P("gridColumnEnd", [["col-end", ["gridColumnEnd"]]]), + gridRow: P("gridRow", [["row", ["gridRow"]]]), + gridRowStart: P("gridRowStart", [["row-start", ["gridRowStart"]]]), + gridRowEnd: P("gridRowEnd", [["row-end", ["gridRowEnd"]]]), + float: ({ addUtilities: r }) => { + r({ + ".float-start": { float: "inline-start" }, + ".float-end": { float: "inline-end" }, + ".float-right": { float: "right" }, + ".float-left": { float: "left" }, + ".float-none": { float: "none" }, + }); + }, + clear: ({ addUtilities: r }) => { + r({ + ".clear-start": { clear: "inline-start" }, + ".clear-end": { clear: "inline-end" }, + ".clear-left": { clear: "left" }, + ".clear-right": { clear: "right" }, + ".clear-both": { clear: "both" }, + ".clear-none": { clear: "none" }, + }); + }, + margin: P( + "margin", + [ + ["m", ["margin"]], + [ + ["mx", ["margin-left", "margin-right"]], + ["my", ["margin-top", "margin-bottom"]], + ], + [ + ["ms", ["margin-inline-start"]], + ["me", ["margin-inline-end"]], + ["mt", ["margin-top"]], + ["mr", ["margin-right"]], + ["mb", ["margin-bottom"]], + ["ml", ["margin-left"]], + ], + ], + { supportsNegativeValues: !0 } + ), + boxSizing: ({ addUtilities: r }) => { + r({ + ".box-border": { "box-sizing": "border-box" }, + ".box-content": { "box-sizing": "content-box" }, + }); + }, + lineClamp: ({ matchUtilities: r, addUtilities: e, theme: t }) => { + (r( + { + "line-clamp": (i) => ({ + overflow: "hidden", + display: "-webkit-box", + "-webkit-box-orient": "vertical", + "-webkit-line-clamp": `${i}`, + }), + }, + { values: t("lineClamp") } + ), + e({ + ".line-clamp-none": { + overflow: "visible", + display: "block", + "-webkit-box-orient": "horizontal", + "-webkit-line-clamp": "none", + }, + })); + }, + display: ({ addUtilities: r }) => { + r({ + ".block": { display: "block" }, + ".inline-block": { display: "inline-block" }, + ".inline": { display: "inline" }, + ".flex": { display: "flex" }, + ".inline-flex": { display: "inline-flex" }, + ".table": { display: "table" }, + ".inline-table": { display: "inline-table" }, + ".table-caption": { display: "table-caption" }, + ".table-cell": { display: "table-cell" }, + ".table-column": { display: "table-column" }, + ".table-column-group": { display: "table-column-group" }, + ".table-footer-group": { display: "table-footer-group" }, + ".table-header-group": { display: "table-header-group" }, + ".table-row-group": { display: "table-row-group" }, + ".table-row": { display: "table-row" }, + ".flow-root": { display: "flow-root" }, + ".grid": { display: "grid" }, + ".inline-grid": { display: "inline-grid" }, + ".contents": { display: "contents" }, + ".list-item": { display: "list-item" }, + ".hidden": { display: "none" }, + }); + }, + aspectRatio: P("aspectRatio", [["aspect", ["aspect-ratio"]]]), + size: P("size", [["size", ["width", "height"]]]), + height: P("height", [["h", ["height"]]]), + maxHeight: P("maxHeight", [["max-h", ["maxHeight"]]]), + minHeight: P("minHeight", [["min-h", ["minHeight"]]]), + width: P("width", [["w", ["width"]]]), + minWidth: P("minWidth", [["min-w", ["minWidth"]]]), + maxWidth: P("maxWidth", [["max-w", ["maxWidth"]]]), + flex: P("flex"), + flexShrink: P("flexShrink", [ + ["flex-shrink", ["flex-shrink"]], + ["shrink", ["flex-shrink"]], + ]), + flexGrow: P("flexGrow", [ + ["flex-grow", ["flex-grow"]], + ["grow", ["flex-grow"]], + ]), + flexBasis: P("flexBasis", [["basis", ["flex-basis"]]]), + tableLayout: ({ addUtilities: r }) => { + r({ ".table-auto": { "table-layout": "auto" }, ".table-fixed": { "table-layout": "fixed" } }); + }, + captionSide: ({ addUtilities: r }) => { + r({ + ".caption-top": { "caption-side": "top" }, + ".caption-bottom": { "caption-side": "bottom" }, + }); + }, + borderCollapse: ({ addUtilities: r }) => { + r({ + ".border-collapse": { "border-collapse": "collapse" }, + ".border-separate": { "border-collapse": "separate" }, + }); + }, + borderSpacing: ({ addDefaults: r, matchUtilities: e, theme: t }) => { + (r("border-spacing", { "--tw-border-spacing-x": 0, "--tw-border-spacing-y": 0 }), + e( + { + "border-spacing": (i) => ({ + "--tw-border-spacing-x": i, + "--tw-border-spacing-y": i, + "@defaults border-spacing": {}, + "border-spacing": "var(--tw-border-spacing-x) var(--tw-border-spacing-y)", + }), + "border-spacing-x": (i) => ({ + "--tw-border-spacing-x": i, + "@defaults border-spacing": {}, + "border-spacing": "var(--tw-border-spacing-x) var(--tw-border-spacing-y)", + }), + "border-spacing-y": (i) => ({ + "--tw-border-spacing-y": i, + "@defaults border-spacing": {}, + "border-spacing": "var(--tw-border-spacing-x) var(--tw-border-spacing-y)", + }), + }, + { values: t("borderSpacing") } + )); + }, + transformOrigin: P("transformOrigin", [["origin", ["transformOrigin"]]]), + translate: P( + "translate", + [ + [ + ["translate-x", [["@defaults transform", {}], "--tw-translate-x", ["transform", Te]]], + ["translate-y", [["@defaults transform", {}], "--tw-translate-y", ["transform", Te]]], + ], + ], + { supportsNegativeValues: !0 } + ), + rotate: P("rotate", [["rotate", [["@defaults transform", {}], "--tw-rotate", ["transform", Te]]]], { + supportsNegativeValues: !0, + }), + skew: P( + "skew", + [ + [ + ["skew-x", [["@defaults transform", {}], "--tw-skew-x", ["transform", Te]]], + ["skew-y", [["@defaults transform", {}], "--tw-skew-y", ["transform", Te]]], + ], + ], + { supportsNegativeValues: !0 } + ), + scale: P( + "scale", + [ + ["scale", [["@defaults transform", {}], "--tw-scale-x", "--tw-scale-y", ["transform", Te]]], + [ + ["scale-x", [["@defaults transform", {}], "--tw-scale-x", ["transform", Te]]], + ["scale-y", [["@defaults transform", {}], "--tw-scale-y", ["transform", Te]]], + ], + ], + { supportsNegativeValues: !0 } + ), + transform: ({ addDefaults: r, addUtilities: e }) => { + (r("transform", { + "--tw-translate-x": "0", + "--tw-translate-y": "0", + "--tw-rotate": "0", + "--tw-skew-x": "0", + "--tw-skew-y": "0", + "--tw-scale-x": "1", + "--tw-scale-y": "1", + }), + e({ + ".transform": { "@defaults transform": {}, transform: Te }, + ".transform-cpu": { transform: Te }, + ".transform-gpu": { + transform: Te.replace( + "translate(var(--tw-translate-x), var(--tw-translate-y))", + "translate3d(var(--tw-translate-x), var(--tw-translate-y), 0)" + ), + }, + ".transform-none": { transform: "none" }, + })); + }, + animation: ({ matchUtilities: r, theme: e, config: t }) => { + let i = (a) => ce(t("prefix") + a), + n = Object.fromEntries( + Object.entries(e("keyframes") ?? {}).map(([a, s]) => [a, { [`@keyframes ${i(a)}`]: s }]) + ); + r( + { + animate: (a) => { + let s = Ka(a); + return [ + ...s.flatMap((o) => n[o.name]), + { + animation: s + .map(({ name: o, value: u }) => + o === void 0 || n[o] === void 0 ? u : u.replace(o, i(o)) + ) + .join(", "), + }, + ]; + }, + }, + { values: e("animation") } + ); + }, + cursor: P("cursor"), + touchAction: ({ addDefaults: r, addUtilities: e }) => { + r("touch-action", { "--tw-pan-x": " ", "--tw-pan-y": " ", "--tw-pinch-zoom": " " }); + let t = "var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)"; + e({ + ".touch-auto": { "touch-action": "auto" }, + ".touch-none": { "touch-action": "none" }, + ".touch-pan-x": { "@defaults touch-action": {}, "--tw-pan-x": "pan-x", "touch-action": t }, + ".touch-pan-left": { + "@defaults touch-action": {}, + "--tw-pan-x": "pan-left", + "touch-action": t, + }, + ".touch-pan-right": { + "@defaults touch-action": {}, + "--tw-pan-x": "pan-right", + "touch-action": t, + }, + ".touch-pan-y": { "@defaults touch-action": {}, "--tw-pan-y": "pan-y", "touch-action": t }, + ".touch-pan-up": { + "@defaults touch-action": {}, + "--tw-pan-y": "pan-up", + "touch-action": t, + }, + ".touch-pan-down": { + "@defaults touch-action": {}, + "--tw-pan-y": "pan-down", + "touch-action": t, + }, + ".touch-pinch-zoom": { + "@defaults touch-action": {}, + "--tw-pinch-zoom": "pinch-zoom", + "touch-action": t, + }, + ".touch-manipulation": { "touch-action": "manipulation" }, + }); + }, + userSelect: ({ addUtilities: r }) => { + r({ + ".select-none": { "user-select": "none" }, + ".select-text": { "user-select": "text" }, + ".select-all": { "user-select": "all" }, + ".select-auto": { "user-select": "auto" }, + }); + }, + resize: ({ addUtilities: r }) => { + r({ + ".resize-none": { resize: "none" }, + ".resize-y": { resize: "vertical" }, + ".resize-x": { resize: "horizontal" }, + ".resize": { resize: "both" }, + }); + }, + scrollSnapType: ({ addDefaults: r, addUtilities: e }) => { + (r("scroll-snap-type", { "--tw-scroll-snap-strictness": "proximity" }), + e({ + ".snap-none": { "scroll-snap-type": "none" }, + ".snap-x": { + "@defaults scroll-snap-type": {}, + "scroll-snap-type": "x var(--tw-scroll-snap-strictness)", + }, + ".snap-y": { + "@defaults scroll-snap-type": {}, + "scroll-snap-type": "y var(--tw-scroll-snap-strictness)", + }, + ".snap-both": { + "@defaults scroll-snap-type": {}, + "scroll-snap-type": "both var(--tw-scroll-snap-strictness)", + }, + ".snap-mandatory": { "--tw-scroll-snap-strictness": "mandatory" }, + ".snap-proximity": { "--tw-scroll-snap-strictness": "proximity" }, + })); + }, + scrollSnapAlign: ({ addUtilities: r }) => { + r({ + ".snap-start": { "scroll-snap-align": "start" }, + ".snap-end": { "scroll-snap-align": "end" }, + ".snap-center": { "scroll-snap-align": "center" }, + ".snap-align-none": { "scroll-snap-align": "none" }, + }); + }, + scrollSnapStop: ({ addUtilities: r }) => { + r({ + ".snap-normal": { "scroll-snap-stop": "normal" }, + ".snap-always": { "scroll-snap-stop": "always" }, + }); + }, + scrollMargin: P( + "scrollMargin", + [ + ["scroll-m", ["scroll-margin"]], + [ + ["scroll-mx", ["scroll-margin-left", "scroll-margin-right"]], + ["scroll-my", ["scroll-margin-top", "scroll-margin-bottom"]], + ], + [ + ["scroll-ms", ["scroll-margin-inline-start"]], + ["scroll-me", ["scroll-margin-inline-end"]], + ["scroll-mt", ["scroll-margin-top"]], + ["scroll-mr", ["scroll-margin-right"]], + ["scroll-mb", ["scroll-margin-bottom"]], + ["scroll-ml", ["scroll-margin-left"]], + ], + ], + { supportsNegativeValues: !0 } + ), + scrollPadding: P("scrollPadding", [ + ["scroll-p", ["scroll-padding"]], + [ + ["scroll-px", ["scroll-padding-left", "scroll-padding-right"]], + ["scroll-py", ["scroll-padding-top", "scroll-padding-bottom"]], + ], + [ + ["scroll-ps", ["scroll-padding-inline-start"]], + ["scroll-pe", ["scroll-padding-inline-end"]], + ["scroll-pt", ["scroll-padding-top"]], + ["scroll-pr", ["scroll-padding-right"]], + ["scroll-pb", ["scroll-padding-bottom"]], + ["scroll-pl", ["scroll-padding-left"]], + ], + ]), + listStylePosition: ({ addUtilities: r }) => { + r({ + ".list-inside": { "list-style-position": "inside" }, + ".list-outside": { "list-style-position": "outside" }, + }); + }, + listStyleType: P("listStyleType", [["list", ["listStyleType"]]]), + listStyleImage: P("listStyleImage", [["list-image", ["listStyleImage"]]]), + appearance: ({ addUtilities: r }) => { + r({ ".appearance-none": { appearance: "none" }, ".appearance-auto": { appearance: "auto" } }); + }, + columns: P("columns", [["columns", ["columns"]]]), + breakBefore: ({ addUtilities: r }) => { + r({ + ".break-before-auto": { "break-before": "auto" }, + ".break-before-avoid": { "break-before": "avoid" }, + ".break-before-all": { "break-before": "all" }, + ".break-before-avoid-page": { "break-before": "avoid-page" }, + ".break-before-page": { "break-before": "page" }, + ".break-before-left": { "break-before": "left" }, + ".break-before-right": { "break-before": "right" }, + ".break-before-column": { "break-before": "column" }, + }); + }, + breakInside: ({ addUtilities: r }) => { + r({ + ".break-inside-auto": { "break-inside": "auto" }, + ".break-inside-avoid": { "break-inside": "avoid" }, + ".break-inside-avoid-page": { "break-inside": "avoid-page" }, + ".break-inside-avoid-column": { "break-inside": "avoid-column" }, + }); + }, + breakAfter: ({ addUtilities: r }) => { + r({ + ".break-after-auto": { "break-after": "auto" }, + ".break-after-avoid": { "break-after": "avoid" }, + ".break-after-all": { "break-after": "all" }, + ".break-after-avoid-page": { "break-after": "avoid-page" }, + ".break-after-page": { "break-after": "page" }, + ".break-after-left": { "break-after": "left" }, + ".break-after-right": { "break-after": "right" }, + ".break-after-column": { "break-after": "column" }, + }); + }, + gridAutoColumns: P("gridAutoColumns", [["auto-cols", ["gridAutoColumns"]]]), + gridAutoFlow: ({ addUtilities: r }) => { + r({ + ".grid-flow-row": { gridAutoFlow: "row" }, + ".grid-flow-col": { gridAutoFlow: "column" }, + ".grid-flow-dense": { gridAutoFlow: "dense" }, + ".grid-flow-row-dense": { gridAutoFlow: "row dense" }, + ".grid-flow-col-dense": { gridAutoFlow: "column dense" }, + }); + }, + gridAutoRows: P("gridAutoRows", [["auto-rows", ["gridAutoRows"]]]), + gridTemplateColumns: P("gridTemplateColumns", [["grid-cols", ["gridTemplateColumns"]]]), + gridTemplateRows: P("gridTemplateRows", [["grid-rows", ["gridTemplateRows"]]]), + flexDirection: ({ addUtilities: r }) => { + r({ + ".flex-row": { "flex-direction": "row" }, + ".flex-row-reverse": { "flex-direction": "row-reverse" }, + ".flex-col": { "flex-direction": "column" }, + ".flex-col-reverse": { "flex-direction": "column-reverse" }, + }); + }, + flexWrap: ({ addUtilities: r }) => { + r({ + ".flex-wrap": { "flex-wrap": "wrap" }, + ".flex-wrap-reverse": { "flex-wrap": "wrap-reverse" }, + ".flex-nowrap": { "flex-wrap": "nowrap" }, + }); + }, + placeContent: ({ addUtilities: r }) => { + r({ + ".place-content-center": { "place-content": "center" }, + ".place-content-start": { "place-content": "start" }, + ".place-content-end": { "place-content": "end" }, + ".place-content-between": { "place-content": "space-between" }, + ".place-content-around": { "place-content": "space-around" }, + ".place-content-evenly": { "place-content": "space-evenly" }, + ".place-content-baseline": { "place-content": "baseline" }, + ".place-content-stretch": { "place-content": "stretch" }, + }); + }, + placeItems: ({ addUtilities: r }) => { + r({ + ".place-items-start": { "place-items": "start" }, + ".place-items-end": { "place-items": "end" }, + ".place-items-center": { "place-items": "center" }, + ".place-items-baseline": { "place-items": "baseline" }, + ".place-items-stretch": { "place-items": "stretch" }, + }); + }, + alignContent: ({ addUtilities: r }) => { + r({ + ".content-normal": { "align-content": "normal" }, + ".content-center": { "align-content": "center" }, + ".content-start": { "align-content": "flex-start" }, + ".content-end": { "align-content": "flex-end" }, + ".content-between": { "align-content": "space-between" }, + ".content-around": { "align-content": "space-around" }, + ".content-evenly": { "align-content": "space-evenly" }, + ".content-baseline": { "align-content": "baseline" }, + ".content-stretch": { "align-content": "stretch" }, + }); + }, + alignItems: ({ addUtilities: r }) => { + r({ + ".items-start": { "align-items": "flex-start" }, + ".items-end": { "align-items": "flex-end" }, + ".items-center": { "align-items": "center" }, + ".items-baseline": { "align-items": "baseline" }, + ".items-stretch": { "align-items": "stretch" }, + }); + }, + justifyContent: ({ addUtilities: r }) => { + r({ + ".justify-normal": { "justify-content": "normal" }, + ".justify-start": { "justify-content": "flex-start" }, + ".justify-end": { "justify-content": "flex-end" }, + ".justify-center": { "justify-content": "center" }, + ".justify-between": { "justify-content": "space-between" }, + ".justify-around": { "justify-content": "space-around" }, + ".justify-evenly": { "justify-content": "space-evenly" }, + ".justify-stretch": { "justify-content": "stretch" }, + }); + }, + justifyItems: ({ addUtilities: r }) => { + r({ + ".justify-items-start": { "justify-items": "start" }, + ".justify-items-end": { "justify-items": "end" }, + ".justify-items-center": { "justify-items": "center" }, + ".justify-items-stretch": { "justify-items": "stretch" }, + }); + }, + gap: P("gap", [ + ["gap", ["gap"]], + [ + ["gap-x", ["columnGap"]], + ["gap-y", ["rowGap"]], + ], + ]), + space: ({ matchUtilities: r, addUtilities: e, theme: t }) => { + (r( + { + "space-x": (i) => ( + (i = i === "0" ? "0px" : i), + { + "& > :not([hidden]) ~ :not([hidden])": { + "--tw-space-x-reverse": "0", + "margin-right": `calc(${i} * var(--tw-space-x-reverse))`, + "margin-left": `calc(${i} * calc(1 - var(--tw-space-x-reverse)))`, + }, + } + ), + "space-y": (i) => ( + (i = i === "0" ? "0px" : i), + { + "& > :not([hidden]) ~ :not([hidden])": { + "--tw-space-y-reverse": "0", + "margin-top": `calc(${i} * calc(1 - var(--tw-space-y-reverse)))`, + "margin-bottom": `calc(${i} * var(--tw-space-y-reverse))`, + }, + } + ), + }, + { values: t("space"), supportsNegativeValues: !0 } + ), + e({ + ".space-y-reverse > :not([hidden]) ~ :not([hidden])": { "--tw-space-y-reverse": "1" }, + ".space-x-reverse > :not([hidden]) ~ :not([hidden])": { "--tw-space-x-reverse": "1" }, + })); + }, + divideWidth: ({ matchUtilities: r, addUtilities: e, theme: t }) => { + (r( + { + "divide-x": (i) => ( + (i = i === "0" ? "0px" : i), + { + "& > :not([hidden]) ~ :not([hidden])": { + "@defaults border-width": {}, + "--tw-divide-x-reverse": "0", + "border-right-width": `calc(${i} * var(--tw-divide-x-reverse))`, + "border-left-width": `calc(${i} * calc(1 - var(--tw-divide-x-reverse)))`, + }, + } + ), + "divide-y": (i) => ( + (i = i === "0" ? "0px" : i), + { + "& > :not([hidden]) ~ :not([hidden])": { + "@defaults border-width": {}, + "--tw-divide-y-reverse": "0", + "border-top-width": `calc(${i} * calc(1 - var(--tw-divide-y-reverse)))`, + "border-bottom-width": `calc(${i} * var(--tw-divide-y-reverse))`, + }, + } + ), + }, + { values: t("divideWidth"), type: ["line-width", "length", "any"] } + ), + e({ + ".divide-y-reverse > :not([hidden]) ~ :not([hidden])": { + "@defaults border-width": {}, + "--tw-divide-y-reverse": "1", + }, + ".divide-x-reverse > :not([hidden]) ~ :not([hidden])": { + "@defaults border-width": {}, + "--tw-divide-x-reverse": "1", + }, + })); + }, + divideStyle: ({ addUtilities: r }) => { + r({ + ".divide-solid > :not([hidden]) ~ :not([hidden])": { "border-style": "solid" }, + ".divide-dashed > :not([hidden]) ~ :not([hidden])": { "border-style": "dashed" }, + ".divide-dotted > :not([hidden]) ~ :not([hidden])": { "border-style": "dotted" }, + ".divide-double > :not([hidden]) ~ :not([hidden])": { "border-style": "double" }, + ".divide-none > :not([hidden]) ~ :not([hidden])": { "border-style": "none" }, + }); + }, + divideColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + r( + { + divide: (i) => + t("divideOpacity") + ? { + ["& > :not([hidden]) ~ :not([hidden])"]: se({ + color: i, + property: "border-color", + variable: "--tw-divide-opacity", + }), + } + : { ["& > :not([hidden]) ~ :not([hidden])"]: { "border-color": N(i) } }, + }, + { values: (({ DEFAULT: i, ...n }) => n)(re(e("divideColor"))), type: ["color", "any"] } + ); + }, + divideOpacity: ({ matchUtilities: r, theme: e }) => { + r( + { + "divide-opacity": (t) => ({ + ["& > :not([hidden]) ~ :not([hidden])"]: { "--tw-divide-opacity": t }, + }), + }, + { values: e("divideOpacity") } + ); + }, + placeSelf: ({ addUtilities: r }) => { + r({ + ".place-self-auto": { "place-self": "auto" }, + ".place-self-start": { "place-self": "start" }, + ".place-self-end": { "place-self": "end" }, + ".place-self-center": { "place-self": "center" }, + ".place-self-stretch": { "place-self": "stretch" }, + }); + }, + alignSelf: ({ addUtilities: r }) => { + r({ + ".self-auto": { "align-self": "auto" }, + ".self-start": { "align-self": "flex-start" }, + ".self-end": { "align-self": "flex-end" }, + ".self-center": { "align-self": "center" }, + ".self-stretch": { "align-self": "stretch" }, + ".self-baseline": { "align-self": "baseline" }, + }); + }, + justifySelf: ({ addUtilities: r }) => { + r({ + ".justify-self-auto": { "justify-self": "auto" }, + ".justify-self-start": { "justify-self": "start" }, + ".justify-self-end": { "justify-self": "end" }, + ".justify-self-center": { "justify-self": "center" }, + ".justify-self-stretch": { "justify-self": "stretch" }, + }); + }, + overflow: ({ addUtilities: r }) => { + r({ + ".overflow-auto": { overflow: "auto" }, + ".overflow-hidden": { overflow: "hidden" }, + ".overflow-clip": { overflow: "clip" }, + ".overflow-visible": { overflow: "visible" }, + ".overflow-scroll": { overflow: "scroll" }, + ".overflow-x-auto": { "overflow-x": "auto" }, + ".overflow-y-auto": { "overflow-y": "auto" }, + ".overflow-x-hidden": { "overflow-x": "hidden" }, + ".overflow-y-hidden": { "overflow-y": "hidden" }, + ".overflow-x-clip": { "overflow-x": "clip" }, + ".overflow-y-clip": { "overflow-y": "clip" }, + ".overflow-x-visible": { "overflow-x": "visible" }, + ".overflow-y-visible": { "overflow-y": "visible" }, + ".overflow-x-scroll": { "overflow-x": "scroll" }, + ".overflow-y-scroll": { "overflow-y": "scroll" }, + }); + }, + overscrollBehavior: ({ addUtilities: r }) => { + r({ + ".overscroll-auto": { "overscroll-behavior": "auto" }, + ".overscroll-contain": { "overscroll-behavior": "contain" }, + ".overscroll-none": { "overscroll-behavior": "none" }, + ".overscroll-y-auto": { "overscroll-behavior-y": "auto" }, + ".overscroll-y-contain": { "overscroll-behavior-y": "contain" }, + ".overscroll-y-none": { "overscroll-behavior-y": "none" }, + ".overscroll-x-auto": { "overscroll-behavior-x": "auto" }, + ".overscroll-x-contain": { "overscroll-behavior-x": "contain" }, + ".overscroll-x-none": { "overscroll-behavior-x": "none" }, + }); + }, + scrollBehavior: ({ addUtilities: r }) => { + r({ + ".scroll-auto": { "scroll-behavior": "auto" }, + ".scroll-smooth": { "scroll-behavior": "smooth" }, + }); + }, + textOverflow: ({ addUtilities: r }) => { + r({ + ".truncate": { overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }, + ".overflow-ellipsis": { "text-overflow": "ellipsis" }, + ".text-ellipsis": { "text-overflow": "ellipsis" }, + ".text-clip": { "text-overflow": "clip" }, + }); + }, + hyphens: ({ addUtilities: r }) => { + r({ + ".hyphens-none": { hyphens: "none" }, + ".hyphens-manual": { hyphens: "manual" }, + ".hyphens-auto": { hyphens: "auto" }, + }); + }, + whitespace: ({ addUtilities: r }) => { + r({ + ".whitespace-normal": { "white-space": "normal" }, + ".whitespace-nowrap": { "white-space": "nowrap" }, + ".whitespace-pre": { "white-space": "pre" }, + ".whitespace-pre-line": { "white-space": "pre-line" }, + ".whitespace-pre-wrap": { "white-space": "pre-wrap" }, + ".whitespace-break-spaces": { "white-space": "break-spaces" }, + }); + }, + textWrap: ({ addUtilities: r }) => { + r({ + ".text-wrap": { "text-wrap": "wrap" }, + ".text-nowrap": { "text-wrap": "nowrap" }, + ".text-balance": { "text-wrap": "balance" }, + ".text-pretty": { "text-wrap": "pretty" }, + }); + }, + wordBreak: ({ addUtilities: r }) => { + r({ + ".break-normal": { "overflow-wrap": "normal", "word-break": "normal" }, + ".break-words": { "overflow-wrap": "break-word" }, + ".break-all": { "word-break": "break-all" }, + ".break-keep": { "word-break": "keep-all" }, + }); + }, + borderRadius: P("borderRadius", [ + ["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"]], + ], + ]), + borderWidth: P( + "borderWidth", + [ + ["border", [["@defaults border-width", {}], "border-width"]], + [ + [ + "border-x", + [["@defaults border-width", {}], "border-left-width", "border-right-width"], + ], + [ + "border-y", + [["@defaults border-width", {}], "border-top-width", "border-bottom-width"], + ], + ], + [ + ["border-s", [["@defaults border-width", {}], "border-inline-start-width"]], + ["border-e", [["@defaults border-width", {}], "border-inline-end-width"]], + ["border-t", [["@defaults border-width", {}], "border-top-width"]], + ["border-r", [["@defaults border-width", {}], "border-right-width"]], + ["border-b", [["@defaults border-width", {}], "border-bottom-width"]], + ["border-l", [["@defaults border-width", {}], "border-left-width"]], + ], + ], + { type: ["line-width", "length"] } + ), + borderStyle: ({ addUtilities: r }) => { + r({ + ".border-solid": { "border-style": "solid" }, + ".border-dashed": { "border-style": "dashed" }, + ".border-dotted": { "border-style": "dotted" }, + ".border-double": { "border-style": "double" }, + ".border-hidden": { "border-style": "hidden" }, + ".border-none": { "border-style": "none" }, + }); + }, + borderColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + (r( + { + border: (i) => + t("borderOpacity") + ? se({ color: i, property: "border-color", variable: "--tw-border-opacity" }) + : { "border-color": N(i) }, + }, + { values: (({ DEFAULT: i, ...n }) => n)(re(e("borderColor"))), type: ["color", "any"] } + ), + r( + { + "border-x": (i) => + t("borderOpacity") + ? se({ + color: i, + property: ["border-left-color", "border-right-color"], + variable: "--tw-border-opacity", + }) + : { "border-left-color": N(i), "border-right-color": N(i) }, + "border-y": (i) => + t("borderOpacity") + ? se({ + color: i, + property: ["border-top-color", "border-bottom-color"], + variable: "--tw-border-opacity", + }) + : { "border-top-color": N(i), "border-bottom-color": N(i) }, + }, + { values: (({ DEFAULT: i, ...n }) => n)(re(e("borderColor"))), type: ["color", "any"] } + ), + r( + { + "border-s": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-inline-start-color", + variable: "--tw-border-opacity", + }) + : { "border-inline-start-color": N(i) }, + "border-e": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-inline-end-color", + variable: "--tw-border-opacity", + }) + : { "border-inline-end-color": N(i) }, + "border-t": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-top-color", + variable: "--tw-border-opacity", + }) + : { "border-top-color": N(i) }, + "border-r": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-right-color", + variable: "--tw-border-opacity", + }) + : { "border-right-color": N(i) }, + "border-b": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-bottom-color", + variable: "--tw-border-opacity", + }) + : { "border-bottom-color": N(i) }, + "border-l": (i) => + t("borderOpacity") + ? se({ + color: i, + property: "border-left-color", + variable: "--tw-border-opacity", + }) + : { "border-left-color": N(i) }, + }, + { values: (({ DEFAULT: i, ...n }) => n)(re(e("borderColor"))), type: ["color", "any"] } + )); + }, + borderOpacity: P("borderOpacity", [["border-opacity", ["--tw-border-opacity"]]]), + backgroundColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + r( + { + bg: (i) => + t("backgroundOpacity") + ? se({ color: i, property: "background-color", variable: "--tw-bg-opacity" }) + : { "background-color": N(i) }, + }, + { values: re(e("backgroundColor")), type: ["color", "any"] } + ); + }, + backgroundOpacity: P("backgroundOpacity", [["bg-opacity", ["--tw-bg-opacity"]]]), + backgroundImage: P("backgroundImage", [["bg", ["background-image"]]], { + type: ["lookup", "image", "url"], + }), + gradientColorStops: (() => { + function r(e) { + return Ie(e, 0, "rgb(255 255 255 / 0)"); + } + return function ({ matchUtilities: e, theme: t, addDefaults: i }) { + i("gradient-color-stops", { + "--tw-gradient-from-position": " ", + "--tw-gradient-via-position": " ", + "--tw-gradient-to-position": " ", + }); + let n = { values: re(t("gradientColorStops")), type: ["color", "any"] }, + a = { values: t("gradientColorStopPositions"), type: ["length", "percentage"] }; + (e( + { + from: (s) => { + let o = r(s); + return { + "@defaults gradient-color-stops": {}, + "--tw-gradient-from": `${N(s)} var(--tw-gradient-from-position)`, + "--tw-gradient-to": `${o} var(--tw-gradient-to-position)`, + "--tw-gradient-stops": "var(--tw-gradient-from), var(--tw-gradient-to)", + }; + }, + }, + n + ), + e({ from: (s) => ({ "--tw-gradient-from-position": s }) }, a), + e( + { + via: (s) => { + let o = r(s); + return { + "@defaults gradient-color-stops": {}, + "--tw-gradient-to": `${o} var(--tw-gradient-to-position)`, + "--tw-gradient-stops": `var(--tw-gradient-from), ${N(s)} var(--tw-gradient-via-position), var(--tw-gradient-to)`, + }; + }, + }, + n + ), + e({ via: (s) => ({ "--tw-gradient-via-position": s }) }, a), + e( + { + to: (s) => ({ + "@defaults gradient-color-stops": {}, + "--tw-gradient-to": `${N(s)} var(--tw-gradient-to-position)`, + }), + }, + n + ), + e({ to: (s) => ({ "--tw-gradient-to-position": s }) }, a)); + }; + })(), + boxDecorationBreak: ({ addUtilities: r }) => { + r({ + ".decoration-slice": { "box-decoration-break": "slice" }, + ".decoration-clone": { "box-decoration-break": "clone" }, + ".box-decoration-slice": { "box-decoration-break": "slice" }, + ".box-decoration-clone": { "box-decoration-break": "clone" }, + }); + }, + backgroundSize: P("backgroundSize", [["bg", ["background-size"]]], { + type: ["lookup", "length", "percentage", "size"], + }), + backgroundAttachment: ({ addUtilities: r }) => { + r({ + ".bg-fixed": { "background-attachment": "fixed" }, + ".bg-local": { "background-attachment": "local" }, + ".bg-scroll": { "background-attachment": "scroll" }, + }); + }, + backgroundClip: ({ addUtilities: r }) => { + r({ + ".bg-clip-border": { "background-clip": "border-box" }, + ".bg-clip-padding": { "background-clip": "padding-box" }, + ".bg-clip-content": { "background-clip": "content-box" }, + ".bg-clip-text": { "background-clip": "text" }, + }); + }, + backgroundPosition: P("backgroundPosition", [["bg", ["background-position"]]], { + type: ["lookup", ["position", { preferOnConflict: !0 }]], + }), + backgroundRepeat: ({ addUtilities: r }) => { + r({ + ".bg-repeat": { "background-repeat": "repeat" }, + ".bg-no-repeat": { "background-repeat": "no-repeat" }, + ".bg-repeat-x": { "background-repeat": "repeat-x" }, + ".bg-repeat-y": { "background-repeat": "repeat-y" }, + ".bg-repeat-round": { "background-repeat": "round" }, + ".bg-repeat-space": { "background-repeat": "space" }, + }); + }, + backgroundOrigin: ({ addUtilities: r }) => { + r({ + ".bg-origin-border": { "background-origin": "border-box" }, + ".bg-origin-padding": { "background-origin": "padding-box" }, + ".bg-origin-content": { "background-origin": "content-box" }, + }); + }, + fill: ({ matchUtilities: r, theme: e }) => { + r({ fill: (t) => ({ fill: N(t) }) }, { values: re(e("fill")), type: ["color", "any"] }); + }, + stroke: ({ matchUtilities: r, theme: e }) => { + r( + { stroke: (t) => ({ stroke: N(t) }) }, + { values: re(e("stroke")), type: ["color", "url", "any"] } + ); + }, + strokeWidth: P("strokeWidth", [["stroke", ["stroke-width"]]], { + type: ["length", "number", "percentage"], + }), + objectFit: ({ addUtilities: r }) => { + r({ + ".object-contain": { "object-fit": "contain" }, + ".object-cover": { "object-fit": "cover" }, + ".object-fill": { "object-fit": "fill" }, + ".object-none": { "object-fit": "none" }, + ".object-scale-down": { "object-fit": "scale-down" }, + }); + }, + objectPosition: P("objectPosition", [["object", ["object-position"]]]), + padding: P("padding", [ + ["p", ["padding"]], + [ + ["px", ["padding-left", "padding-right"]], + ["py", ["padding-top", "padding-bottom"]], + ], + [ + ["ps", ["padding-inline-start"]], + ["pe", ["padding-inline-end"]], + ["pt", ["padding-top"]], + ["pr", ["padding-right"]], + ["pb", ["padding-bottom"]], + ["pl", ["padding-left"]], + ], + ]), + textAlign: ({ addUtilities: r }) => { + r({ + ".text-left": { "text-align": "left" }, + ".text-center": { "text-align": "center" }, + ".text-right": { "text-align": "right" }, + ".text-justify": { "text-align": "justify" }, + ".text-start": { "text-align": "start" }, + ".text-end": { "text-align": "end" }, + }); + }, + textIndent: P("textIndent", [["indent", ["text-indent"]]], { supportsNegativeValues: !0 }), + verticalAlign: ({ addUtilities: r, matchUtilities: e }) => { + (r({ + ".align-baseline": { "vertical-align": "baseline" }, + ".align-top": { "vertical-align": "top" }, + ".align-middle": { "vertical-align": "middle" }, + ".align-bottom": { "vertical-align": "bottom" }, + ".align-text-top": { "vertical-align": "text-top" }, + ".align-text-bottom": { "vertical-align": "text-bottom" }, + ".align-sub": { "vertical-align": "sub" }, + ".align-super": { "vertical-align": "super" }, + }), + e({ align: (t) => ({ "vertical-align": t }) })); + }, + fontFamily: ({ matchUtilities: r, theme: e }) => { + r( + { + font: (t) => { + let [i, n = {}] = Array.isArray(t) && ie(t[1]) ? t : [t], + { fontFeatureSettings: a, fontVariationSettings: s } = n; + return { + "font-family": Array.isArray(i) ? i.join(", ") : i, + ...(a === void 0 ? {} : { "font-feature-settings": a }), + ...(s === void 0 ? {} : { "font-variation-settings": s }), + }; + }, + }, + { values: e("fontFamily"), type: ["lookup", "generic-name", "family-name"] } + ); + }, + fontSize: ({ matchUtilities: r, theme: e }) => { + r( + { + text: (t, { modifier: i }) => { + let [n, a] = Array.isArray(t) ? t : [t]; + if (i) return { "font-size": n, "line-height": i }; + let { + lineHeight: s, + letterSpacing: o, + fontWeight: u, + } = ie(a) ? a : { lineHeight: a }; + return { + "font-size": n, + ...(s === void 0 ? {} : { "line-height": s }), + ...(o === void 0 ? {} : { "letter-spacing": o }), + ...(u === void 0 ? {} : { "font-weight": u }), + }; + }, + }, + { + values: e("fontSize"), + modifiers: e("lineHeight"), + type: ["absolute-size", "relative-size", "length", "percentage"], + } + ); + }, + fontWeight: P("fontWeight", [["font", ["fontWeight"]]], { type: ["lookup", "number", "any"] }), + textTransform: ({ addUtilities: r }) => { + r({ + ".uppercase": { "text-transform": "uppercase" }, + ".lowercase": { "text-transform": "lowercase" }, + ".capitalize": { "text-transform": "capitalize" }, + ".normal-case": { "text-transform": "none" }, + }); + }, + fontStyle: ({ addUtilities: r }) => { + r({ ".italic": { "font-style": "italic" }, ".not-italic": { "font-style": "normal" } }); + }, + fontVariantNumeric: ({ addDefaults: r, addUtilities: e }) => { + let t = + "var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)"; + (r("font-variant-numeric", { + "--tw-ordinal": " ", + "--tw-slashed-zero": " ", + "--tw-numeric-figure": " ", + "--tw-numeric-spacing": " ", + "--tw-numeric-fraction": " ", + }), + e({ + ".normal-nums": { "font-variant-numeric": "normal" }, + ".ordinal": { + "@defaults font-variant-numeric": {}, + "--tw-ordinal": "ordinal", + "font-variant-numeric": t, + }, + ".slashed-zero": { + "@defaults font-variant-numeric": {}, + "--tw-slashed-zero": "slashed-zero", + "font-variant-numeric": t, + }, + ".lining-nums": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-figure": "lining-nums", + "font-variant-numeric": t, + }, + ".oldstyle-nums": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-figure": "oldstyle-nums", + "font-variant-numeric": t, + }, + ".proportional-nums": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-spacing": "proportional-nums", + "font-variant-numeric": t, + }, + ".tabular-nums": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-spacing": "tabular-nums", + "font-variant-numeric": t, + }, + ".diagonal-fractions": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-fraction": "diagonal-fractions", + "font-variant-numeric": t, + }, + ".stacked-fractions": { + "@defaults font-variant-numeric": {}, + "--tw-numeric-fraction": "stacked-fractions", + "font-variant-numeric": t, + }, + })); + }, + lineHeight: P("lineHeight", [["leading", ["lineHeight"]]]), + letterSpacing: P("letterSpacing", [["tracking", ["letterSpacing"]]], { + supportsNegativeValues: !0, + }), + textColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + r( + { + text: (i) => + t("textOpacity") + ? se({ color: i, property: "color", variable: "--tw-text-opacity" }) + : { color: N(i) }, + }, + { values: re(e("textColor")), type: ["color", "any"] } + ); + }, + textOpacity: P("textOpacity", [["text-opacity", ["--tw-text-opacity"]]]), + textDecoration: ({ addUtilities: r }) => { + r({ + ".underline": { "text-decoration-line": "underline" }, + ".overline": { "text-decoration-line": "overline" }, + ".line-through": { "text-decoration-line": "line-through" }, + ".no-underline": { "text-decoration-line": "none" }, + }); + }, + textDecorationColor: ({ matchUtilities: r, theme: e }) => { + r( + { decoration: (t) => ({ "text-decoration-color": N(t) }) }, + { values: re(e("textDecorationColor")), type: ["color", "any"] } + ); + }, + textDecorationStyle: ({ addUtilities: r }) => { + r({ + ".decoration-solid": { "text-decoration-style": "solid" }, + ".decoration-double": { "text-decoration-style": "double" }, + ".decoration-dotted": { "text-decoration-style": "dotted" }, + ".decoration-dashed": { "text-decoration-style": "dashed" }, + ".decoration-wavy": { "text-decoration-style": "wavy" }, + }); + }, + textDecorationThickness: P( + "textDecorationThickness", + [["decoration", ["text-decoration-thickness"]]], + { type: ["length", "percentage"] } + ), + textUnderlineOffset: P("textUnderlineOffset", [["underline-offset", ["text-underline-offset"]]], { + type: ["length", "percentage", "any"], + }), + fontSmoothing: ({ addUtilities: r }) => { + r({ + ".antialiased": { + "-webkit-font-smoothing": "antialiased", + "-moz-osx-font-smoothing": "grayscale", + }, + ".subpixel-antialiased": { + "-webkit-font-smoothing": "auto", + "-moz-osx-font-smoothing": "auto", + }, + }); + }, + placeholderColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + r( + { + placeholder: (i) => + t("placeholderOpacity") + ? { + "&::placeholder": se({ + color: i, + property: "color", + variable: "--tw-placeholder-opacity", + }), + } + : { "&::placeholder": { color: N(i) } }, + }, + { values: re(e("placeholderColor")), type: ["color", "any"] } + ); + }, + placeholderOpacity: ({ matchUtilities: r, theme: e }) => { + r( + { + "placeholder-opacity": (t) => ({ + ["&::placeholder"]: { "--tw-placeholder-opacity": t }, + }), + }, + { values: e("placeholderOpacity") } + ); + }, + caretColor: ({ matchUtilities: r, theme: e }) => { + r( + { caret: (t) => ({ "caret-color": N(t) }) }, + { values: re(e("caretColor")), type: ["color", "any"] } + ); + }, + accentColor: ({ matchUtilities: r, theme: e }) => { + r( + { accent: (t) => ({ "accent-color": N(t) }) }, + { values: re(e("accentColor")), type: ["color", "any"] } + ); + }, + opacity: P("opacity", [["opacity", ["opacity"]]]), + backgroundBlendMode: ({ addUtilities: r }) => { + r({ + ".bg-blend-normal": { "background-blend-mode": "normal" }, + ".bg-blend-multiply": { "background-blend-mode": "multiply" }, + ".bg-blend-screen": { "background-blend-mode": "screen" }, + ".bg-blend-overlay": { "background-blend-mode": "overlay" }, + ".bg-blend-darken": { "background-blend-mode": "darken" }, + ".bg-blend-lighten": { "background-blend-mode": "lighten" }, + ".bg-blend-color-dodge": { "background-blend-mode": "color-dodge" }, + ".bg-blend-color-burn": { "background-blend-mode": "color-burn" }, + ".bg-blend-hard-light": { "background-blend-mode": "hard-light" }, + ".bg-blend-soft-light": { "background-blend-mode": "soft-light" }, + ".bg-blend-difference": { "background-blend-mode": "difference" }, + ".bg-blend-exclusion": { "background-blend-mode": "exclusion" }, + ".bg-blend-hue": { "background-blend-mode": "hue" }, + ".bg-blend-saturation": { "background-blend-mode": "saturation" }, + ".bg-blend-color": { "background-blend-mode": "color" }, + ".bg-blend-luminosity": { "background-blend-mode": "luminosity" }, + }); + }, + mixBlendMode: ({ addUtilities: r }) => { + r({ + ".mix-blend-normal": { "mix-blend-mode": "normal" }, + ".mix-blend-multiply": { "mix-blend-mode": "multiply" }, + ".mix-blend-screen": { "mix-blend-mode": "screen" }, + ".mix-blend-overlay": { "mix-blend-mode": "overlay" }, + ".mix-blend-darken": { "mix-blend-mode": "darken" }, + ".mix-blend-lighten": { "mix-blend-mode": "lighten" }, + ".mix-blend-color-dodge": { "mix-blend-mode": "color-dodge" }, + ".mix-blend-color-burn": { "mix-blend-mode": "color-burn" }, + ".mix-blend-hard-light": { "mix-blend-mode": "hard-light" }, + ".mix-blend-soft-light": { "mix-blend-mode": "soft-light" }, + ".mix-blend-difference": { "mix-blend-mode": "difference" }, + ".mix-blend-exclusion": { "mix-blend-mode": "exclusion" }, + ".mix-blend-hue": { "mix-blend-mode": "hue" }, + ".mix-blend-saturation": { "mix-blend-mode": "saturation" }, + ".mix-blend-color": { "mix-blend-mode": "color" }, + ".mix-blend-luminosity": { "mix-blend-mode": "luminosity" }, + ".mix-blend-plus-darker": { "mix-blend-mode": "plus-darker" }, + ".mix-blend-plus-lighter": { "mix-blend-mode": "plus-lighter" }, + }); + }, + boxShadow: (() => { + let r = Ge("boxShadow"), + e = [ + "var(--tw-ring-offset-shadow, 0 0 #0000)", + "var(--tw-ring-shadow, 0 0 #0000)", + "var(--tw-shadow)", + ].join(", "); + return function ({ matchUtilities: t, addDefaults: i, theme: n }) { + (i("box-shadow", { + "--tw-ring-offset-shadow": "0 0 #0000", + "--tw-ring-shadow": "0 0 #0000", + "--tw-shadow": "0 0 #0000", + "--tw-shadow-colored": "0 0 #0000", + }), + t( + { + shadow: (a) => { + a = r(a); + let s = xi(a); + for (let o of s) !o.valid || (o.color = "var(--tw-shadow-color)"); + return { + "@defaults box-shadow": {}, + "--tw-shadow": a === "none" ? "0 0 #0000" : a, + "--tw-shadow-colored": a === "none" ? "0 0 #0000" : Lu(s), + "box-shadow": e, + }; + }, + }, + { values: n("boxShadow"), type: ["shadow"] } + )); + }; + })(), + boxShadowColor: ({ matchUtilities: r, theme: e }) => { + r( + { + shadow: (t) => ({ + "--tw-shadow-color": N(t), + "--tw-shadow": "var(--tw-shadow-colored)", + }), + }, + { values: re(e("boxShadowColor")), type: ["color", "any"] } + ); + }, + outlineStyle: ({ addUtilities: r }) => { + r({ + ".outline-none": { outline: "2px solid transparent", "outline-offset": "2px" }, + ".outline": { "outline-style": "solid" }, + ".outline-dashed": { "outline-style": "dashed" }, + ".outline-dotted": { "outline-style": "dotted" }, + ".outline-double": { "outline-style": "double" }, + }); + }, + outlineWidth: P("outlineWidth", [["outline", ["outline-width"]]], { + type: ["length", "number", "percentage"], + }), + outlineOffset: P("outlineOffset", [["outline-offset", ["outline-offset"]]], { + type: ["length", "number", "percentage", "any"], + supportsNegativeValues: !0, + }), + outlineColor: ({ matchUtilities: r, theme: e }) => { + r( + { outline: (t) => ({ "outline-color": N(t) }) }, + { values: re(e("outlineColor")), type: ["color", "any"] } + ); + }, + ringWidth: ({ matchUtilities: r, addDefaults: e, addUtilities: t, theme: i, config: n }) => { + let a = (() => { + if (K(n(), "respectDefaultRingColorOpacity")) return i("ringColor.DEFAULT"); + let s = i("ringOpacity.DEFAULT", "0.5"); + return i("ringColor")?.DEFAULT + ? Ie(i("ringColor")?.DEFAULT, s, `rgb(147 197 253 / ${s})`) + : `rgb(147 197 253 / ${s})`; + })(); + (e("ring-width", { + "--tw-ring-inset": " ", + "--tw-ring-offset-width": i("ringOffsetWidth.DEFAULT", "0px"), + "--tw-ring-offset-color": i("ringOffsetColor.DEFAULT", "#fff"), + "--tw-ring-color": a, + "--tw-ring-offset-shadow": "0 0 #0000", + "--tw-ring-shadow": "0 0 #0000", + "--tw-shadow": "0 0 #0000", + "--tw-shadow-colored": "0 0 #0000", + }), + r( + { + ring: (s) => ({ + "@defaults ring-width": {}, + "--tw-ring-offset-shadow": + "var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)", + "--tw-ring-shadow": `var(--tw-ring-inset) 0 0 0 calc(${s} + var(--tw-ring-offset-width)) var(--tw-ring-color)`, + "box-shadow": [ + "var(--tw-ring-offset-shadow)", + "var(--tw-ring-shadow)", + "var(--tw-shadow, 0 0 #0000)", + ].join(", "), + }), + }, + { values: i("ringWidth"), type: "length" } + ), + t({ ".ring-inset": { "@defaults ring-width": {}, "--tw-ring-inset": "inset" } })); + }, + ringColor: ({ matchUtilities: r, theme: e, corePlugins: t }) => { + r( + { + ring: (i) => + t("ringOpacity") + ? se({ color: i, property: "--tw-ring-color", variable: "--tw-ring-opacity" }) + : { "--tw-ring-color": N(i) }, + }, + { + values: Object.fromEntries( + Object.entries(re(e("ringColor"))).filter(([i]) => i !== "DEFAULT") + ), + type: ["color", "any"], + } + ); + }, + ringOpacity: (r) => { + let { config: e } = r; + return P("ringOpacity", [["ring-opacity", ["--tw-ring-opacity"]]], { + filterDefault: !K(e(), "respectDefaultRingColorOpacity"), + })(r); + }, + ringOffsetWidth: P("ringOffsetWidth", [["ring-offset", ["--tw-ring-offset-width"]]], { + type: "length", + }), + ringOffsetColor: ({ matchUtilities: r, theme: e }) => { + r( + { "ring-offset": (t) => ({ "--tw-ring-offset-color": N(t) }) }, + { values: re(e("ringOffsetColor")), type: ["color", "any"] } + ); + }, + blur: ({ matchUtilities: r, theme: e }) => { + r( + { blur: (t) => ({ "--tw-blur": `blur(${t})`, "@defaults filter": {}, filter: Be }) }, + { values: e("blur") } + ); + }, + brightness: ({ matchUtilities: r, theme: e }) => { + r( + { + brightness: (t) => ({ + "--tw-brightness": `brightness(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("brightness") } + ); + }, + contrast: ({ matchUtilities: r, theme: e }) => { + r( + { + contrast: (t) => ({ + "--tw-contrast": `contrast(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("contrast") } + ); + }, + dropShadow: ({ matchUtilities: r, theme: e }) => { + r( + { + "drop-shadow": (t) => ({ + "--tw-drop-shadow": Array.isArray(t) + ? t.map((i) => `drop-shadow(${i})`).join(" ") + : `drop-shadow(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("dropShadow") } + ); + }, + grayscale: ({ matchUtilities: r, theme: e }) => { + r( + { + grayscale: (t) => ({ + "--tw-grayscale": `grayscale(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("grayscale") } + ); + }, + hueRotate: ({ matchUtilities: r, theme: e }) => { + r( + { + "hue-rotate": (t) => ({ + "--tw-hue-rotate": `hue-rotate(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("hueRotate"), supportsNegativeValues: !0 } + ); + }, + invert: ({ matchUtilities: r, theme: e }) => { + r( + { invert: (t) => ({ "--tw-invert": `invert(${t})`, "@defaults filter": {}, filter: Be }) }, + { values: e("invert") } + ); + }, + saturate: ({ matchUtilities: r, theme: e }) => { + r( + { + saturate: (t) => ({ + "--tw-saturate": `saturate(${t})`, + "@defaults filter": {}, + filter: Be, + }), + }, + { values: e("saturate") } + ); + }, + sepia: ({ matchUtilities: r, theme: e }) => { + r( + { sepia: (t) => ({ "--tw-sepia": `sepia(${t})`, "@defaults filter": {}, filter: Be }) }, + { values: e("sepia") } + ); + }, + filter: ({ addDefaults: r, addUtilities: e }) => { + (r("filter", { + "--tw-blur": " ", + "--tw-brightness": " ", + "--tw-contrast": " ", + "--tw-grayscale": " ", + "--tw-hue-rotate": " ", + "--tw-invert": " ", + "--tw-saturate": " ", + "--tw-sepia": " ", + "--tw-drop-shadow": " ", + }), + e({ + ".filter": { "@defaults filter": {}, filter: Be }, + ".filter-none": { filter: "none" }, + })); + }, + backdropBlur: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-blur": (t) => ({ + "--tw-backdrop-blur": `blur(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropBlur") } + ); + }, + backdropBrightness: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-brightness": (t) => ({ + "--tw-backdrop-brightness": `brightness(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropBrightness") } + ); + }, + backdropContrast: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-contrast": (t) => ({ + "--tw-backdrop-contrast": `contrast(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropContrast") } + ); + }, + backdropGrayscale: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-grayscale": (t) => ({ + "--tw-backdrop-grayscale": `grayscale(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropGrayscale") } + ); + }, + backdropHueRotate: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-hue-rotate": (t) => ({ + "--tw-backdrop-hue-rotate": `hue-rotate(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropHueRotate"), supportsNegativeValues: !0 } + ); + }, + backdropInvert: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-invert": (t) => ({ + "--tw-backdrop-invert": `invert(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropInvert") } + ); + }, + backdropOpacity: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-opacity": (t) => ({ + "--tw-backdrop-opacity": `opacity(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropOpacity") } + ); + }, + backdropSaturate: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-saturate": (t) => ({ + "--tw-backdrop-saturate": `saturate(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropSaturate") } + ); + }, + backdropSepia: ({ matchUtilities: r, theme: e }) => { + r( + { + "backdrop-sepia": (t) => ({ + "--tw-backdrop-sepia": `sepia(${t})`, + "@defaults backdrop-filter": {}, + "backdrop-filter": Fe, + }), + }, + { values: e("backdropSepia") } + ); + }, + backdropFilter: ({ addDefaults: r, addUtilities: e }) => { + (r("backdrop-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": " ", + }), + e({ + ".backdrop-filter": { "@defaults backdrop-filter": {}, "backdrop-filter": Fe }, + ".backdrop-filter-none": { "backdrop-filter": "none" }, + })); + }, + transitionProperty: ({ matchUtilities: r, theme: e }) => { + let t = e("transitionTimingFunction.DEFAULT"), + i = e("transitionDuration.DEFAULT"); + r( + { + transition: (n) => ({ + "transition-property": n, + ...(n === "none" + ? {} + : { "transition-timing-function": t, "transition-duration": i }), + }), + }, + { values: e("transitionProperty") } + ); + }, + transitionDelay: P("transitionDelay", [["delay", ["transitionDelay"]]]), + transitionDuration: P("transitionDuration", [["duration", ["transitionDuration"]]], { + filterDefault: !0, + }), + transitionTimingFunction: P("transitionTimingFunction", [["ease", ["transitionTimingFunction"]]], { + filterDefault: !0, + }), + willChange: P("willChange", [["will-change", ["will-change"]]]), + contain: ({ addDefaults: r, addUtilities: e }) => { + let t = + "var(--tw-contain-size) var(--tw-contain-layout) var(--tw-contain-paint) var(--tw-contain-style)"; + (r("contain", { + "--tw-contain-size": " ", + "--tw-contain-layout": " ", + "--tw-contain-paint": " ", + "--tw-contain-style": " ", + }), + e({ + ".contain-none": { contain: "none" }, + ".contain-content": { contain: "content" }, + ".contain-strict": { contain: "strict" }, + ".contain-size": { "@defaults contain": {}, "--tw-contain-size": "size", contain: t }, + ".contain-inline-size": { + "@defaults contain": {}, + "--tw-contain-size": "inline-size", + contain: t, + }, + ".contain-layout": { + "@defaults contain": {}, + "--tw-contain-layout": "layout", + contain: t, + }, + ".contain-paint": { + "@defaults contain": {}, + "--tw-contain-paint": "paint", + contain: t, + }, + ".contain-style": { + "@defaults contain": {}, + "--tw-contain-style": "style", + contain: t, + }, + })); + }, + content: P("content", [["content", ["--tw-content", ["content", "var(--tw-content)"]]]]), + forcedColorAdjust: ({ addUtilities: r }) => { + r({ + ".forced-color-adjust-auto": { "forced-color-adjust": "auto" }, + ".forced-color-adjust-none": { "forced-color-adjust": "none" }, + }); + }, + })); + }); + function h2(r) { + if (r === void 0) return !1; + if (r === "true" || r === "1") return !0; + if (r === "false" || r === "0") return !1; + if (r === "*") return !0; + let e = r.split(",").map((t) => t.split(":")[0]); + return e.includes("-tailwindcss") ? !1 : !!e.includes("tailwindcss"); + } + var Pe, + Ad, + _d, + vn, + Za, + He, + ti, + lt = C(() => { + l(); + ((Pe = + typeof h != "undefined" + ? { NODE_ENV: "production", DEBUG: h2(h.env.DEBUG) } + : { NODE_ENV: "production", DEBUG: !1 }), + (Ad = new Map()), + (_d = new Map()), + (vn = new Map()), + (Za = new Map()), + (He = new String("*")), + (ti = Symbol("__NONE__"))); + }); + function zt(r) { + let e = [], + t = !1; + for (let i = 0; i < r.length; i++) { + let n = r[i]; + if (n === ":" && !t && e.length === 0) return !1; + if ((m2.has(n) && r[i - 1] !== "\\" && (t = !t), !t && r[i - 1] !== "\\")) { + if (Od.has(n)) e.push(n); + else if (Ed.has(n)) { + let a = Ed.get(n); + if (e.length <= 0 || e.pop() !== a) return !1; + } + } + } + return !(e.length > 0); + } + var Od, + Ed, + m2, + eo = C(() => { + l(); + ((Od = new Map([ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ])), + (Ed = new Map(Array.from(Od.entries()).map(([r, e]) => [e, r]))), + (m2 = new Set(['"', "'", "`"]))); + }); + function jt(r) { + let [e] = Td(r); + return (e.forEach(([t, i]) => t.removeChild(i)), r.nodes.push(...e.map(([, t]) => t)), r); + } + function Td(r) { + let e = [], + t = null; + for (let i of r.nodes) + if (i.type === "combinator") ((e = e.filter(([, n]) => ro(n).includes("jumpable"))), (t = null)); + else if (i.type === "pseudo") { + g2(i) ? ((t = i), e.push([r, i, null])) : t && y2(i, t) ? e.push([r, i, t]) : (t = null); + for (let n of i.nodes ?? []) { + let [a, s] = Td(n); + ((t = s || t), e.push(...a)); + } + } + return [e, t]; + } + function Pd(r) { + return r.value.startsWith("::") || to[r.value] !== void 0; + } + function g2(r) { + return Pd(r) && ro(r).includes("terminal"); + } + function y2(r, e) { + return r.type !== "pseudo" || Pd(r) ? !1 : ro(e).includes("actionable"); + } + function ro(r) { + return to[r.value] ?? to.__default__; + } + var to, + xn = C(() => { + l(); + to = { + "::after": ["terminal", "jumpable"], + "::backdrop": ["terminal", "jumpable"], + "::before": ["terminal", "jumpable"], + "::cue": ["terminal"], + "::cue-region": ["terminal"], + "::first-letter": ["terminal", "jumpable"], + "::first-line": ["terminal", "jumpable"], + "::grammar-error": ["terminal"], + "::marker": ["terminal", "jumpable"], + "::part": ["terminal", "actionable"], + "::placeholder": ["terminal", "jumpable"], + "::selection": ["terminal", "jumpable"], + "::slotted": ["terminal"], + "::spelling-error": ["terminal"], + "::target-text": ["terminal"], + "::file-selector-button": ["terminal", "actionable"], + "::deep": ["actionable"], + "::v-deep": ["actionable"], + "::ng-deep": ["actionable"], + ":after": ["terminal", "jumpable"], + ":before": ["terminal", "jumpable"], + ":first-letter": ["terminal", "jumpable"], + ":first-line": ["terminal", "jumpable"], + ":where": [], + ":is": [], + ":has": [], + __default__: ["terminal", "actionable"], + }; + }); + function Vt(r, { context: e, candidate: t }) { + let i = e?.tailwindConfig.prefix ?? "", + n = r.map((s) => { + let o = (0, Le.default)().astSync(s.format); + return { ...s, ast: s.respectPrefix ? Nt(i, o) : o }; + }), + a = Le.default.root({ nodes: [Le.default.selector({ nodes: [Le.default.className({ value: ce(t) })] })] }); + for (let { ast: s } of n) + (([a, s] = b2(a, s)), s.walkNesting((o) => o.replaceWith(...a.nodes[0].nodes)), (a = s)); + return a; + } + function Id(r) { + let e = []; + for (; r.prev() && r.prev().type !== "combinator"; ) r = r.prev(); + for (; r && r.type !== "combinator"; ) (e.push(r), (r = r.next())); + return e; + } + function w2(r) { + return ( + r.sort((e, t) => + e.type === "tag" && t.type === "class" + ? -1 + : e.type === "class" && t.type === "tag" + ? 1 + : e.type === "class" && t.type === "pseudo" && t.value.startsWith("::") + ? -1 + : e.type === "pseudo" && e.value.startsWith("::") && t.type === "class" + ? 1 + : r.index(e) - r.index(t) + ), + r + ); + } + function no(r, e) { + let t = !1; + (r.walk((i) => { + if (i.type === "class" && i.value === e) return ((t = !0), !1); + }), + t || r.remove()); + } + function kn(r, e, { context: t, candidate: i, base: n }) { + let a = t?.tailwindConfig?.separator ?? ":"; + n = n ?? ae(i, a).pop(); + let s = (0, Le.default)().astSync(r); + if ( + (s.walkClasses((f) => { + f.raws && f.value.includes(n) && (f.raws.value = ce((0, Dd.default)(f.raws.value))); + }), + s.each((f) => no(f, n)), + s.length === 0) + ) + return null; + let o = Array.isArray(e) ? Vt(e, { context: t, candidate: i }) : e; + if (o === null) return s.toString(); + let u = Le.default.comment({ value: "/*__simple__*/" }), + c = Le.default.comment({ value: "/*__simple__*/" }); + return ( + s.walkClasses((f) => { + if (f.value !== n) return; + let d = f.parent, + p = o.nodes[0].nodes; + if (d.nodes.length === 1) { + f.replaceWith(...p); + return; + } + let m = Id(f); + (d.insertBefore(m[0], u), d.insertAfter(m[m.length - 1], c)); + for (let x of p) d.insertBefore(m[0], x.clone()); + (f.remove(), (m = Id(u))); + let b = d.index(u); + (d.nodes.splice(b, m.length, ...w2(Le.default.selector({ nodes: m })).nodes), u.remove(), c.remove()); + }), + s.walkPseudos((f) => { + f.value === io && f.replaceWith(f.nodes); + }), + s.each((f) => jt(f)), + s.toString() + ); + } + function b2(r, e) { + let t = []; + return ( + r.walkPseudos((i) => { + i.value === io && t.push({ pseudo: i, value: i.nodes[0].toString() }); + }), + e.walkPseudos((i) => { + if (i.value !== io) return; + let n = i.nodes[0].toString(), + a = t.find((c) => c.value === n); + if (!a) return; + let s = [], + o = i.next(); + for (; o && o.type !== "combinator"; ) (s.push(o), (o = o.next())); + let u = o; + (a.pseudo.parent.insertAfter(a.pseudo, Le.default.selector({ nodes: s.map((c) => c.clone()) })), + i.remove(), + s.forEach((c) => c.remove()), + u && u.type === "combinator" && u.remove()); + }), + [r, e] + ); + } + var Le, + Dd, + io, + so = C(() => { + l(); + ((Le = X(Me())), (Dd = X(Ki()))); + $t(); + dn(); + xn(); + _t(); + io = ":merge"; + }); + function Sn(r, e) { + let t = (0, ao.default)().astSync(r); + return ( + t.each((i) => { + ((i.nodes[0].type === "pseudo" && + i.nodes[0].value === ":is" && + i.nodes.every((a) => a.type !== "combinator")) || + (i.nodes = [ao.default.pseudo({ value: ":is", nodes: [i.clone()] })]), + jt(i)); + }), + `${e} ${t.toString()}` + ); + } + var ao, + oo = C(() => { + l(); + ao = X(Me()); + xn(); + }); + function lo(r) { + return v2.transformSync(r); + } + function* x2(r) { + let e = 1 / 0; + for (; e >= 0; ) { + let t, + i = !1; + if (e === 1 / 0 && r.endsWith("]")) { + let s = r.indexOf("["); + r[s - 1] === "-" ? (t = s - 1) : r[s - 1] === "/" ? ((t = s - 1), (i = !0)) : (t = -1); + } else e === 1 / 0 && r.includes("/") ? ((t = r.lastIndexOf("/")), (i = !0)) : (t = r.lastIndexOf("-", e)); + if (t < 0) break; + let n = r.slice(0, t), + a = r.slice(i ? t : t + 1); + ((e = t - 1), !(n === "" || a === "/") && (yield [n, a])); + } + } + function k2(r, e) { + if (r.length === 0 || e.tailwindConfig.prefix === "") return r; + for (let t of r) { + let [i] = t; + if (i.options.respectPrefix) { + let n = j.root({ nodes: [t[1].clone()] }), + a = t[1].raws.tailwind.classCandidate; + (n.walkRules((s) => { + let o = a.startsWith("-"); + s.selector = Nt(e.tailwindConfig.prefix, s.selector, o); + }), + (t[1] = n.nodes[0])); + } + } + return r; + } + function S2(r, e) { + if (r.length === 0) return r; + let t = []; + function i(n) { + return n.parent && n.parent.type === "atrule" && n.parent.name === "keyframes"; + } + for (let [n, a] of r) { + let s = j.root({ nodes: [a.clone()] }); + (s.walkRules((o) => { + if (i(o)) return; + let u = (0, Cn.default)().astSync(o.selector); + (u.each((c) => no(c, e)), + Ju(u, (c) => (c === e ? `!${c}` : c)), + (o.selector = u.toString()), + o.walkDecls((c) => (c.important = !0))); + }), + t.push([{ ...n, important: !0 }, s.nodes[0]])); + } + return t; + } + function C2(r, e, t) { + if (e.length === 0) return e; + let i = { modifier: null, value: ti }; + { + let [n, ...a] = ae(r, "/"); + if ( + (a.length > 1 && ((n = n + "/" + a.slice(0, -1).join("/")), (a = a.slice(-1))), + a.length && + !t.variantMap.has(r) && + ((r = n), (i.modifier = a[0]), !K(t.tailwindConfig, "generalizedModifiers"))) + ) + return []; + } + if (r.endsWith("]") && !r.startsWith("[")) { + let n = /(.)(-?)\[(.*)\]/g.exec(r); + if (n) { + let [, a, s, o] = n; + if (a === "@" && s === "-") return []; + if (a !== "@" && s === "") return []; + ((r = r.replace(`${s}[${o}]`, "")), (i.value = o)); + } + } + if (co(r) && !t.variantMap.has(r)) { + let n = t.offsets.recordVariant(r), + a = L(r.slice(1, -1)), + s = ae(a, ","); + if (s.length > 1) return []; + if (!s.every(En)) return []; + let o = s.map((u, c) => [t.offsets.applyParallelOffset(n, c), ri(u.trim())]); + t.variantMap.set(r, o); + } + if (t.variantMap.has(r)) { + let n = co(r), + a = t.variantOptions.get(r)?.[Zr] ?? {}, + s = t.variantMap.get(r).slice(), + o = [], + u = (() => !(n || a.respectPrefix === !1))(); + for (let [c, f] of e) { + if (c.layer === "user") continue; + let d = j.root({ nodes: [f.clone()] }); + for (let [p, m, b] of s) { + let w = function () { + x.raws.neededBackup || + ((x.raws.neededBackup = !0), + x.walkRules((E) => (E.raws.originalSelector = E.selector))); + }, + k = function (E) { + return ( + w(), + x.each((I) => { + I.type === "rule" && + (I.selectors = I.selectors.map((q) => + E({ + get className() { + return lo(q); + }, + selector: q, + }) + )); + }), + x + ); + }, + x = (b ?? d).clone(), + y = [], + S = m({ + get container() { + return (w(), x); + }, + separator: t.tailwindConfig.separator, + modifySelectors: k, + wrap(E) { + let I = x.nodes; + (x.removeAll(), E.append(I), x.append(E)); + }, + format(E) { + y.push({ format: E, respectPrefix: u }); + }, + args: i, + }); + if (Array.isArray(S)) { + for (let [E, I] of S.entries()) s.push([t.offsets.applyParallelOffset(p, E), I, x.clone()]); + continue; + } + if ((typeof S == "string" && y.push({ format: S, respectPrefix: u }), S === null)) continue; + (x.raws.neededBackup && + (delete x.raws.neededBackup, + x.walkRules((E) => { + let I = E.raws.originalSelector; + if (!I || (delete E.raws.originalSelector, I === E.selector)) return; + let q = E.selector, + R = (0, Cn.default)((J) => { + J.walkClasses((ue) => { + ue.value = `${r}${t.tailwindConfig.separator}${ue.value}`; + }); + }).processSync(I); + (y.push({ format: q.replace(R, "&"), respectPrefix: u }), (E.selector = I)); + })), + (x.nodes[0].raws.tailwind = { ...x.nodes[0].raws.tailwind, parentLayer: c.layer })); + let _ = [ + { + ...c, + sort: t.offsets.applyVariantOffset(c.sort, p, Object.assign(i, t.variantOptions.get(r))), + collectedFormats: (c.collectedFormats ?? []).concat(y), + }, + x.nodes[0], + ]; + o.push(_); + } + } + return o; + } + return []; + } + function uo(r, e, t = {}) { + return !ie(r) && !Array.isArray(r) + ? [[r], t] + : Array.isArray(r) + ? uo(r[0], e, r[1]) + : (e.has(r) || e.set(r, Lt(r)), [e.get(r), t]); + } + function _2(r) { + return A2.test(r); + } + function O2(r) { + if (!r.includes("://")) return !1; + try { + let e = new URL(r); + return e.scheme !== "" && e.host !== ""; + } catch (e) { + return !1; + } + } + function qd(r) { + let e = !0; + return ( + r.walkDecls((t) => { + if (!Rd(t.prop, t.value)) return ((e = !1), !1); + }), + e + ); + } + function Rd(r, e) { + if (O2(`${r}:${e}`)) return !1; + try { + return (j.parse(`a{${r}:${e}}`).toResult(), !0); + } catch (t) { + return !1; + } + } + function E2(r, e) { + let [, t, i] = r.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/) ?? []; + if (i === void 0 || !_2(t) || !zt(i)) return null; + let n = L(i, { property: t }); + return Rd(t, n) + ? [ + [ + { sort: e.offsets.arbitraryProperty(r), layer: "utilities", options: { respectImportant: !0 } }, + () => ({ [Ja(r)]: { [t]: n } }), + ], + ] + : null; + } + function* T2(r, e) { + (e.candidateRuleMap.has(r) && (yield [e.candidateRuleMap.get(r), "DEFAULT"]), + yield* (function* (o) { + o !== null && (yield [o, "DEFAULT"]); + })(E2(r, e))); + let t = r, + i = !1, + n = e.tailwindConfig.prefix, + a = n.length, + s = t.startsWith(n) || t.startsWith(`-${n}`); + (t[a] === "-" && s && ((i = !0), (t = n + t.slice(a + 1))), + i && e.candidateRuleMap.has(t) && (yield [e.candidateRuleMap.get(t), "-DEFAULT"])); + for (let [o, u] of x2(t)) e.candidateRuleMap.has(o) && (yield [e.candidateRuleMap.get(o), i ? `-${u}` : u]); + } + function P2(r, e) { + return r === He ? [He] : ae(r, e); + } + function* D2(r, e) { + for (let t of r) + ((t[1].raws.tailwind = { + ...t[1].raws.tailwind, + classCandidate: e, + preserveSource: t[0].options?.preserveSource ?? !1, + }), + yield t); + } + function* fo(r, e) { + let t = e.tailwindConfig.separator, + [i, ...n] = P2(r, t).reverse(), + a = !1; + i.startsWith("!") && ((a = !0), (i = i.slice(1))); + for (let s of T2(i, e)) { + let o = [], + u = new Map(), + [c, f] = s, + d = c.length === 1; + for (let [p, m] of c) { + let b = []; + if (typeof m == "function") + for (let x of [].concat(m(f, { isOnlyPlugin: d }))) { + let [y, w] = uo(x, e.postCssNodeCache); + for (let k of y) b.push([{ ...p, options: { ...p.options, ...w } }, k]); + } + else if (f === "DEFAULT" || f === "-DEFAULT") { + let x = m, + [y, w] = uo(x, e.postCssNodeCache); + for (let k of y) b.push([{ ...p, options: { ...p.options, ...w } }, k]); + } + if (b.length > 0) { + let x = Array.from(ys(p.options?.types ?? [], f, p.options ?? {}, e.tailwindConfig)).map( + ([y, w]) => w + ); + (x.length > 0 && u.set(b, x), o.push(b)); + } + } + if (co(f)) { + if (o.length > 1) { + let b = function (y) { + return y.length === 1 + ? y[0] + : y.find((w) => { + let k = u.get(w); + return w.some(([{ options: S }, _]) => + qd(_) + ? S.types.some(({ type: E, preferOnConflict: I }) => k.includes(E) && I) + : !1 + ); + }); + }, + [p, m] = o.reduce( + (y, w) => ( + w.some(([{ options: S }]) => S.types.some(({ type: _ }) => _ === "any")) + ? y[0].push(w) + : y[1].push(w), + y + ), + [[], []] + ), + x = b(m) ?? b(p); + if (x) o = [x]; + else { + let y = o.map((k) => new Set([...(u.get(k) ?? [])])); + for (let k of y) + for (let S of k) { + let _ = !1; + for (let E of y) k !== E && E.has(S) && (E.delete(S), (_ = !0)); + _ && k.delete(S); + } + let w = []; + for (let [k, S] of y.entries()) + for (let _ of S) { + let E = o[k] + .map(([, I]) => I) + .flat() + .map((I) => + I.toString() + .split( + ` +` + ) + .slice(1, -1) + .map((q) => q.trim()) + .map((q) => ` ${q}`).join(` +`) + ).join(` -`);w.push(` Use \`${r.replace("[",`[${_}:`)}\` for \`${E.trim()}\``);break}F.warn([`The class \`${r}\` is ambiguous and matches multiple utilities.`,...w,`If this is content and not a class, replace it with \`${r.replace("[","[").replace("]","]")}\` to silence this warning.`]);continue}}o=o.map(p=>p.filter(m=>qd(m[1])))}o=o.flat(),o=Array.from(D2(o,i)),o=k2(o,e),a&&(o=S2(o,i));for(let p of n)o=C2(p,o,e);for(let p of o)p[1].raws.tailwind={...p[1].raws.tailwind,candidate:r},p=I2(p,{context:e,candidate:r}),p!==null&&(yield p)}}function I2(r,{context:e,candidate:t}){if(!r[0].collectedFormats)return r;let i=!0,n;try{n=Vt(r[0].collectedFormats,{context:e,candidate:t})}catch{return null}let a=j.root({nodes:[r[1].clone()]});return a.walkRules(s=>{if(!An(s))try{let o=kn(s.selector,n,{candidate:t,context:e});if(o===null){s.remove();return}s.selector=o}catch{return i=!1,!1}}),!i||a.nodes.length===0?null:(r[1]=a.nodes[0],r)}function An(r){return r.parent&&r.parent.type==="atrule"&&r.parent.name==="keyframes"}function q2(r){if(r===!0)return e=>{An(e)||e.walkDecls(t=>{t.parent.type==="rule"&&!An(t.parent)&&(t.important=!0)})};if(typeof r=="string")return e=>{An(e)||(e.selectors=e.selectors.map(t=>Sn(t,r)))}}function _n(r,e,t=!1){let i=[],n=q2(e.tailwindConfig.important);for(let a of r){if(e.notClassCache.has(a))continue;if(e.candidateRuleCache.has(a)){i=i.concat(Array.from(e.candidateRuleCache.get(a)));continue}let s=Array.from(fo(a,e));if(s.length===0){e.notClassCache.add(a);continue}e.classCache.set(a,s);let o=e.candidateRuleCache.get(a)??new Set;e.candidateRuleCache.set(a,o);for(let u of s){let[{sort:c,options:f},d]=u;if(f.respectImportant&&n){let m=j.root({nodes:[d.clone()]});m.walkRules(n),d=m.nodes[0]}let p=[c,t?d.clone():d];o.add(p),e.ruleCache.add(p),i.push(p)}}return i}function co(r){return r.startsWith("[")&&r.endsWith("]")}var Cn,v2,A2,On=C(()=>{l();st();Cn=X(Me());Qa();At();dn();hr();Oe();lt();so();Xa();dr();ei();eo();_t();je();oo();v2=(0,Cn.default)(r=>r.first.filter(({type:e})=>e==="class").pop().value);A2=/^[a-z_-]/});var Md,Bd=C(()=>{l();Md={}});function R2(r){try{return Md.createHash("md5").update(r,"utf-8").digest("binary")}catch(e){return""}}function Fd(r,e){let t=e.toString();if(!t.includes("@tailwind"))return!1;let i=Za.get(r),n=R2(t),a=i!==n;return Za.set(r,n),a}var Ld=C(()=>{l();Bd();lt()});function Tn(r){return(r>0n)-(r<0n)}var Nd=C(()=>{l()});function $d(r,e){let t=0n,i=0n;for(let[n,a]of e)r&n&&(t=t|n,i=i|a);return r&~t|i}var zd=C(()=>{l()});function jd(r){let e=null;for(let t of r)e=e??t,e=e>t?e:t;return e}function M2(r,e){let t=r.length,i=e.length,n=t{l();Nd();zd();po=class{constructor(){this.offsets={defaults:0n,base:0n,components:0n,utilities:0n,variants:0n,user:0n},this.layerPositions={defaults:0n,base:1n,components:2n,utilities:3n,user:4n,variants:5n},this.reservedVariantBits=0n,this.variantOffsets=new Map}create(e){return{layer:e,parentLayer:e,arbitrary:0n,variants:0n,parallelIndex:0n,index:this.offsets[e]++,propertyOffset:0n,property:"",options:[]}}arbitraryProperty(e){return{...this.create("utilities"),arbitrary:1n,property:e}}forVariant(e,t=0){let i=this.variantOffsets.get(e);if(i===void 0)throw new Error(`Cannot find offset for unknown variant ${e}`);return{...this.create("variants"),variants:i<n.startsWith("[")).sort(([n],[a])=>M2(n,a)),t=e.map(([,n])=>n).sort((n,a)=>Tn(n-a));return e.map(([,n],a)=>[n,t[a]]).filter(([n,a])=>n!==a)}remapArbitraryVariantOffsets(e){let t=this.recalculateVariantOffsets();return t.length===0?e:e.map(i=>{let[n,a]=i;return n={...n,variants:$d(n.variants,t)},[n,a]})}sortArbitraryProperties(e){let t=new Set;for(let[s]of e)s.arbitrary===1n&&t.add(s.property);if(t.size===0)return e;let i=Array.from(t).sort(),n=new Map,a=1n;for(let s of i)n.set(s,a++);return e.map(s=>{let[o,u]=s;return o={...o,propertyOffset:n.get(o.property)??0n},[o,u]})}sort(e){return e=this.remapArbitraryVariantOffsets(e),e=this.sortArbitraryProperties(e),e.sort(([t],[i])=>Tn(this.compare(t,i)))}}});function yo(r,e){let t=r.tailwindConfig.prefix;return typeof t=="function"?t(e):t+e}function Wd({type:r="any",...e}){let t=[].concat(r);return{...e,types:t.map(i=>Array.isArray(i)?{type:i[0],...i[1]}:{type:i,preferOnConflict:!1})}}function B2(r){let e=[],t="",i=0;for(let n=0;n0&&e.push(t.trim()),e=e.filter(n=>n!==""),e}function F2(r,e,{before:t=[]}={}){if(t=[].concat(t),t.length<=0){r.push(e);return}let i=r.length-1;for(let n of t){let a=r.indexOf(n);a!==-1&&(i=Math.min(i,a))}r.splice(i,0,e)}function Gd(r){return Array.isArray(r)?r.flatMap(e=>!Array.isArray(e)&&!ie(e)?e:Lt(e)):Gd([r])}function L2(r,e){return(0,ho.default)(i=>{let n=[];return e&&e(i),i.walkClasses(a=>{n.push(a.value)}),n}).transformSync(r)}function N2(r){r.walkPseudos(e=>{e.value===":not"&&e.remove()})}function $2(r,e={containsNonOnDemandable:!1},t=0){let i=[],n=[];r.type==="rule"?n.push(...r.selectors):r.type==="atrule"&&r.walkRules(a=>n.push(...a.selectors));for(let a of n){let s=L2(a,N2);s.length===0&&(e.containsNonOnDemandable=!0);for(let o of s)i.push(o)}return t===0?[e.containsNonOnDemandable||i.length===0,i]:i}function Pn(r){return Gd(r).flatMap(e=>{let t=new Map,[i,n]=$2(e);return i&&n.unshift(He),n.map(a=>(t.has(e)||t.set(e,e),[a,t.get(e)]))})}function En(r){return r.startsWith("@")||r.includes("&")}function ri(r){r=r.replace(/\n+/g,"").replace(/\s{1,}/g," ").trim();let e=B2(r).map(t=>{if(!t.startsWith("@"))return({format:a})=>a(t);let[,i,n]=/@(\S*)( .+|[({].*)?/g.exec(t);return({wrap:a})=>a(j.atRule({name:i,params:n?.trim()??""}))}).reverse();return t=>{for(let i of e)i(t)}}function z2(r,e,{variantList:t,variantMap:i,offsets:n,classList:a}){function s(p,m){return p?(0,Ud.default)(r,p,m):r}function o(p){return Nt(r.prefix,p)}function u(p,m){return p===He?He:m.respectPrefix?e.tailwindConfig.prefix+p:p}function c(p,m,b={}){let x=Ze(p),y=s(["theme",...x],m);return Ge(x[0])(y,b)}let f=0,d={postcss:j,prefix:o,e:ce,config:s,theme:c,corePlugins:p=>Array.isArray(r.corePlugins)?r.corePlugins.includes(p):s(["corePlugins",p],!0),variants:()=>[],addBase(p){for(let[m,b]of Pn(p)){let x=u(m,{}),y=n.create("base");e.candidateRuleMap.has(x)||e.candidateRuleMap.set(x,[]),e.candidateRuleMap.get(x).push([{sort:y,layer:"base"},b])}},addDefaults(p,m){let b={[`@defaults ${p}`]:m};for(let[x,y]of Pn(b)){let w=u(x,{});e.candidateRuleMap.has(w)||e.candidateRuleMap.set(w,[]),e.candidateRuleMap.get(w).push([{sort:n.create("defaults"),layer:"defaults"},y])}},addComponents(p,m){m=Object.assign({},{preserveSource:!1,respectPrefix:!0,respectImportant:!1},Array.isArray(m)?{}:m);for(let[x,y]of Pn(p)){let w=u(x,m);a.add(w),e.candidateRuleMap.has(w)||e.candidateRuleMap.set(w,[]),e.candidateRuleMap.get(w).push([{sort:n.create("components"),layer:"components",options:m},y])}},addUtilities(p,m){m=Object.assign({},{preserveSource:!1,respectPrefix:!0,respectImportant:!0},Array.isArray(m)?{}:m);for(let[x,y]of Pn(p)){let w=u(x,m);a.add(w),e.candidateRuleMap.has(w)||e.candidateRuleMap.set(w,[]),e.candidateRuleMap.get(w).push([{sort:n.create("utilities"),layer:"utilities",options:m},y])}},matchUtilities:function(p,m){m=Wd({...{respectPrefix:!0,respectImportant:!0,modifiers:!1},...m});let x=n.create("utilities");for(let y in p){let S=function(E,{isOnlyPlugin:I}){let[q,R,J]=gs(m.types,E,m,r);if(q===void 0)return[];if(!m.types.some(({type:ee})=>ee===R))if(I)F.warn([`Unnecessary typehint \`${R}\` in \`${y}-${E}\`.`,`You can safely update it to \`${y}-${E.replace(R+":","")}\`.`]);else return[];if(!zt(q))return[];let ue={get modifier(){return m.modifiers||F.warn(`modifier-used-without-options-for-${y}`,["Your plugin must set `modifiers: true` in its options to support modifiers."]),J}},de=K(r,"generalizedModifiers");return[].concat(de?k(q,ue):k(q)).filter(Boolean).map(ee=>({[hn(y,E)]:ee}))},w=u(y,m),k=p[y];a.add([w,m]);let _=[{sort:x,layer:"utilities",options:m},S];e.candidateRuleMap.has(w)||e.candidateRuleMap.set(w,[]),e.candidateRuleMap.get(w).push(_)}},matchComponents:function(p,m){m=Wd({...{respectPrefix:!0,respectImportant:!1,modifiers:!1},...m});let x=n.create("components");for(let y in p){let S=function(E,{isOnlyPlugin:I}){let[q,R,J]=gs(m.types,E,m,r);if(q===void 0)return[];if(!m.types.some(({type:ee})=>ee===R))if(I)F.warn([`Unnecessary typehint \`${R}\` in \`${y}-${E}\`.`,`You can safely update it to \`${y}-${E.replace(R+":","")}\`.`]);else return[];if(!zt(q))return[];let ue={get modifier(){return m.modifiers||F.warn(`modifier-used-without-options-for-${y}`,["Your plugin must set `modifiers: true` in its options to support modifiers."]),J}},de=K(r,"generalizedModifiers");return[].concat(de?k(q,ue):k(q)).filter(Boolean).map(ee=>({[hn(y,E)]:ee}))},w=u(y,m),k=p[y];a.add([w,m]);let _=[{sort:x,layer:"components",options:m},S];e.candidateRuleMap.has(w)||e.candidateRuleMap.set(w,[]),e.candidateRuleMap.get(w).push(_)}},addVariant(p,m,b={}){m=[].concat(m).map(x=>{if(typeof x!="string")return(y={})=>{let{args:w,modifySelectors:k,container:S,separator:_,wrap:E,format:I}=y,q=x(Object.assign({modifySelectors:k,container:S,separator:_},b.type===mo.MatchVariant&&{args:w,wrap:E,format:I}));if(typeof q=="string"&&!En(q))throw new Error(`Your custom variant \`${p}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);return Array.isArray(q)?q.filter(R=>typeof R=="string").map(R=>ri(R)):q&&typeof q=="string"&&ri(q)(y)};if(!En(x))throw new Error(`Your custom variant \`${p}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);return ri(x)}),F2(t,p,b),i.set(p,m),e.variantOptions.set(p,b)},matchVariant(p,m,b){let x=b?.id??++f,y=p==="@",w=K(r,"generalizedModifiers");for(let[S,_]of Object.entries(b?.values??{}))S!=="DEFAULT"&&d.addVariant(y?`${p}${S}`:`${p}-${S}`,({args:E,container:I})=>m(_,w?{modifier:E?.modifier,container:I}:{container:I}),{...b,value:_,id:x,type:mo.MatchVariant,variantInfo:go.Base});let k="DEFAULT"in(b?.values??{});d.addVariant(p,({args:S,container:_})=>S?.value===ti&&!k?null:m(S?.value===ti?b.values.DEFAULT:S?.value??(typeof S=="string"?S:""),w?{modifier:S?.modifier,container:_}:{container:_}),{...b,id:x,type:mo.MatchVariant,variantInfo:go.Dynamic})}};return d}function Dn(r){return wo.has(r)||wo.set(r,new Map),wo.get(r)}function Hd(r,e){let t=!1,i=new Map;for(let n of r){if(!n)continue;let a=Ss.parse(n),s=a.hash?a.href.replace(a.hash,""):a.href;s=a.search?s.replace(a.search,""):s;let o=te.statSync(decodeURIComponent(s),{throwIfNoEntry:!1})?.mtimeMs;!o||((!e.has(n)||o>e.get(n))&&(t=!0),i.set(n,o))}return[t,i]}function Yd(r){r.walkAtRules(e=>{["responsive","variants"].includes(e.name)&&(Yd(e),e.before(e.nodes),e.remove())})}function j2(r){let e=[];return r.each(t=>{t.type==="atrule"&&["responsive","variants"].includes(t.name)&&(t.name="layer",t.params="utilities")}),r.walkAtRules("layer",t=>{if(Yd(t),t.params==="base"){for(let i of t.nodes)e.push(function({addBase:n}){n(i,{respectPrefix:!1})});t.remove()}else if(t.params==="components"){for(let i of t.nodes)e.push(function({addComponents:n}){n(i,{respectPrefix:!1,preserveSource:!0})});t.remove()}else if(t.params==="utilities"){for(let i of t.nodes)e.push(function({addUtilities:n}){n(i,{respectPrefix:!1,preserveSource:!0})});t.remove()}}),e}function V2(r,e){let t=Object.entries({...H,...Sd}).map(([u,c])=>r.tailwindConfig.corePlugins.includes(u)?c:null).filter(Boolean),i=r.tailwindConfig.plugins.map(u=>(u.__isOptionsFunction&&(u=u()),typeof u=="function"?u:u.handler)),n=j2(e),a=[H.childVariant,H.pseudoElementVariants,H.pseudoClassVariants,H.hasVariants,H.ariaVariants,H.dataVariants],s=[H.supportsVariants,H.reducedMotionVariants,H.prefersContrastVariants,H.screenVariants,H.orientationVariants,H.directionVariants,H.darkVariants,H.forcedColorsVariants,H.printVariant];return(r.tailwindConfig.darkMode==="class"||Array.isArray(r.tailwindConfig.darkMode)&&r.tailwindConfig.darkMode[0]==="class")&&(s=[H.supportsVariants,H.reducedMotionVariants,H.prefersContrastVariants,H.darkVariants,H.screenVariants,H.orientationVariants,H.directionVariants,H.forcedColorsVariants,H.printVariant]),[...t,...a,...i,...s,...n]}function U2(r,e){let t=[],i=new Map;e.variantMap=i;let n=new po;e.offsets=n;let a=new Set,s=z2(e.tailwindConfig,e,{variantList:t,variantMap:i,offsets:n,classList:a});for(let f of r)if(Array.isArray(f))for(let d of f)d(s);else f?.(s);n.recordVariants(t,f=>i.get(f).length);for(let[f,d]of i.entries())e.variantMap.set(f,d.map((p,m)=>[n.forVariant(f,m),p]));let o=(e.tailwindConfig.safelist??[]).filter(Boolean);if(o.length>0){let f=[];for(let d of o){if(typeof d=="string"){e.changedContent.push({content:d,extension:"html"});continue}if(d instanceof RegExp){F.warn("root-regex",["Regular expressions in `safelist` work differently in Tailwind CSS v3.0.","Update your `safelist` configuration to eliminate this warning.","https://tailwindcss.com/docs/content-configuration#safelisting-classes"]);continue}f.push(d)}if(f.length>0){let d=new Map,p=e.tailwindConfig.prefix.length,m=f.some(b=>b.pattern.source.includes("!"));for(let b of a){let x=Array.isArray(b)?(()=>{let[y,w]=b,S=Object.keys(w?.values??{}).map(_=>Kr(y,_));return w?.supportsNegativeValues&&(S=[...S,...S.map(_=>"-"+_)],S=[...S,...S.map(_=>_.slice(0,p)+"-"+_.slice(p))]),w.types.some(({type:_})=>_==="color")&&(S=[...S,...S.flatMap(_=>Object.keys(e.tailwindConfig.theme.opacity).map(E=>`${_}/${E}`))]),m&&w?.respectImportant&&(S=[...S,...S.map(_=>"!"+_)]),S})():[b];for(let y of x)for(let{pattern:w,variants:k=[]}of f)if(w.lastIndex=0,d.has(w)||d.set(w,0),!!w.test(y)){d.set(w,d.get(w)+1),e.changedContent.push({content:y,extension:"html"});for(let S of k)e.changedContent.push({content:S+e.tailwindConfig.separator+y,extension:"html"})}}for(let[b,x]of d.entries())x===0&&F.warn([`The safelist pattern \`${b}\` doesn't match any Tailwind CSS classes.`,"Fix this pattern or remove it from your `safelist` configuration.","https://tailwindcss.com/docs/content-configuration#safelisting-classes"])}}let u=[].concat(e.tailwindConfig.darkMode??"media")[1]??"dark",c=[yo(e,u),yo(e,"group"),yo(e,"peer")];e.getClassOrder=function(d){let p=[...d].sort((y,w)=>y===w?0:y[y,null])),b=_n(new Set(p),e,!0);b=e.offsets.sort(b);let x=BigInt(c.length);for(let[,y]of b){let w=y.raws.tailwind.candidate;m.set(w,m.get(w)??x++)}return d.map(y=>{let w=m.get(y)??null,k=c.indexOf(y);return w===null&&k!==-1&&(w=BigInt(k)),[y,w]})},e.getClassList=function(d={}){let p=[];for(let m of a)if(Array.isArray(m)){let[b,x]=m,y=[],w=Object.keys(x?.modifiers??{});x?.types?.some(({type:_})=>_==="color")&&w.push(...Object.keys(e.tailwindConfig.theme.opacity??{}));let k={modifiers:w},S=d.includeMetadata&&w.length>0;for(let[_,E]of Object.entries(x?.values??{})){if(E==null)continue;let I=Kr(b,_);if(p.push(S?[I,k]:I),x?.supportsNegativeValues&&Ke(E)){let q=Kr(b,`-${_}`);y.push(S?[q,k]:q)}}p.push(...y)}else p.push(m);return p},e.getVariants=function(){let d=Math.random().toString(36).substring(7).toUpperCase(),p=[];for(let[m,b]of e.variantOptions.entries())b.variantInfo!==go.Base&&p.push({name:m,isArbitrary:b.type===Symbol.for("MATCH_VARIANT"),values:Object.keys(b.values??{}),hasDash:m!=="@",selectors({modifier:x,value:y}={}){let w=`TAILWINDPLACEHOLDER${d}`,k=j.rule({selector:`.${w}`}),S=j.root({nodes:[k.clone()]}),_=S.toString(),E=(e.variantMap.get(m)??[]).flatMap(([oe,he])=>he),I=[];for(let oe of E){let he=[],ui={args:{modifier:x,value:b.values?.[y]??y},separator:e.tailwindConfig.separator,modifySelectors(Ce){return S.each(ts=>{ts.type==="rule"&&(ts.selectors=ts.selectors.map(mu=>Ce({get className(){return lo(mu)},selector:mu})))}),S},format(Ce){he.push(Ce)},wrap(Ce){he.push(`@${Ce.name} ${Ce.params} { & }`)},container:S},fi=oe(ui);if(he.length>0&&I.push(he),Array.isArray(fi))for(let Ce of fi)he=[],Ce(ui),I.push(he)}let q=[],R=S.toString();_!==R&&(S.walkRules(oe=>{let he=oe.selector,ui=(0,ho.default)(fi=>{fi.walkClasses(Ce=>{Ce.value=`${m}${e.tailwindConfig.separator}${Ce.value}`})}).processSync(he);q.push(he.replace(ui,"&").replace(w,"&"))}),S.walkAtRules(oe=>{q.push(`@${oe.name} (${oe.params}) { & }`)}));let J=!(y in(b.values??{})),ue=b[Zr]??{},de=(()=>!(J||ue.respectPrefix===!1))();I=I.map(oe=>oe.map(he=>({format:he,respectPrefix:de}))),q=q.map(oe=>({format:oe,respectPrefix:de}));let De={candidate:w,context:e},ee=I.map(oe=>kn(`.${w}`,Vt(oe,De),De).replace(`.${w}`,"&").replace("{ & }","").trim());return q.length>0&&ee.push(Vt(q,De).toString().replace(`.${w}`,"&")),ee}});return p}}function Qd(r,e){!r.classCache.has(e)||(r.notClassCache.add(e),r.classCache.delete(e),r.applyClassCache.delete(e),r.candidateRuleMap.delete(e),r.candidateRuleCache.delete(e),r.stylesheetCache=null)}function W2(r,e){let t=e.raws.tailwind.candidate;if(!!t){for(let i of r.ruleCache)i[1].raws.tailwind.candidate===t&&r.ruleCache.delete(i);Qd(r,t)}}function bo(r,e=[],t=j.root()){let i={disposables:[],ruleCache:new Set,candidateRuleCache:new Map,classCache:new Map,applyClassCache:new Map,notClassCache:new Set(r.blocklist??[]),postCssNodeCache:new Map,candidateRuleMap:new Map,tailwindConfig:r,changedContent:e,variantMap:new Map,stylesheetCache:null,variantOptions:new Map,markInvalidUtilityCandidate:a=>Qd(i,a),markInvalidUtilityNode:a=>W2(i,a)},n=V2(i,t);return U2(n,i),i}function Jd(r,e,t,i,n,a){let s=e.opts.from,o=i!==null;Pe.DEBUG&&console.log("Source path:",s);let u;if(o&&Ut.has(s))u=Ut.get(s);else if(ii.has(n)){let p=ii.get(n);ut.get(p).add(s),Ut.set(s,p),u=p}let c=Fd(s,r);if(u){let[p,m]=Hd([...a],Dn(u));if(!p&&!c)return[u,!1,m]}if(Ut.has(s)){let p=Ut.get(s);if(ut.has(p)&&(ut.get(p).delete(s),ut.get(p).size===0)){ut.delete(p);for(let[m,b]of ii)b===p&&ii.delete(m);for(let m of p.disposables.splice(0))m(p)}}Pe.DEBUG&&console.log("Setting up new context...");let f=bo(t,[],r);Object.assign(f,{userConfigPath:i});let[,d]=Hd([...a],Dn(f));return ii.set(n,f),Ut.set(s,f),ut.has(f)||ut.set(f,new Set),ut.get(f).add(s),[f,!0,d]}var Ud,ho,Zr,mo,go,wo,Ut,ii,ut,ei=C(()=>{l();ze();Cs();st();Ud=X(Gs()),ho=X(Me());Jr();Qa();dn();At();$t();Xa();hr();Cd();lt();lt();gi();Oe();di();eo();On();Ld();Vd();je();so();Zr=Symbol(),mo={AddVariant:Symbol.for("ADD_VARIANT"),MatchVariant:Symbol.for("MATCH_VARIANT")},go={Base:1<<0,Dynamic:1<<1};wo=new WeakMap;Ut=Ad,ii=_d,ut=vn});function vo(r){return r.ignore?[]:r.glob?h.env.ROLLUP_WATCH==="true"?[{type:"dependency",file:r.base}]:[{type:"dir-dependency",dir:r.base,glob:r.glob}]:[{type:"dependency",file:r.base}]}var Xd=C(()=>{l()});function Kd(r,e){return{handler:r,config:e}}var Zd,eh=C(()=>{l();Kd.withOptions=function(r,e=()=>({})){let t=function(i){return{__options:i,handler:r(i),config:e(i)}};return t.__isOptionsFunction=!0,t.__pluginFunction=r,t.__configFunction=e,t};Zd=Kd});var In={};Ae(In,{default:()=>G2});var G2,qn=C(()=>{l();eh();G2=Zd});var rh=v((M6,th)=>{l();var H2=(qn(),In).default,Y2={overflow:"hidden",display:"-webkit-box","-webkit-box-orient":"vertical"},Q2=H2(function({matchUtilities:r,addUtilities:e,theme:t,variants:i}){let n=t("lineClamp");r({"line-clamp":a=>({...Y2,"-webkit-line-clamp":`${a}`})},{values:n}),e([{".line-clamp-none":{"-webkit-line-clamp":"unset"}}],i("lineClamp"))},{theme:{lineClamp:{1:"1",2:"2",3:"3",4:"4",5:"5",6:"6"}},variants:{lineClamp:["responsive"]}});th.exports=Q2});function xo(r){r.content.files.length===0&&F.warn("content-problems",["The `content` option in your Tailwind CSS configuration is missing or empty.","Configure your content sources or your generated CSS will be missing styles.","https://tailwindcss.com/docs/content-configuration"]);try{let e=rh();r.plugins.includes(e)&&(F.warn("line-clamp-in-core",["As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default.","Remove it from the `plugins` array in your configuration to eliminate this warning."]),r.plugins=r.plugins.filter(t=>t!==e))}catch{}return r}var ih=C(()=>{l();Oe()});var nh,sh=C(()=>{l();nh=()=>!1});var Rn,ah=C(()=>{l();Rn={sync:r=>[].concat(r),generateTasks:r=>[{dynamic:!1,base:".",negative:[],positive:[].concat(r),patterns:[].concat(r)}],escapePath:r=>r}});var ko,oh=C(()=>{l();ko=r=>r});var lh,uh=C(()=>{l();lh=()=>""});function fh(r){let e=r,t=lh(r);return t!=="."&&(e=r.substr(t.length),e.charAt(0)==="/"&&(e=e.substr(1))),e.substr(0,2)==="./"&&(e=e.substr(2)),e.charAt(0)==="/"&&(e=e.substr(1)),{base:t,glob:e}}var ch=C(()=>{l();uh()});function ph(r,e){let t=e.content.files;t=t.filter(o=>typeof o=="string"),t=t.map(ko);let i=Rn.generateTasks(t),n=[],a=[];for(let o of i)n.push(...o.positive.map(u=>dh(u,!1))),a.push(...o.negative.map(u=>dh(u,!0)));let s=[...n,...a];return s=X2(r,s),s=s.flatMap(K2),s=s.map(J2),s}function dh(r,e){let t={original:r,base:r,ignore:e,pattern:r,glob:null};return nh(r)&&Object.assign(t,fh(r)),t}function J2(r){let e=ko(r.base);return e=Rn.escapePath(e),r.pattern=r.glob?`${e}/${r.glob}`:e,r.pattern=r.ignore?`!${r.pattern}`:r.pattern,r}function X2(r,e){let t=[];return r.userConfigPath&&r.tailwindConfig.content.relative&&(t=[Z.dirname(r.userConfigPath)]),e.map(i=>(i.base=Z.resolve(...t,i.base),i))}function K2(r){let e=[r];try{let t=te.realpathSync(r.base);t!==r.base&&e.push({...r,base:t})}catch{}return e}function hh(r,e,t){let i=r.tailwindConfig.content.files.filter(s=>typeof s.raw=="string").map(({raw:s,extension:o="html"})=>({content:s,extension:o})),[n,a]=Z2(e,t);for(let s of n){let o=Z.extname(s).slice(1);i.push({file:s,extension:o})}return[i,a]}function Z2(r,e){let t=r.map(s=>s.pattern),i=new Map,n=new Set;Pe.DEBUG&&console.time("Finding changed files");let a=Rn.sync(t,{absolute:!0});for(let s of a){let o=e.get(s)||-1/0,u=te.statSync(s).mtimeMs;u>o&&(n.add(s),i.set(s,u))}return Pe.DEBUG&&console.timeEnd("Finding changed files"),[n,i]}var mh=C(()=>{l();ze();bt();sh();ah();oh();ch();lt()});function gh(){}var yh=C(()=>{l()});function iC(r,e){for(let t of e){let i=`${r}${t}`;if(te.existsSync(i)&&te.statSync(i).isFile())return i}for(let t of e){let i=`${r}/index${t}`;if(te.existsSync(i))return i}return null}function*wh(r,e,t,i=Z.extname(r)){let n=iC(Z.resolve(e,r),eC.includes(i)?tC:rC);if(n===null||t.has(n))return;t.add(n),yield n,e=Z.dirname(n),i=Z.extname(n);let a=te.readFileSync(n,"utf-8");for(let s of[...a.matchAll(/import[\s\S]*?['"](.{3,}?)['"]/gi),...a.matchAll(/import[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi),...a.matchAll(/require\(['"`](.+)['"`]\)/gi)])!s[1].startsWith(".")||(yield*wh(s[1],e,t,i))}function So(r){return r===null?new Set:new Set(wh(r,Z.dirname(r),new Set))}var eC,tC,rC,bh=C(()=>{l();ze();bt();eC=[".js",".cjs",".mjs"],tC=["",".js",".cjs",".mjs",".ts",".cts",".mts",".jsx",".tsx"],rC=["",".ts",".cts",".mts",".tsx",".js",".cjs",".mjs",".jsx"]});function nC(r,e){if(Co.has(r))return Co.get(r);let t=ph(r,e);return Co.set(r,t).get(r)}function sC(r){let e=ks(r);if(e!==null){let[i,n,a,s]=xh.get(e)||[],o=So(e),u=!1,c=new Map;for(let p of o){let m=te.statSync(p).mtimeMs;c.set(p,m),(!s||!s.has(p)||m>s.get(p))&&(u=!0)}if(!u)return[i,e,n,a];for(let p of o)delete yu.cache[p];let f=xo(gr(gh(e))),d=pi(f);return xh.set(e,[f,d,o,c]),[f,e,d,o]}let t=gr(r?.config??r??{});return t=xo(t),[t,null,pi(t),[]]}function Ao(r){return({tailwindDirectives:e,registerDependency:t})=>(i,n)=>{let[a,s,o,u]=sC(r),c=new Set(u);if(e.size>0){c.add(n.opts.from);for(let b of n.messages)b.type==="dependency"&&c.add(b.file)}let[f,,d]=Jd(i,n,a,s,o,c),p=Dn(f),m=nC(f,a);if(e.size>0){for(let y of m)for(let w of vo(y))t(w);let[b,x]=hh(f,m,p);for(let y of b)f.changedContent.push(y);for(let[y,w]of x.entries())d.set(y,w)}for(let b of u)t({type:"dependency",file:b});for(let[b,x]of d.entries())p.set(b,x);return f}}var vh,xh,Co,kh=C(()=>{l();ze();vh=X(rs());ku();xs();cf();ei();Xd();ih();mh();yh();bh();xh=new vh.default({maxSize:100}),Co=new WeakMap});function _o(r){let e=new Set,t=new Set,i=new Set;if(r.walkAtRules(n=>{n.name==="apply"&&i.add(n),n.name==="import"&&(n.params==='"tailwindcss/base"'||n.params==="'tailwindcss/base'"?(n.name="tailwind",n.params="base"):n.params==='"tailwindcss/components"'||n.params==="'tailwindcss/components'"?(n.name="tailwind",n.params="components"):n.params==='"tailwindcss/utilities"'||n.params==="'tailwindcss/utilities'"?(n.name="tailwind",n.params="utilities"):(n.params==='"tailwindcss/screens"'||n.params==="'tailwindcss/screens'"||n.params==='"tailwindcss/variants"'||n.params==="'tailwindcss/variants'")&&(n.name="tailwind",n.params="variants")),n.name==="tailwind"&&(n.params==="screens"&&(n.params="variants"),e.add(n.params)),["layer","responsive","variants"].includes(n.name)&&(["responsive","variants"].includes(n.name)&&F.warn(`${n.name}-at-rule-deprecated`,[`The \`@${n.name}\` directive has been deprecated in Tailwind CSS v3.0.`,"Use `@layer utilities` or `@layer components` instead.","https://tailwindcss.com/docs/upgrade-guide#replace-variants-with-layer"]),t.add(n))}),!e.has("base")||!e.has("components")||!e.has("utilities")){for(let n of t)if(n.name==="layer"&&["base","components","utilities"].includes(n.params)){if(!e.has(n.params))throw n.error(`\`@layer ${n.params}\` is used but no matching \`@tailwind ${n.params}\` directive is present.`)}else if(n.name==="responsive"){if(!e.has("utilities"))throw n.error("`@responsive` is used but `@tailwind utilities` is missing.")}else if(n.name==="variants"&&!e.has("utilities"))throw n.error("`@variants` is used but `@tailwind utilities` is missing.")}return{tailwindDirectives:e,applyDirectives:i}}var Sh=C(()=>{l();Oe()});function St(r,e=void 0,t=void 0){return r.map(i=>{let n=i.clone();return t!==void 0&&(n.raws.tailwind={...n.raws.tailwind,...t}),e!==void 0&&Ch(n,a=>{if(a.raws.tailwind?.preserveSource===!0&&a.source)return!1;a.source=e}),n})}function Ch(r,e){e(r)!==!1&&r.each?.(t=>Ch(t,e))}var Ah=C(()=>{l()});function Oo(r){return r=Array.isArray(r)?r:[r],r=r.map(e=>e instanceof RegExp?e.source:e),r.join("")}function ye(r){return new RegExp(Oo(r),"g")}function ft(r){return`(?:${r.map(Oo).join("|")})`}function Eo(r){return`(?:${Oo(r)})?`}function Oh(r){return r&&aC.test(r)?r.replace(_h,"\\$&"):r||""}var _h,aC,Eh=C(()=>{l();_h=/[\\^$.*+?()[\]{}|]/g,aC=RegExp(_h.source)});function Th(r){let e=Array.from(oC(r));return t=>{let i=[];for(let n of e)for(let a of t.match(n)??[])i.push(fC(a));return i}}function*oC(r){let e=r.tailwindConfig.separator,t=r.tailwindConfig.prefix!==""?Eo(ye([/-?/,Oh(r.tailwindConfig.prefix)])):"",i=ft([/\[[^\s:'"`]+:[^\s\[\]]+\]/,/\[[^\s:'"`\]]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,ye([ft([/-?(?:\w+)/,/@(?:\w+)/]),Eo(ft([ye([ft([/-(?:\w+-)*\['[^\s]+'\]/,/-(?:\w+-)*\["[^\s]+"\]/,/-(?:\w+-)*\[`[^\s]+`\]/,/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s:\[\]]+\]/]),/(?![{([]])/,/(?:\/[^\s'"`\\><$]*)?/]),ye([ft([/-(?:\w+-)*\['[^\s]+'\]/,/-(?:\w+-)*\["[^\s]+"\]/,/-(?:\w+-)*\[`[^\s]+`\]/,/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s\[\]]+\]/]),/(?![{([]])/,/(?:\/[^\s'"`\\$]*)?/]),/[-\/][^\s'"`\\$={><]*/]))])]),n=[ft([ye([/@\[[^\s"'`]+\](\/[^\s"'`]+)?/,e]),ye([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/[\w_-]+/,e]),ye([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/,e]),ye([/[^\s"'`\[\\]+/,e])]),ft([ye([/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/[\w_-]+/,e]),ye([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/,e]),ye([/[^\s`\[\\]+/,e])])];for(let a of n)yield ye(["((?=((",a,")+))\\2)?",/!?/,t,i]);yield/[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g}function fC(r){if(!r.includes("-["))return r;let e=0,t=[],i=r.matchAll(lC);i=Array.from(i).flatMap(n=>{let[,...a]=n;return a.map((s,o)=>Object.assign([],n,{index:n.index+o,0:s}))});for(let n of i){let a=n[0],s=t[t.length-1];if(a===s?t.pop():(a==="'"||a==='"'||a==="`")&&t.push(a),!s){if(a==="["){e++;continue}else if(a==="]"){e--;continue}if(e<0)return r.substring(0,n.index-1);if(e===0&&!uC.test(a))return r.substring(0,n.index)}}return r}var lC,uC,Ph=C(()=>{l();Eh();lC=/([\[\]'"`])([^\[\]'"`])?/g,uC=/[^"'`\s<>\]]+/});function cC(r,e){let t=r.tailwindConfig.content.extract;return t[e]||t.DEFAULT||Ih[e]||Ih.DEFAULT(r)}function pC(r,e){let t=r.content.transform;return t[e]||t.DEFAULT||qh[e]||qh.DEFAULT}function dC(r,e,t,i){ni.has(e)||ni.set(e,new Dh.default({maxSize:25e3}));for(let n of r.split(` -`))if(n=n.trim(),!i.has(n))if(i.add(n),ni.get(e).has(n))for(let a of ni.get(e).get(n))t.add(a);else{let a=e(n).filter(o=>o!=="!*"),s=new Set(a);for(let o of s)t.add(o);ni.get(e).set(n,s)}}function hC(r,e){let t=e.offsets.sort(r),i={base:new Set,defaults:new Set,components:new Set,utilities:new Set,variants:new Set};for(let[n,a]of t)i[n.layer].add(a);return i}function To(r){return async e=>{let t={base:null,components:null,utilities:null,variants:null};if(e.walkAtRules(y=>{y.name==="tailwind"&&Object.keys(t).includes(y.params)&&(t[y.params]=y)}),Object.values(t).every(y=>y===null))return e;let i=new Set([...r.candidates??[],He]),n=new Set;Ye.DEBUG&&console.time("Reading changed files");let a=[];for(let y of r.changedContent){let w=pC(r.tailwindConfig,y.extension),k=cC(r,y.extension);a.push([y,{transformer:w,extractor:k}])}let s=500;for(let y=0;y{S=k?await te.promises.readFile(k,"utf8"):S,dC(_(S),E,i,n)}))}Ye.DEBUG&&console.timeEnd("Reading changed files");let o=r.classCache.size;Ye.DEBUG&&console.time("Generate rules"),Ye.DEBUG&&console.time("Sorting candidates");let u=new Set([...i].sort((y,w)=>y===w?0:y{let w=y.raws.tailwind?.parentLayer;return w==="components"?t.components!==null:w==="utilities"?t.utilities!==null:!0});t.variants?(t.variants.before(St(b,t.variants.source,{layer:"variants"})),t.variants.remove()):b.length>0&&e.append(St(b,e.source,{layer:"variants"})),e.source.end=e.source.end??e.source.start;let x=b.some(y=>y.raws.tailwind?.parentLayer==="utilities");t.utilities&&p.size===0&&!x&&F.warn("content-problems",["No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.","https://tailwindcss.com/docs/content-configuration"]),Ye.DEBUG&&(console.log("Potential classes: ",i.size),console.log("Active contexts: ",vn.size)),r.changedContent=[],e.walkAtRules("layer",y=>{Object.keys(t).includes(y.params)&&y.remove()})}}var Dh,Ye,Ih,qh,ni,Rh=C(()=>{l();ze();Dh=X(rs());lt();On();Oe();Ah();Ph();Ye=Pe,Ih={DEFAULT:Th},qh={DEFAULT:r=>r,svelte:r=>r.replace(/(?:^|\s)class:/g," ")};ni=new WeakMap});function Bn(r){let e=new Map;j.root({nodes:[r.clone()]}).walkRules(a=>{(0,Mn.default)(s=>{s.walkClasses(o=>{let u=o.parent.toString(),c=e.get(u);c||e.set(u,c=new Set),c.add(o.value)})}).processSync(a.selector)});let i=Array.from(e.values(),a=>Array.from(a)),n=i.flat();return Object.assign(n,{groups:i})}function Po(r){return mC.astSync(r)}function Mh(r,e){let t=new Set;for(let i of r)t.add(i.split(e).pop());return Array.from(t)}function Bh(r,e){let t=r.tailwindConfig.prefix;return typeof t=="function"?t(e):t+e}function*Fh(r){for(yield r;r.parent;)yield r.parent,r=r.parent}function gC(r,e={}){let t=r.nodes;r.nodes=[];let i=r.clone(e);return r.nodes=t,i}function yC(r){for(let e of Fh(r))if(r!==e){if(e.type==="root")break;r=gC(e,{nodes:[r]})}return r}function wC(r,e){let t=new Map;return r.walkRules(i=>{for(let s of Fh(i))if(s.raws.tailwind?.layer!==void 0)return;let n=yC(i),a=e.offsets.create("user");for(let s of Bn(i)){let o=t.get(s)||[];t.set(s,o),o.push([{layer:"user",sort:a,important:!1},n])}}),t}function bC(r,e){for(let t of r){if(e.notClassCache.has(t)||e.applyClassCache.has(t))continue;if(e.classCache.has(t)){e.applyClassCache.set(t,e.classCache.get(t).map(([n,a])=>[n,a.clone()]));continue}let i=Array.from(fo(t,e));if(i.length===0){e.notClassCache.add(t);continue}e.applyClassCache.set(t,i)}return e.applyClassCache}function vC(r){let e=null;return{get:t=>(e=e||r(),e.get(t)),has:t=>(e=e||r(),e.has(t))}}function xC(r){return{get:e=>r.flatMap(t=>t.get(e)||[]),has:e=>r.some(t=>t.has(e))}}function Lh(r){let e=r.split(/[\s\t\n]+/g);return e[e.length-1]==="!important"?[e.slice(0,-1),!0]:[e,!1]}function Nh(r,e,t){let i=new Set,n=[];if(r.walkAtRules("apply",u=>{let[c]=Lh(u.params);for(let f of c)i.add(f);n.push(u)}),n.length===0)return;let a=xC([t,bC(i,e)]);function s(u,c,f){let d=Po(u),p=Po(c),b=Po(`.${ce(f)}`).nodes[0].nodes[0];return d.each(x=>{let y=new Set;p.each(w=>{let k=!1;w=w.clone(),w.walkClasses(S=>{S.value===b.value&&(k||(S.replaceWith(...x.nodes.map(_=>_.clone())),y.add(w),k=!0))})});for(let w of y){let k=[[]];for(let S of w.nodes)S.type==="combinator"?(k.push(S),k.push([])):k[k.length-1].push(S);w.nodes=[];for(let S of k)Array.isArray(S)&&S.sort((_,E)=>_.type==="tag"&&E.type==="class"?-1:_.type==="class"&&E.type==="tag"?1:_.type==="class"&&E.type==="pseudo"&&E.value.startsWith("::")?-1:_.type==="pseudo"&&_.value.startsWith("::")&&E.type==="class"?1:0),w.nodes=w.nodes.concat(S)}x.replaceWith(...y)}),d.toString()}let o=new Map;for(let u of n){let[c]=o.get(u.parent)||[[],u.source];o.set(u.parent,[c,u.source]);let[f,d]=Lh(u.params);if(u.parent.type==="atrule"){if(u.parent.name==="screen"){let p=u.parent.params;throw u.error(`@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${f.map(m=>`${p}:${m}`).join(" ")} instead.`)}throw u.error(`@apply is not supported within nested at-rules like @${u.parent.name}. You can fix this by un-nesting @${u.parent.name}.`)}for(let p of f){if([Bh(e,"group"),Bh(e,"peer")].includes(p))throw u.error(`@apply should not be used with the '${p}' utility`);if(!a.has(p))throw u.error(`The \`${p}\` class does not exist. If \`${p}\` is a custom class, make sure it is defined within a \`@layer\` directive.`);let m=a.get(p);for(let[,b]of m)b.type!=="atrule"&&b.walkRules(()=>{throw u.error([`The \`${p}\` class cannot be used with \`@apply\` because \`@apply\` does not currently support nested CSS.`,"Rewrite the selector without nesting or configure the `tailwindcss/nesting` plugin:","https://tailwindcss.com/docs/using-with-preprocessors#nesting"].join(` -`))});c.push([p,d,m])}}for(let[u,[c,f]]of o){let d=[];for(let[m,b,x]of c){let y=[m,...Mh([m],e.tailwindConfig.separator)];for(let[w,k]of x){let S=Bn(u),_=Bn(k);if(_=_.groups.filter(R=>R.some(J=>y.includes(J))).flat(),_=_.concat(Mh(_,e.tailwindConfig.separator)),S.some(R=>_.includes(R)))throw k.error(`You cannot \`@apply\` the \`${m}\` utility here because it creates a circular dependency.`);let I=j.root({nodes:[k.clone()]});I.walk(R=>{R.source=f}),(k.type!=="atrule"||k.type==="atrule"&&k.name!=="keyframes")&&I.walkRules(R=>{if(!Bn(R).some(ee=>ee===m)){R.remove();return}let J=typeof e.tailwindConfig.important=="string"?e.tailwindConfig.important:null,de=u.raws.tailwind!==void 0&&J&&u.selector.indexOf(J)===0?u.selector.slice(J.length):u.selector;de===""&&(de=u.selector),R.selector=s(de,R.selector,m),J&&de!==u.selector&&(R.selector=Sn(R.selector,J)),R.walkDecls(ee=>{ee.important=w.important||b});let De=(0,Mn.default)().astSync(R.selector);De.each(ee=>jt(ee)),R.selector=De.toString()}),!!I.nodes[0]&&d.push([w.sort,I.nodes[0]])}}let p=e.offsets.sort(d).map(m=>m[1]);u.after(p)}for(let u of n)u.parent.nodes.length>1?u.remove():u.parent.remove();Nh(r,e,t)}function Do(r){return e=>{let t=vC(()=>wC(e,r));Nh(e,r,t)}}var Mn,mC,$h=C(()=>{l();st();Mn=X(Me());On();$t();oo();xn();mC=(0,Mn.default)()});var zh=v((I4,Fn)=>{l();(function(){"use strict";function r(i,n,a){if(!i)return null;r.caseSensitive||(i=i.toLowerCase());var s=r.threshold===null?null:r.threshold*i.length,o=r.thresholdAbsolute,u;s!==null&&o!==null?u=Math.min(s,o):s!==null?u=s:o!==null?u=o:u=null;var c,f,d,p,m,b=n.length;for(m=0;ma)return a+1;var u=[],c,f,d,p,m;for(c=0;c<=o;c++)u[c]=[c];for(f=0;f<=s;f++)u[0][f]=f;for(c=1;c<=o;c++){for(d=e,p=1,c>a&&(p=c-a),m=o+1,m>a+c&&(m=a+c),f=1;f<=s;f++)fm?u[c][f]=a+1:n.charAt(c-1)===i.charAt(f-1)?u[c][f]=u[c-1][f-1]:u[c][f]=Math.min(u[c-1][f-1]+1,Math.min(u[c][f-1]+1,u[c-1][f]+1)),u[c][f]a)return a+1}return u[o][s]}})()});var Vh=v((q4,jh)=>{l();var Io="(".charCodeAt(0),qo=")".charCodeAt(0),Ln="'".charCodeAt(0),Ro='"'.charCodeAt(0),Mo="\\".charCodeAt(0),Wt="/".charCodeAt(0),Bo=",".charCodeAt(0),Fo=":".charCodeAt(0),Nn="*".charCodeAt(0),kC="u".charCodeAt(0),SC="U".charCodeAt(0),CC="+".charCodeAt(0),AC=/^[a-f0-9?-]+$/i;jh.exports=function(r){for(var e=[],t=r,i,n,a,s,o,u,c,f,d=0,p=t.charCodeAt(d),m=t.length,b=[{nodes:e}],x=0,y,w="",k="",S="";d{l();Uh.exports=function r(e,t,i){var n,a,s,o;for(n=0,a=e.length;n{l();function Gh(r,e){var t=r.type,i=r.value,n,a;return e&&(a=e(r))!==void 0?a:t==="word"||t==="space"?i:t==="string"?(n=r.quote||"",n+i+(r.unclosed?"":n)):t==="comment"?"/*"+i+(r.unclosed?"":"*/"):t==="div"?(r.before||"")+i+(r.after||""):Array.isArray(r.nodes)?(n=Hh(r.nodes,e),t!=="function"?n:i+"("+(r.before||"")+n+(r.after||"")+(r.unclosed?"":")")):i}function Hh(r,e){var t,i;if(Array.isArray(r)){for(t="",i=r.length-1;~i;i-=1)t=Gh(r[i],e)+t;return t}return Gh(r,e)}Yh.exports=Hh});var Xh=v((B4,Jh)=>{l();var $n="-".charCodeAt(0),zn="+".charCodeAt(0),Lo=".".charCodeAt(0),_C="e".charCodeAt(0),OC="E".charCodeAt(0);function EC(r){var e=r.charCodeAt(0),t;if(e===zn||e===$n){if(t=r.charCodeAt(1),t>=48&&t<=57)return!0;var i=r.charCodeAt(2);return t===Lo&&i>=48&&i<=57}return e===Lo?(t=r.charCodeAt(1),t>=48&&t<=57):e>=48&&e<=57}Jh.exports=function(r){var e=0,t=r.length,i,n,a;if(t===0||!EC(r))return!1;for(i=r.charCodeAt(e),(i===zn||i===$n)&&e++;e57));)e+=1;if(i=r.charCodeAt(e),n=r.charCodeAt(e+1),i===Lo&&n>=48&&n<=57)for(e+=2;e57));)e+=1;if(i=r.charCodeAt(e),n=r.charCodeAt(e+1),a=r.charCodeAt(e+2),(i===_C||i===OC)&&(n>=48&&n<=57||(n===zn||n===$n)&&a>=48&&a<=57))for(e+=n===zn||n===$n?3:2;e57));)e+=1;return{number:r.slice(0,e),unit:r.slice(e)}}});var tm=v((F4,em)=>{l();var TC=Vh(),Kh=Wh(),Zh=Qh();function ct(r){return this instanceof ct?(this.nodes=TC(r),this):new ct(r)}ct.prototype.toString=function(){return Array.isArray(this.nodes)?Zh(this.nodes):""};ct.prototype.walk=function(r,e){return Kh(this.nodes,r,e),this};ct.unit=Xh();ct.walk=Kh;ct.stringify=Zh;em.exports=ct});function $o(r){return typeof r=="object"&&r!==null}function PC(r,e){let t=Ze(e);do if(t.pop(),(0,si.default)(r,t)!==void 0)break;while(t.length);return t.length?t:void 0}function Gt(r){return typeof r=="string"?r:r.reduce((e,t,i)=>t.includes(".")?`${e}[${t}]`:i===0?t:`${e}.${t}`,"")}function im(r){return r.map(e=>`'${e}'`).join(", ")}function nm(r){return im(Object.keys(r))}function zo(r,e,t,i={}){let n=Array.isArray(e)?Gt(e):e.replace(/^['"]+|['"]+$/g,""),a=Array.isArray(e)?e:Ze(n),s=(0,si.default)(r.theme,a,t);if(s===void 0){let u=`'${n}' does not exist in your theme config.`,c=a.slice(0,-1),f=(0,si.default)(r.theme,c);if($o(f)){let d=Object.keys(f).filter(m=>zo(r,[...c,m]).isValid),p=(0,rm.default)(a[a.length-1],d);p?u+=` Did you mean '${Gt([...c,p])}'?`:d.length>0&&(u+=` '${Gt(c)}' has the following valid keys: ${im(d)}`)}else{let d=PC(r.theme,n);if(d){let p=(0,si.default)(r.theme,d);$o(p)?u+=` '${Gt(d)}' has the following keys: ${nm(p)}`:u+=` '${Gt(d)}' is not an object.`}else u+=` Your theme has the following top-level keys: ${nm(r.theme)}`}return{isValid:!1,error:u}}if(!(typeof s=="string"||typeof s=="number"||typeof s=="function"||s instanceof String||s instanceof Number||Array.isArray(s))){let u=`'${n}' was found but does not resolve to a string.`;if($o(s)){let c=Object.keys(s).filter(f=>zo(r,[...a,f]).isValid);c.length&&(u+=` Did you mean something like '${Gt([...a,c[0]])}'?`)}return{isValid:!1,error:u}}let[o]=a;return{isValid:!0,value:Ge(o)(s,i)}}function DC(r,e,t){e=e.map(n=>sm(r,n,t));let i=[""];for(let n of e)n.type==="div"&&n.value===","?i.push(""):i[i.length-1]+=No.default.stringify(n);return i}function sm(r,e,t){if(e.type==="function"&&t[e.value]!==void 0){let i=DC(r,e.nodes,t);e.type="word",e.value=t[e.value](r,...i)}return e}function IC(r,e,t){return Object.keys(t).some(n=>e.includes(`${n}(`))?(0,No.default)(e).walk(n=>{sm(r,n,t)}).toString():e}function*RC(r){r=r.replace(/^['"]+|['"]+$/g,"");let e=r.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/),t;yield[r,void 0],e&&(r=e[1],t=e[2],yield[r,t])}function MC(r,e,t){let i=Array.from(RC(e)).map(([n,a])=>Object.assign(zo(r,n,t,{opacityValue:a}),{resolvedPath:n,alpha:a}));return i.find(n=>n.isValid)??i[0]}function am(r){let e=r.tailwindConfig,t={theme:(i,n,...a)=>{let{isValid:s,value:o,error:u,alpha:c}=MC(e,n,a.length?a:void 0);if(!s){let p=i.parent,m=p?.raws.tailwind?.candidate;if(p&&m!==void 0){r.markInvalidUtilityNode(p),p.remove(),F.warn("invalid-theme-key-in-class",[`The utility \`${m}\` contains an invalid theme value and was not generated.`]);return}throw i.error(u)}let f=Ot(o),d=f!==void 0&&typeof f=="function";return(c!==void 0||d)&&(c===void 0&&(c=1),o=Ie(f,c,f)),o},screen:(i,n)=>{n=n.replace(/^['"]+/g,"").replace(/['"]+$/g,"");let s=ot(e.theme.screens).find(({name:o})=>o===n);if(!s)throw i.error(`The '${n}' screen does not exist in your theme.`);return at(s)}};return i=>{i.walk(n=>{let a=qC[n.type];a!==void 0&&(n[a]=IC(n,n[a],t))})}}var si,rm,No,qC,om=C(()=>{l();si=X(Gs()),rm=X(zh());Jr();No=X(tm());wn();mn();gi();fr();hr();Oe();qC={atrule:"params",decl:"value"}});function lm({tailwindConfig:{theme:r}}){return function(e){e.walkAtRules("screen",t=>{let i=t.params,a=ot(r.screens).find(({name:s})=>s===i);if(!a)throw t.error(`No \`${i}\` screen found.`);t.name="media",t.params=at(a)})}}var um=C(()=>{l();wn();mn()});function BC(r){let e=r.filter(o=>o.type!=="pseudo"||o.nodes.length>0?!0:o.value.startsWith("::")||[":before",":after",":first-line",":first-letter"].includes(o.value)).reverse(),t=new Set(["tag","class","id","attribute"]),i=e.findIndex(o=>t.has(o.type));if(i===-1)return e.reverse().join("").trim();let n=e[i],a=fm[n.type]?fm[n.type](n):n;e=e.slice(0,i);let s=e.findIndex(o=>o.type==="combinator"&&o.value===">");return s!==-1&&(e.splice(0,s),e.unshift(jn.default.universal())),[a,...e.reverse()].join("").trim()}function LC(r){return jo.has(r)||jo.set(r,FC.transformSync(r)),jo.get(r)}function Vo({tailwindConfig:r}){return e=>{let t=new Map,i=new Set;if(e.walkAtRules("defaults",n=>{if(n.nodes&&n.nodes.length>0){i.add(n);return}let a=n.params;t.has(a)||t.set(a,new Set),t.get(a).add(n.parent),n.remove()}),K(r,"optimizeUniversalDefaults"))for(let n of i){let a=new Map,s=t.get(n.params)??[];for(let o of s)for(let u of LC(o.selector)){let c=u.includes(":-")||u.includes("::-")||u.includes(":has")?u:"__DEFAULT__",f=a.get(c)??new Set;a.set(c,f),f.add(u)}if(K(r,"optimizeUniversalDefaults")){if(a.size===0){n.remove();continue}for(let[,o]of a){let u=j.rule({source:n.source});u.selectors=[...o],u.append(n.nodes.map(c=>c.clone())),n.before(u)}}n.remove()}else if(i.size){let n=j.rule({selectors:["*","::before","::after"]});for(let s of i)n.append(s.nodes),n.parent||s.before(n),n.source||(n.source=s.source),s.remove();let a=n.clone({selectors:["::backdrop"]});n.after(a)}}}var jn,fm,FC,jo,cm=C(()=>{l();st();jn=X(Me());je();fm={id(r){return jn.default.attribute({attribute:"id",operator:"=",value:r.value,quoteMark:'"'})}};FC=(0,jn.default)(r=>r.map(e=>{let t=e.split(i=>i.type==="combinator"&&i.value===" ").pop();return BC(t)})),jo=new Map});function Uo(){function r(e){let t=null;e.each(i=>{if(!NC.has(i.type)){t=null;return}if(t===null){t=i;return}let n=pm[i.type];i.type==="atrule"&&i.name==="font-face"?t=i:n.every(a=>(i[a]??"").replace(/\s+/g," ")===(t[a]??"").replace(/\s+/g," "))?(i.nodes&&t.append(i.nodes),i.remove()):t=i}),e.each(i=>{i.type==="atrule"&&r(i)})}return e=>{r(e)}}var pm,NC,dm=C(()=>{l();pm={atrule:["name","params"],rule:["selector"]},NC=new Set(Object.keys(pm))});function Wo(){return r=>{r.walkRules(e=>{let t=new Map,i=new Set([]),n=new Map;e.walkDecls(a=>{if(a.parent===e){if(t.has(a.prop)){if(t.get(a.prop).value===a.value){i.add(t.get(a.prop)),t.set(a.prop,a);return}n.has(a.prop)||n.set(a.prop,new Set),n.get(a.prop).add(t.get(a.prop)),n.get(a.prop).add(a)}t.set(a.prop,a)}});for(let a of i)a.remove();for(let a of n.values()){let s=new Map;for(let o of a){let u=zC(o.value);u!==null&&(s.has(u)||s.set(u,new Set),s.get(u).add(o))}for(let o of s.values()){let u=Array.from(o).slice(0,-1);for(let c of u)c.remove()}}})}}function zC(r){let e=/^-?\d*.?\d+([\w%]+)?$/g.exec(r);return e?e[1]??$C:null}var $C,hm=C(()=>{l();$C=Symbol("unitless-number")});function jC(r){if(!r.walkAtRules)return;let e=new Set;if(r.walkAtRules("apply",t=>{e.add(t.parent)}),e.size!==0)for(let t of e){let i=[],n=[];for(let a of t.nodes)a.type==="atrule"&&a.name==="apply"?(n.length>0&&(i.push(n),n=[]),i.push([a])):n.push(a);if(n.length>0&&i.push(n),i.length!==1){for(let a of[...i].reverse()){let s=t.clone({nodes:[]});s.append(a),t.after(s)}t.remove()}}}function Vn(){return r=>{jC(r)}}var mm=C(()=>{l()});function Un(r){return async function(e,t){let{tailwindDirectives:i,applyDirectives:n}=_o(e);Vn()(e,t);let a=r({tailwindDirectives:i,applyDirectives:n,registerDependency(s){t.messages.push({plugin:"tailwindcss",parent:t.opts.from,...s})},createContext(s,o){return bo(s,o,e)}})(e,t);if(a.tailwindConfig.separator==="-")throw new Error("The '-' character cannot be used as a custom separator in JIT mode due to parsing ambiguity. Please use another character like '_' instead.");Iu(a.tailwindConfig),await To(a)(e,t),Vn()(e,t),Do(a)(e,t),am(a)(e,t),lm(a)(e,t),Vo(a)(e,t),Uo(a)(e,t),Wo(a)(e,t)}}var gm=C(()=>{l();Sh();Rh();$h();om();um();cm();dm();hm();mm();ei();je()});function ym(r,e){let t=null,i=null;return r.walkAtRules("config",n=>{if(i=n.source?.input.file??e.opts.from??null,i===null)throw n.error("The `@config` directive cannot be used without setting `from` in your PostCSS config.");if(t)throw n.error("Only one `@config` directive is allowed per file.");let a=n.params.match(/(['"])(.*?)\1/);if(!a)throw n.error("A path is required when using the `@config` directive.");let s=a[2];if(Z.isAbsolute(s))throw n.error("The `@config` directive cannot be used with an absolute path.");if(t=Z.resolve(Z.dirname(i),s),!te.existsSync(t))throw n.error(`The config file at "${s}" does not exist. Make sure the path is correct and the file exists.`);n.remove()}),t||null}var wm=C(()=>{l();ze();bt()});var bm=v((vD,Go)=>{l();kh();gm();lt();wm();Go.exports=function(e){return{postcssPlugin:"tailwindcss",plugins:[Pe.DEBUG&&function(t){return console.log(` -`),console.time("JIT TOTAL"),t},async function(t,i){e=ym(t,i)??e;let n=Ao(e);if(t.type==="document"){let a=t.nodes.filter(s=>s.type==="root");for(let s of a)s.type==="root"&&await Un(n)(s,i);return}await Un(n)(t,i)},Pe.DEBUG&&function(t){return console.timeEnd("JIT TOTAL"),console.log(` -`),t}].filter(Boolean)}};Go.exports.postcss=!0});var xm=v((xD,vm)=>{l();vm.exports=bm()});var Ho=v((kD,km)=>{l();km.exports=()=>["and_chr 114","and_uc 15.5","chrome 114","chrome 113","chrome 109","edge 114","firefox 114","ios_saf 16.5","ios_saf 16.4","ios_saf 16.3","ios_saf 16.1","opera 99","safari 16.5","samsung 21"]});var Wn={};Ae(Wn,{agents:()=>VC,feature:()=>UC});function UC(){return{status:"cr",title:"CSS Feature Queries",stats:{ie:{"6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","5.5":"n"},edge:{"12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","79":"y","80":"y","81":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","101":"y","102":"y","103":"y","104":"y","105":"y","106":"y","107":"y","108":"y","109":"y","110":"y","111":"y","112":"y","113":"y","114":"y"},firefox:{"2":"n","3":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y","40":"y","41":"y","42":"y","43":"y","44":"y","45":"y","46":"y","47":"y","48":"y","49":"y","50":"y","51":"y","52":"y","53":"y","54":"y","55":"y","56":"y","57":"y","58":"y","59":"y","60":"y","61":"y","62":"y","63":"y","64":"y","65":"y","66":"y","67":"y","68":"y","69":"y","70":"y","71":"y","72":"y","73":"y","74":"y","75":"y","76":"y","77":"y","78":"y","79":"y","80":"y","81":"y","82":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","101":"y","102":"y","103":"y","104":"y","105":"y","106":"y","107":"y","108":"y","109":"y","110":"y","111":"y","112":"y","113":"y","114":"y","115":"y","116":"y","117":"y","3.5":"n","3.6":"n"},chrome:{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y","40":"y","41":"y","42":"y","43":"y","44":"y","45":"y","46":"y","47":"y","48":"y","49":"y","50":"y","51":"y","52":"y","53":"y","54":"y","55":"y","56":"y","57":"y","58":"y","59":"y","60":"y","61":"y","62":"y","63":"y","64":"y","65":"y","66":"y","67":"y","68":"y","69":"y","70":"y","71":"y","72":"y","73":"y","74":"y","75":"y","76":"y","77":"y","78":"y","79":"y","80":"y","81":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","101":"y","102":"y","103":"y","104":"y","105":"y","106":"y","107":"y","108":"y","109":"y","110":"y","111":"y","112":"y","113":"y","114":"y","115":"y","116":"y","117":"y"},safari:{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","17":"y","9.1":"y","10.1":"y","11.1":"y","12.1":"y","13.1":"y","14.1":"y","15.1":"y","15.2-15.3":"y","15.4":"y","15.5":"y","15.6":"y","16.0":"y","16.1":"y","16.2":"y","16.3":"y","16.4":"y","16.5":"y","16.6":"y",TP:"y","3.1":"n","3.2":"n","5.1":"n","6.1":"n","7.1":"n"},opera:{"9":"n","11":"n","12":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y","40":"y","41":"y","42":"y","43":"y","44":"y","45":"y","46":"y","47":"y","48":"y","49":"y","50":"y","51":"y","52":"y","53":"y","54":"y","55":"y","56":"y","57":"y","58":"y","60":"y","62":"y","63":"y","64":"y","65":"y","66":"y","67":"y","68":"y","69":"y","70":"y","71":"y","72":"y","73":"y","74":"y","75":"y","76":"y","77":"y","78":"y","79":"y","80":"y","81":"y","82":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","12.1":"y","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11.1":"n","11.5":"n","11.6":"n"},ios_saf:{"8":"n","17":"y","9.0-9.2":"y","9.3":"y","10.0-10.2":"y","10.3":"y","11.0-11.2":"y","11.3-11.4":"y","12.0-12.1":"y","12.2-12.5":"y","13.0-13.1":"y","13.2":"y","13.3":"y","13.4-13.7":"y","14.0-14.4":"y","14.5-14.8":"y","15.0-15.1":"y","15.2-15.3":"y","15.4":"y","15.5":"y","15.6":"y","16.0":"y","16.1":"y","16.2":"y","16.3":"y","16.4":"y","16.5":"y","16.6":"y","3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8.1-8.4":"n"},op_mini:{all:"y"},android:{"3":"n","4":"n","114":"y","4.4":"y","4.4.3-4.4.4":"y","2.1":"n","2.2":"n","2.3":"n","4.1":"n","4.2-4.3":"n"},bb:{"7":"n","10":"n"},op_mob:{"10":"n","11":"n","12":"n","73":"y","11.1":"n","11.5":"n","12.1":"n"},and_chr:{"114":"y"},and_ff:{"115":"y"},ie_mob:{"10":"n","11":"n"},and_uc:{"15.5":"y"},samsung:{"4":"y","20":"y","21":"y","5.0-5.4":"y","6.2-6.4":"y","7.2-7.4":"y","8.2":"y","9.2":"y","10.1":"y","11.1-11.2":"y","12.0":"y","13.0":"y","14.0":"y","15.0":"y","16.0":"y","17.0":"y","18.0":"y","19.0":"y"},and_qq:{"13.1":"y"},baidu:{"13.18":"y"},kaios:{"2.5":"y","3.0-3.1":"y"}}}}var VC,Gn=C(()=>{l();VC={ie:{prefix:"ms"},edge:{prefix:"webkit",prefix_exceptions:{"12":"ms","13":"ms","14":"ms","15":"ms","16":"ms","17":"ms","18":"ms"}},firefox:{prefix:"moz"},chrome:{prefix:"webkit"},safari:{prefix:"webkit"},opera:{prefix:"webkit",prefix_exceptions:{"9":"o","11":"o","12":"o","9.5-9.6":"o","10.0-10.1":"o","10.5":"o","10.6":"o","11.1":"o","11.5":"o","11.6":"o","12.1":"o"}},ios_saf:{prefix:"webkit"},op_mini:{prefix:"o"},android:{prefix:"webkit"},bb:{prefix:"webkit"},op_mob:{prefix:"o",prefix_exceptions:{"73":"webkit"}},and_chr:{prefix:"webkit"},and_ff:{prefix:"moz"},ie_mob:{prefix:"ms"},and_uc:{prefix:"webkit",prefix_exceptions:{"15.5":"webkit"}},samsung:{prefix:"webkit"},and_qq:{prefix:"webkit"},baidu:{prefix:"webkit"},kaios:{prefix:"moz"}}});var Sm=v(()=>{l()});var le=v((AD,pt)=>{l();var{list:Yo}=ge();pt.exports.error=function(r){let e=new Error(r);throw e.autoprefixer=!0,e};pt.exports.uniq=function(r){return[...new Set(r)]};pt.exports.removeNote=function(r){return r.includes(" ")?r.split(" ")[0]:r};pt.exports.escapeRegexp=function(r){return r.replace(/[$()*+-.?[\\\]^{|}]/g,"\\$&")};pt.exports.regexp=function(r,e=!0){return e&&(r=this.escapeRegexp(r)),new RegExp(`(^|[\\s,(])(${r}($|[\\s(,]))`,"gi")};pt.exports.editList=function(r,e){let t=Yo.comma(r),i=e(t,[]);if(t===i)return r;let n=r.match(/,\s*/);return n=n?n[0]:", ",i.join(n)};pt.exports.splitSelector=function(r){return Yo.comma(r).map(e=>Yo.space(e).map(t=>t.split(/(?=\.|#)/g)))}});var dt=v((_D,_m)=>{l();var WC=Ho(),Cm=(Gn(),Wn).agents,GC=le(),Am=class{static prefixes(){if(this.prefixesCache)return this.prefixesCache;this.prefixesCache=[];for(let e in Cm)this.prefixesCache.push(`-${Cm[e].prefix}-`);return this.prefixesCache=GC.uniq(this.prefixesCache).sort((e,t)=>t.length-e.length),this.prefixesCache}static withPrefix(e){return this.prefixesRegexp||(this.prefixesRegexp=new RegExp(this.prefixes().join("|"))),this.prefixesRegexp.test(e)}constructor(e,t,i,n){this.data=e,this.options=i||{},this.browserslistOpts=n||{},this.selected=this.parse(t)}parse(e){let t={};for(let i in this.browserslistOpts)t[i]=this.browserslistOpts[i];return t.path=this.options.from,WC(e,t)}prefix(e){let[t,i]=e.split(" "),n=this.data[t],a=n.prefix_exceptions&&n.prefix_exceptions[i];return a||(a=n.prefix),`-${a}-`}isSelected(e){return this.selected.includes(e)}};_m.exports=Am});var ai=v((OD,Om)=>{l();Om.exports={prefix(r){let e=r.match(/^(-\w+-)/);return e?e[0]:""},unprefixed(r){return r.replace(/^-\w+-/,"")}}});var Ht=v((ED,Tm)=>{l();var HC=dt(),Em=ai(),YC=le();function Qo(r,e){let t=new r.constructor;for(let i of Object.keys(r||{})){let n=r[i];i==="parent"&&typeof n=="object"?e&&(t[i]=e):i==="source"||i===null?t[i]=n:Array.isArray(n)?t[i]=n.map(a=>Qo(a,t)):i!=="_autoprefixerPrefix"&&i!=="_autoprefixerValues"&&i!=="proxyCache"&&(typeof n=="object"&&n!==null&&(n=Qo(n,t)),t[i]=n)}return t}var Hn=class{static hack(e){return this.hacks||(this.hacks={}),e.names.map(t=>(this.hacks[t]=e,this.hacks[t]))}static load(e,t,i){let n=this.hacks&&this.hacks[e];return n?new n(e,t,i):new this(e,t,i)}static clone(e,t){let i=Qo(e);for(let n in t)i[n]=t[n];return i}constructor(e,t,i){this.prefixes=t,this.name=e,this.all=i}parentPrefix(e){let t;return typeof e._autoprefixerPrefix!="undefined"?t=e._autoprefixerPrefix:e.type==="decl"&&e.prop[0]==="-"?t=Em.prefix(e.prop):e.type==="root"?t=!1:e.type==="rule"&&e.selector.includes(":-")&&/:(-\w+-)/.test(e.selector)?t=e.selector.match(/:(-\w+-)/)[1]:e.type==="atrule"&&e.name[0]==="-"?t=Em.prefix(e.name):t=this.parentPrefix(e.parent),HC.prefixes().includes(t)||(t=!1),e._autoprefixerPrefix=t,e._autoprefixerPrefix}process(e,t){if(!this.check(e))return;let i=this.parentPrefix(e),n=this.prefixes.filter(s=>!i||i===YC.removeNote(s)),a=[];for(let s of n)this.add(e,s,a.concat([s]),t)&&a.push(s);return a}clone(e,t){return Hn.clone(e,t)}};Tm.exports=Hn});var M=v((TD,Im)=>{l();var QC=Ht(),JC=dt(),Pm=le(),Dm=class extends QC{check(){return!0}prefixed(e,t){return t+e}normalize(e){return e}otherPrefixes(e,t){for(let i of JC.prefixes())if(i!==t&&e.includes(i))return!0;return!1}set(e,t){return e.prop=this.prefixed(e.prop,t),e}needCascade(e){return e._autoprefixerCascade||(e._autoprefixerCascade=this.all.options.cascade!==!1&&e.raw("before").includes(` -`)),e._autoprefixerCascade}maxPrefixed(e,t){if(t._autoprefixerMax)return t._autoprefixerMax;let i=0;for(let n of e)n=Pm.removeNote(n),n.length>i&&(i=n.length);return t._autoprefixerMax=i,t._autoprefixerMax}calcBefore(e,t,i=""){let a=this.maxPrefixed(e,t)-Pm.removeNote(i).length,s=t.raw("before");return a>0&&(s+=Array(a).fill(" ").join("")),s}restoreBefore(e){let t=e.raw("before").split(` -`),i=t[t.length-1];this.all.group(e).up(n=>{let a=n.raw("before").split(` -`),s=a[a.length-1];s.lengths.prop===n.prop&&s.value===n.value)))return this.needCascade(e)&&(n.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,n)}isAlready(e,t){let i=this.all.group(e).up(n=>n.prop===t);return i||(i=this.all.group(e).down(n=>n.prop===t)),i}add(e,t,i,n){let a=this.prefixed(e.prop,t);if(!(this.isAlready(e,a)||this.otherPrefixes(e.value,t)))return this.insert(e,t,i,n)}process(e,t){if(!this.needCascade(e)){super.process(e,t);return}let i=super.process(e,t);!i||!i.length||(this.restoreBefore(e),e.raws.before=this.calcBefore(i,e))}old(e,t){return[this.prefixed(e,t)]}};Im.exports=Dm});var Rm=v((PD,qm)=>{l();qm.exports=function r(e){return{mul:t=>new r(e*t),div:t=>new r(e/t),simplify:()=>new r(e),toString:()=>e.toString()}}});var Fm=v((DD,Bm)=>{l();var XC=Rm(),KC=Ht(),Jo=le(),ZC=/(min|max)-resolution\s*:\s*\d*\.?\d+(dppx|dpcm|dpi|x)/gi,eA=/(min|max)-resolution(\s*:\s*)(\d*\.?\d+)(dppx|dpcm|dpi|x)/i,Mm=class extends KC{prefixName(e,t){return e==="-moz-"?t+"--moz-device-pixel-ratio":e+t+"-device-pixel-ratio"}prefixQuery(e,t,i,n,a){return n=new XC(n),a==="dpi"?n=n.div(96):a==="dpcm"&&(n=n.mul(2.54).div(96)),n=n.simplify(),e==="-o-"&&(n=n.n+"/"+n.d),this.prefixName(e,t)+i+n}clean(e){if(!this.bad){this.bad=[];for(let t of this.prefixes)this.bad.push(this.prefixName(t,"min")),this.bad.push(this.prefixName(t,"max"))}e.params=Jo.editList(e.params,t=>t.filter(i=>this.bad.every(n=>!i.includes(n))))}process(e){let t=this.parentPrefix(e),i=t?[t]:this.prefixes;e.params=Jo.editList(e.params,(n,a)=>{for(let s of n){if(!s.includes("min-resolution")&&!s.includes("max-resolution")){a.push(s);continue}for(let o of i){let u=s.replace(ZC,c=>{let f=c.match(eA);return this.prefixQuery(o,f[1],f[2],f[3],f[4])});a.push(u)}a.push(s)}return Jo.uniq(a)})}};Bm.exports=Mm});var Nm=v((ID,Lm)=>{l();var Xo="(".charCodeAt(0),Ko=")".charCodeAt(0),Yn="'".charCodeAt(0),Zo='"'.charCodeAt(0),el="\\".charCodeAt(0),Yt="/".charCodeAt(0),tl=",".charCodeAt(0),rl=":".charCodeAt(0),Qn="*".charCodeAt(0),tA="u".charCodeAt(0),rA="U".charCodeAt(0),iA="+".charCodeAt(0),nA=/^[a-f0-9?-]+$/i;Lm.exports=function(r){for(var e=[],t=r,i,n,a,s,o,u,c,f,d=0,p=t.charCodeAt(d),m=t.length,b=[{nodes:e}],x=0,y,w="",k="",S="";d{l();$m.exports=function r(e,t,i){var n,a,s,o;for(n=0,a=e.length;n{l();function jm(r,e){var t=r.type,i=r.value,n,a;return e&&(a=e(r))!==void 0?a:t==="word"||t==="space"?i:t==="string"?(n=r.quote||"",n+i+(r.unclosed?"":n)):t==="comment"?"/*"+i+(r.unclosed?"":"*/"):t==="div"?(r.before||"")+i+(r.after||""):Array.isArray(r.nodes)?(n=Vm(r.nodes,e),t!=="function"?n:i+"("+(r.before||"")+n+(r.after||"")+(r.unclosed?"":")")):i}function Vm(r,e){var t,i;if(Array.isArray(r)){for(t="",i=r.length-1;~i;i-=1)t=jm(r[i],e)+t;return t}return jm(r,e)}Um.exports=Vm});var Hm=v((MD,Gm)=>{l();var Jn="-".charCodeAt(0),Xn="+".charCodeAt(0),il=".".charCodeAt(0),sA="e".charCodeAt(0),aA="E".charCodeAt(0);function oA(r){var e=r.charCodeAt(0),t;if(e===Xn||e===Jn){if(t=r.charCodeAt(1),t>=48&&t<=57)return!0;var i=r.charCodeAt(2);return t===il&&i>=48&&i<=57}return e===il?(t=r.charCodeAt(1),t>=48&&t<=57):e>=48&&e<=57}Gm.exports=function(r){var e=0,t=r.length,i,n,a;if(t===0||!oA(r))return!1;for(i=r.charCodeAt(e),(i===Xn||i===Jn)&&e++;e57));)e+=1;if(i=r.charCodeAt(e),n=r.charCodeAt(e+1),i===il&&n>=48&&n<=57)for(e+=2;e57));)e+=1;if(i=r.charCodeAt(e),n=r.charCodeAt(e+1),a=r.charCodeAt(e+2),(i===sA||i===aA)&&(n>=48&&n<=57||(n===Xn||n===Jn)&&a>=48&&a<=57))for(e+=n===Xn||n===Jn?3:2;e57));)e+=1;return{number:r.slice(0,e),unit:r.slice(e)}}});var Kn=v((BD,Jm)=>{l();var lA=Nm(),Ym=zm(),Qm=Wm();function ht(r){return this instanceof ht?(this.nodes=lA(r),this):new ht(r)}ht.prototype.toString=function(){return Array.isArray(this.nodes)?Qm(this.nodes):""};ht.prototype.walk=function(r,e){return Ym(this.nodes,r,e),this};ht.unit=Hm();ht.walk=Ym;ht.stringify=Qm;Jm.exports=ht});var tg=v((FD,eg)=>{l();var{list:uA}=ge(),Xm=Kn(),fA=dt(),Km=ai(),Zm=class{constructor(e){this.props=["transition","transition-property"],this.prefixes=e}add(e,t){let i,n,a=this.prefixes.add[e.prop],s=this.ruleVendorPrefixes(e),o=s||a&&a.prefixes||[],u=this.parse(e.value),c=u.map(m=>this.findProp(m)),f=[];if(c.some(m=>m[0]==="-"))return;for(let m of u){if(n=this.findProp(m),n[0]==="-")continue;let b=this.prefixes.add[n];if(!(!b||!b.prefixes))for(i of b.prefixes){if(s&&!s.some(y=>i.includes(y)))continue;let x=this.prefixes.prefixed(n,i);x!=="-ms-transform"&&!c.includes(x)&&(this.disabled(n,i)||f.push(this.clone(n,x,m)))}}u=u.concat(f);let d=this.stringify(u),p=this.stringify(this.cleanFromUnprefixed(u,"-webkit-"));if(o.includes("-webkit-")&&this.cloneBefore(e,`-webkit-${e.prop}`,p),this.cloneBefore(e,e.prop,p),o.includes("-o-")){let m=this.stringify(this.cleanFromUnprefixed(u,"-o-"));this.cloneBefore(e,`-o-${e.prop}`,m)}for(i of o)if(i!=="-webkit-"&&i!=="-o-"){let m=this.stringify(this.cleanOtherPrefixes(u,i));this.cloneBefore(e,i+e.prop,m)}d!==e.value&&!this.already(e,e.prop,d)&&(this.checkForWarning(t,e),e.cloneBefore(),e.value=d)}findProp(e){let t=e[0].value;if(/^\d/.test(t)){for(let[i,n]of e.entries())if(i!==0&&n.type==="word")return n.value}return t}already(e,t,i){return e.parent.some(n=>n.prop===t&&n.value===i)}cloneBefore(e,t,i){this.already(e,t,i)||e.cloneBefore({prop:t,value:i})}checkForWarning(e,t){if(t.prop!=="transition-property")return;let i=!1,n=!1;t.parent.each(a=>{if(a.type!=="decl"||a.prop.indexOf("transition-")!==0)return;let s=uA.comma(a.value);if(a.prop==="transition-property"){s.forEach(o=>{let u=this.prefixes.add[o];u&&u.prefixes&&u.prefixes.length>0&&(i=!0)});return}return n=n||s.length>1,!1}),i&&n&&t.warn(e,"Replace transition-property to transition, because Autoprefixer could not support any cases of transition-property and other transition-*")}remove(e){let t=this.parse(e.value);t=t.filter(s=>{let o=this.prefixes.remove[this.findProp(s)];return!o||!o.remove});let i=this.stringify(t);if(e.value===i)return;if(t.length===0){e.remove();return}let n=e.parent.some(s=>s.prop===e.prop&&s.value===i),a=e.parent.some(s=>s!==e&&s.prop===e.prop&&s.value.length>i.length);if(n||a){e.remove();return}e.value=i}parse(e){let t=Xm(e),i=[],n=[];for(let a of t.nodes)n.push(a),a.type==="div"&&a.value===","&&(i.push(n),n=[]);return i.push(n),i.filter(a=>a.length>0)}stringify(e){if(e.length===0)return"";let t=[];for(let i of e)i[i.length-1].type!=="div"&&i.push(this.div(e)),t=t.concat(i);return t[0].type==="div"&&(t=t.slice(1)),t[t.length-1].type==="div"&&(t=t.slice(0,-2+1||void 0)),Xm.stringify({nodes:t})}clone(e,t,i){let n=[],a=!1;for(let s of i)!a&&s.type==="word"&&s.value===e?(n.push({type:"word",value:t}),a=!0):n.push(s);return n}div(e){for(let t of e)for(let i of t)if(i.type==="div"&&i.value===",")return i;return{type:"div",value:",",after:" "}}cleanOtherPrefixes(e,t){return e.filter(i=>{let n=Km.prefix(this.findProp(i));return n===""||n===t})}cleanFromUnprefixed(e,t){let i=e.map(a=>this.findProp(a)).filter(a=>a.slice(0,t.length)===t).map(a=>this.prefixes.unprefixed(a)),n=[];for(let a of e){let s=this.findProp(a),o=Km.prefix(s);!i.includes(s)&&(o===t||o==="")&&n.push(a)}return n}disabled(e,t){let i=["order","justify-content","align-self","align-content"];if(e.includes("flex")||i.includes(e)){if(this.prefixes.options.flexbox===!1)return!0;if(this.prefixes.options.flexbox==="no-2009")return t.includes("2009")}}ruleVendorPrefixes(e){let{parent:t}=e;if(t.type!=="rule")return!1;if(!t.selector.includes(":-"))return!1;let i=fA.prefixes().filter(n=>t.selector.includes(":"+n));return i.length>0?i:!1}};eg.exports=Zm});var Qt=v((LD,ig)=>{l();var cA=le(),rg=class{constructor(e,t,i,n){this.unprefixed=e,this.prefixed=t,this.string=i||t,this.regexp=n||cA.regexp(t)}check(e){return e.includes(this.string)?!!e.match(this.regexp):!1}};ig.exports=rg});var ke=v((ND,sg)=>{l();var pA=Ht(),dA=Qt(),hA=ai(),mA=le(),ng=class extends pA{static save(e,t){let i=t.prop,n=[];for(let a in t._autoprefixerValues){let s=t._autoprefixerValues[a];if(s===t.value)continue;let o,u=hA.prefix(i);if(u==="-pie-")continue;if(u===a){o=t.value=s,n.push(o);continue}let c=e.prefixed(i,a),f=t.parent;if(!f.every(b=>b.prop!==c)){n.push(o);continue}let d=s.replace(/\s+/," ");if(f.some(b=>b.prop===t.prop&&b.value.replace(/\s+/," ")===d)){n.push(o);continue}let m=this.clone(t,{value:s});o=t.parent.insertBefore(t,m),n.push(o)}return n}check(e){let t=e.value;return t.includes(this.name)?!!t.match(this.regexp()):!1}regexp(){return this.regexpCache||(this.regexpCache=mA.regexp(this.name))}replace(e,t){return e.replace(this.regexp(),`$1${t}$2`)}value(e){return e.raws.value&&e.raws.value.value===e.value?e.raws.value.raw:e.value}add(e,t){e._autoprefixerValues||(e._autoprefixerValues={});let i=e._autoprefixerValues[t]||this.value(e),n;do if(n=i,i=this.replace(i,t),i===!1)return;while(i!==n);e._autoprefixerValues[t]=i}old(e){return new dA(this.name,e+this.name)}};sg.exports=ng});var mt=v(($D,ag)=>{l();ag.exports={}});var sl=v((zD,ug)=>{l();var og=Kn(),gA=ke(),yA=mt().insertAreas,wA=/(^|[^-])linear-gradient\(\s*(top|left|right|bottom)/i,bA=/(^|[^-])radial-gradient\(\s*\d+(\w*|%)\s+\d+(\w*|%)\s*,/i,vA=/(!\s*)?autoprefixer:\s*ignore\s+next/i,xA=/(!\s*)?autoprefixer\s*grid:\s*(on|off|(no-)?autoplace)/i,kA=["width","height","min-width","max-width","min-height","max-height","inline-size","min-inline-size","max-inline-size","block-size","min-block-size","max-block-size"];function nl(r){return r.parent.some(e=>e.prop==="grid-template"||e.prop==="grid-template-areas")}function SA(r){let e=r.parent.some(i=>i.prop==="grid-template-rows"),t=r.parent.some(i=>i.prop==="grid-template-columns");return e&&t}var lg=class{constructor(e){this.prefixes=e}add(e,t){let i=this.prefixes.add["@resolution"],n=this.prefixes.add["@keyframes"],a=this.prefixes.add["@viewport"],s=this.prefixes.add["@supports"];e.walkAtRules(f=>{if(f.name==="keyframes"){if(!this.disabled(f,t))return n&&n.process(f)}else if(f.name==="viewport"){if(!this.disabled(f,t))return a&&a.process(f)}else if(f.name==="supports"){if(this.prefixes.options.supports!==!1&&!this.disabled(f,t))return s.process(f)}else if(f.name==="media"&&f.params.includes("-resolution")&&!this.disabled(f,t))return i&&i.process(f)}),e.walkRules(f=>{if(!this.disabled(f,t))return this.prefixes.add.selectors.map(d=>d.process(f,t))});function o(f){return f.parent.nodes.some(d=>{if(d.type!=="decl")return!1;let p=d.prop==="display"&&/(inline-)?grid/.test(d.value),m=d.prop.startsWith("grid-template"),b=/^grid-([A-z]+-)?gap/.test(d.prop);return p||m||b})}function u(f){return f.parent.some(d=>d.prop==="display"&&/(inline-)?flex/.test(d.value))}let c=this.gridStatus(e,t)&&this.prefixes.add["grid-area"]&&this.prefixes.add["grid-area"].prefixes;return e.walkDecls(f=>{if(this.disabledDecl(f,t))return;let d=f.parent,p=f.prop,m=f.value;if(p==="grid-row-span"){t.warn("grid-row-span is not part of final Grid Layout. Use grid-row.",{node:f});return}else if(p==="grid-column-span"){t.warn("grid-column-span is not part of final Grid Layout. Use grid-column.",{node:f});return}else if(p==="display"&&m==="box"){t.warn("You should write display: flex by final spec instead of display: box",{node:f});return}else if(p==="text-emphasis-position")(m==="under"||m==="over")&&t.warn("You should use 2 values for text-emphasis-position For example, `under left` instead of just `under`.",{node:f});else if(/^(align|justify|place)-(items|content)$/.test(p)&&u(f))(m==="start"||m==="end")&&t.warn(`${m} value has mixed support, consider using flex-${m} instead`,{node:f});else if(p==="text-decoration-skip"&&m==="ink")t.warn("Replace text-decoration-skip: ink to text-decoration-skip-ink: auto, because spec had been changed",{node:f});else{if(c&&this.gridStatus(f,t))if(f.value==="subgrid"&&t.warn("IE does not support subgrid",{node:f}),/^(align|justify|place)-items$/.test(p)&&o(f)){let x=p.replace("-items","-self");t.warn(`IE does not support ${p} on grid containers. Try using ${x} on child elements instead: ${f.parent.selector} > * { ${x}: ${f.value} }`,{node:f})}else if(/^(align|justify|place)-content$/.test(p)&&o(f))t.warn(`IE does not support ${f.prop} on grid containers`,{node:f});else if(p==="display"&&f.value==="contents"){t.warn("Please do not use display: contents; if you have grid setting enabled",{node:f});return}else if(f.prop==="grid-gap"){let x=this.gridStatus(f,t);x==="autoplace"&&!SA(f)&&!nl(f)?t.warn("grid-gap only works if grid-template(-areas) is being used or both rows and columns have been declared and cells have not been manually placed inside the explicit grid",{node:f}):(x===!0||x==="no-autoplace")&&!nl(f)&&t.warn("grid-gap only works if grid-template(-areas) is being used",{node:f})}else if(p==="grid-auto-columns"){t.warn("grid-auto-columns is not supported by IE",{node:f});return}else if(p==="grid-auto-rows"){t.warn("grid-auto-rows is not supported by IE",{node:f});return}else if(p==="grid-auto-flow"){let x=d.some(w=>w.prop==="grid-template-rows"),y=d.some(w=>w.prop==="grid-template-columns");nl(f)?t.warn("grid-auto-flow is not supported by IE",{node:f}):m.includes("dense")?t.warn("grid-auto-flow: dense is not supported by IE",{node:f}):!x&&!y&&t.warn("grid-auto-flow works only if grid-template-rows and grid-template-columns are present in the same rule",{node:f});return}else if(m.includes("auto-fit")){t.warn("auto-fit value is not supported by IE",{node:f,word:"auto-fit"});return}else if(m.includes("auto-fill")){t.warn("auto-fill value is not supported by IE",{node:f,word:"auto-fill"});return}else p.startsWith("grid-template")&&m.includes("[")&&t.warn("Autoprefixer currently does not support line names. Try using grid-template-areas instead.",{node:f,word:"["});if(m.includes("radial-gradient"))if(bA.test(f.value))t.warn("Gradient has outdated direction syntax. New syntax is like `closest-side at 0 0` instead of `0 0, closest-side`.",{node:f});else{let x=og(m);for(let y of x.nodes)if(y.type==="function"&&y.value==="radial-gradient")for(let w of y.nodes)w.type==="word"&&(w.value==="cover"?t.warn("Gradient has outdated direction syntax. Replace `cover` to `farthest-corner`.",{node:f}):w.value==="contain"&&t.warn("Gradient has outdated direction syntax. Replace `contain` to `closest-side`.",{node:f}))}m.includes("linear-gradient")&&wA.test(m)&&t.warn("Gradient has outdated direction syntax. New syntax is like `to left` instead of `right`.",{node:f})}kA.includes(f.prop)&&(f.value.includes("-fill-available")||(f.value.includes("fill-available")?t.warn("Replace fill-available to stretch, because spec had been changed",{node:f}):f.value.includes("fill")&&og(m).nodes.some(y=>y.type==="word"&&y.value==="fill")&&t.warn("Replace fill to stretch, because spec had been changed",{node:f})));let b;if(f.prop==="transition"||f.prop==="transition-property")return this.prefixes.transition.add(f,t);if(f.prop==="align-self"){if(this.displayType(f)!=="grid"&&this.prefixes.options.flexbox!==!1&&(b=this.prefixes.add["align-self"],b&&b.prefixes&&b.process(f)),this.gridStatus(f,t)!==!1&&(b=this.prefixes.add["grid-row-align"],b&&b.prefixes))return b.process(f,t)}else if(f.prop==="justify-self"){if(this.gridStatus(f,t)!==!1&&(b=this.prefixes.add["grid-column-align"],b&&b.prefixes))return b.process(f,t)}else if(f.prop==="place-self"){if(b=this.prefixes.add["place-self"],b&&b.prefixes&&this.gridStatus(f,t)!==!1)return b.process(f,t)}else if(b=this.prefixes.add[f.prop],b&&b.prefixes)return b.process(f,t)}),this.gridStatus(e,t)&&yA(e,this.disabled),e.walkDecls(f=>{if(this.disabledValue(f,t))return;let d=this.prefixes.unprefixed(f.prop),p=this.prefixes.values("add",d);if(Array.isArray(p))for(let m of p)m.process&&m.process(f,t);gA.save(this.prefixes,f)})}remove(e,t){let i=this.prefixes.remove["@resolution"];e.walkAtRules((n,a)=>{this.prefixes.remove[`@${n.name}`]?this.disabled(n,t)||n.parent.removeChild(a):n.name==="media"&&n.params.includes("-resolution")&&i&&i.clean(n)});for(let n of this.prefixes.remove.selectors)e.walkRules((a,s)=>{n.check(a)&&(this.disabled(a,t)||a.parent.removeChild(s))});return e.walkDecls((n,a)=>{if(this.disabled(n,t))return;let s=n.parent,o=this.prefixes.unprefixed(n.prop);if((n.prop==="transition"||n.prop==="transition-property")&&this.prefixes.transition.remove(n),this.prefixes.remove[n.prop]&&this.prefixes.remove[n.prop].remove){let u=this.prefixes.group(n).down(c=>this.prefixes.normalize(c.prop)===o);if(o==="flex-flow"&&(u=!0),n.prop==="-webkit-box-orient"){let c={"flex-direction":!0,"flex-flow":!0};if(!n.parent.some(f=>c[f.prop]))return}if(u&&!this.withHackValue(n)){n.raw("before").includes(` -`)&&this.reduceSpaces(n),s.removeChild(a);return}}for(let u of this.prefixes.values("remove",o)){if(!u.check||!u.check(n.value))continue;if(o=u.unprefixed,this.prefixes.group(n).down(f=>f.value.includes(o))){s.removeChild(a);return}}})}withHackValue(e){return e.prop==="-webkit-background-clip"&&e.value==="text"}disabledValue(e,t){return this.gridStatus(e,t)===!1&&e.type==="decl"&&e.prop==="display"&&e.value.includes("grid")||this.prefixes.options.flexbox===!1&&e.type==="decl"&&e.prop==="display"&&e.value.includes("flex")||e.type==="decl"&&e.prop==="content"?!0:this.disabled(e,t)}disabledDecl(e,t){if(this.gridStatus(e,t)===!1&&e.type==="decl"&&(e.prop.includes("grid")||e.prop==="justify-items"))return!0;if(this.prefixes.options.flexbox===!1&&e.type==="decl"){let i=["order","justify-content","align-items","align-content"];if(e.prop.includes("flex")||i.includes(e.prop))return!0}return this.disabled(e,t)}disabled(e,t){if(!e)return!1;if(e._autoprefixerDisabled!==void 0)return e._autoprefixerDisabled;if(e.parent){let n=e.prev();if(n&&n.type==="comment"&&vA.test(n.text))return e._autoprefixerDisabled=!0,e._autoprefixerSelfDisabled=!0,!0}let i=null;if(e.nodes){let n;e.each(a=>{a.type==="comment"&&/(!\s*)?autoprefixer:\s*(off|on)/i.test(a.text)&&(typeof n!="undefined"?t.warn("Second Autoprefixer control comment was ignored. Autoprefixer applies control comment to whole block, not to next rules.",{node:a}):n=/on/i.test(a.text))}),n!==void 0&&(i=!n)}if(!e.nodes||i===null)if(e.parent){let n=this.disabled(e.parent,t);e.parent._autoprefixerSelfDisabled===!0?i=!1:i=n}else i=!1;return e._autoprefixerDisabled=i,i}reduceSpaces(e){let t=!1;if(this.prefixes.group(e).up(()=>(t=!0,!0)),t)return;let i=e.raw("before").split(` -`),n=i[i.length-1].length,a=!1;this.prefixes.group(e).down(s=>{i=s.raw("before").split(` -`);let o=i.length-1;i[o].length>n&&(a===!1&&(a=i[o].length-n),i[o]=i[o].slice(0,-a),s.raws.before=i.join(` -`))})}displayType(e){for(let t of e.parent.nodes)if(t.prop==="display"){if(t.value.includes("flex"))return"flex";if(t.value.includes("grid"))return"grid"}return!1}gridStatus(e,t){if(!e)return!1;if(e._autoprefixerGridStatus!==void 0)return e._autoprefixerGridStatus;let i=null;if(e.nodes){let n;e.each(a=>{if(a.type==="comment"&&xA.test(a.text)){let s=/:\s*autoplace/i.test(a.text),o=/no-autoplace/i.test(a.text);typeof n!="undefined"?t.warn("Second Autoprefixer grid control comment was ignored. Autoprefixer applies control comments to the whole block, not to the next rules.",{node:a}):s?n="autoplace":o?n=!0:n=/on/i.test(a.text)}}),n!==void 0&&(i=n)}if(e.type==="atrule"&&e.name==="supports"){let n=e.params;n.includes("grid")&&n.includes("auto")&&(i=!1)}if(!e.nodes||i===null)if(e.parent){let n=this.gridStatus(e.parent,t);e.parent._autoprefixerSelfDisabled===!0?i=!1:i=n}else typeof this.prefixes.options.grid!="undefined"?i=this.prefixes.options.grid:typeof h.env.AUTOPREFIXER_GRID!="undefined"?h.env.AUTOPREFIXER_GRID==="autoplace"?i="autoplace":i=!0:i=!1;return e._autoprefixerGridStatus=i,i}};ug.exports=lg});var cg=v((jD,fg)=>{l();fg.exports={A:{A:{"2":"K E F G A B JC"},B:{"1":"C L M H N D O P Q R S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I"},C:{"1":"2 3 4 5 6 7 8 9 AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB 0B dB 1B eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R 2B S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I uB 3B 4B","2":"0 1 KC zB J K E F G A B C L M H N D O k l LC MC"},D:{"1":"8 9 AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB 0B dB 1B eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I uB 3B 4B","2":"0 1 2 3 4 5 6 7 J K E F G A B C L M H N D O k l"},E:{"1":"G A B C L M H D RC 6B vB wB 7B SC TC 8B 9B xB AC yB BC CC DC EC FC GC UC","2":"0 J K E F NC 5B OC PC QC"},F:{"1":"1 2 3 4 5 6 7 8 9 H N D O k l AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R 2B S T U V W X Y Z a b c d e f g h i j wB","2":"G B C VC WC XC YC vB HC ZC"},G:{"1":"D fC gC hC iC jC kC lC mC nC oC pC qC rC sC tC 8B 9B xB AC yB BC CC DC EC FC GC","2":"F 5B aC IC bC cC dC eC"},H:{"1":"uC"},I:{"1":"I zC 0C","2":"zB J vC wC xC yC IC"},J:{"2":"E A"},K:{"1":"m","2":"A B C vB HC wB"},L:{"1":"I"},M:{"1":"uB"},N:{"2":"A B"},O:{"1":"xB"},P:{"1":"J k l 1C 2C 3C 4C 5C 6B 6C 7C 8C 9C AD yB BD CD DD"},Q:{"1":"7B"},R:{"1":"ED"},S:{"1":"FD GD"}},B:4,C:"CSS Feature Queries"}});var mg=v((VD,hg)=>{l();function pg(r){return r[r.length-1]}var dg={parse(r){let e=[""],t=[e];for(let i of r){if(i==="("){e=[""],pg(t).push(e),t.push(e);continue}if(i===")"){t.pop(),e=pg(t),e.push("");continue}e[e.length-1]+=i}return t[0]},stringify(r){let e="";for(let t of r){if(typeof t=="object"){e+=`(${dg.stringify(t)})`;continue}e+=t}return e}};hg.exports=dg});var vg=v((UD,bg)=>{l();var CA=cg(),{feature:AA}=(Gn(),Wn),{parse:_A}=ge(),OA=dt(),al=mg(),EA=ke(),TA=le(),gg=AA(CA),yg=[];for(let r in gg.stats){let e=gg.stats[r];for(let t in e){let i=e[t];/y/.test(i)&&yg.push(r+" "+t)}}var wg=class{constructor(e,t){this.Prefixes=e,this.all=t}prefixer(){if(this.prefixerCache)return this.prefixerCache;let e=this.all.browsers.selected.filter(i=>yg.includes(i)),t=new OA(this.all.browsers.data,e,this.all.options);return this.prefixerCache=new this.Prefixes(this.all.data,t,this.all.options),this.prefixerCache}parse(e){let t=e.split(":"),i=t[0],n=t[1];return n||(n=""),[i.trim(),n.trim()]}virtual(e){let[t,i]=this.parse(e),n=_A("a{}").first;return n.append({prop:t,value:i,raws:{before:""}}),n}prefixed(e){let t=this.virtual(e);if(this.disabled(t.first))return t.nodes;let i={warn:()=>null},n=this.prefixer().add[t.first.prop];n&&n.process&&n.process(t.first,i);for(let a of t.nodes){for(let s of this.prefixer().values("add",t.first.prop))s.process(a);EA.save(this.all,a)}return t.nodes}isNot(e){return typeof e=="string"&&/not\s*/i.test(e)}isOr(e){return typeof e=="string"&&/\s*or\s*/i.test(e)}isProp(e){return typeof e=="object"&&e.length===1&&typeof e[0]=="string"}isHack(e,t){return!new RegExp(`(\\(|\\s)${TA.escapeRegexp(t)}:`).test(e)}toRemove(e,t){let[i,n]=this.parse(e),a=this.all.unprefixed(i),s=this.all.cleaner();if(s.remove[i]&&s.remove[i].remove&&!this.isHack(t,a))return!0;for(let o of s.values("remove",a))if(o.check(n))return!0;return!1}remove(e,t){let i=0;for(;itypeof t!="object"?t:t.length===1&&typeof t[0]=="object"?this.cleanBrackets(t[0]):this.cleanBrackets(t))}convert(e){let t=[""];for(let i of e)t.push([`${i.prop}: ${i.value}`]),t.push(" or ");return t[t.length-1]="",t}normalize(e){if(typeof e!="object")return e;if(e=e.filter(t=>t!==""),typeof e[0]=="string"){let t=e[0].trim();if(t.includes(":")||t==="selector"||t==="not selector")return[al.stringify(e)]}return e.map(t=>this.normalize(t))}add(e,t){return e.map(i=>{if(this.isProp(i)){let n=this.prefixed(i[0]);return n.length>1?this.convert(n):i}return typeof i=="object"?this.add(i,t):i})}process(e){let t=al.parse(e.params);t=this.normalize(t),t=this.remove(t,e.params),t=this.add(t,e.params),t=this.cleanBrackets(t),e.params=al.stringify(t)}disabled(e){if(!this.all.options.grid&&(e.prop==="display"&&e.value.includes("grid")||e.prop.includes("grid")||e.prop==="justify-items"))return!0;if(this.all.options.flexbox===!1){if(e.prop==="display"&&e.value.includes("flex"))return!0;let t=["order","justify-content","align-items","align-content"];if(e.prop.includes("flex")||t.includes(e.prop))return!0}return!1}};bg.exports=wg});var Sg=v((WD,kg)=>{l();var xg=class{constructor(e,t){this.prefix=t,this.prefixed=e.prefixed(this.prefix),this.regexp=e.regexp(this.prefix),this.prefixeds=e.possible().map(i=>[e.prefixed(i),e.regexp(i)]),this.unprefixed=e.name,this.nameRegexp=e.regexp()}isHack(e){let t=e.parent.index(e)+1,i=e.parent.nodes;for(;t{l();var{list:PA}=ge(),DA=Sg(),IA=Ht(),qA=dt(),RA=le(),Cg=class extends IA{constructor(e,t,i){super(e,t,i);this.regexpCache=new Map}check(e){return e.selector.includes(this.name)?!!e.selector.match(this.regexp()):!1}prefixed(e){return this.name.replace(/^(\W*)/,`$1${e}`)}regexp(e){if(!this.regexpCache.has(e)){let t=e?this.prefixed(e):this.name;this.regexpCache.set(e,new RegExp(`(^|[^:"'=])${RA.escapeRegexp(t)}`,"gi"))}return this.regexpCache.get(e)}possible(){return qA.prefixes()}prefixeds(e){if(e._autoprefixerPrefixeds){if(e._autoprefixerPrefixeds[this.name])return e._autoprefixerPrefixeds}else e._autoprefixerPrefixeds={};let t={};if(e.selector.includes(",")){let n=PA.comma(e.selector).filter(a=>a.includes(this.name));for(let a of this.possible())t[a]=n.map(s=>this.replace(s,a)).join(", ")}else for(let i of this.possible())t[i]=this.replace(e.selector,i);return e._autoprefixerPrefixeds[this.name]=t,e._autoprefixerPrefixeds}already(e,t,i){let n=e.parent.index(e)-1;for(;n>=0;){let a=e.parent.nodes[n];if(a.type!=="rule")return!1;let s=!1;for(let o in t[this.name]){let u=t[this.name][o];if(a.selector===u){if(i===o)return!0;s=!0;break}}if(!s)return!1;n-=1}return!1}replace(e,t){return e.replace(this.regexp(),`$1${this.prefixed(t)}`)}add(e,t){let i=this.prefixeds(e);if(this.already(e,i,t))return;let n=this.clone(e,{selector:i[this.name][t]});e.parent.insertBefore(e,n)}old(e){return new DA(this,e)}};Ag.exports=Cg});var Eg=v((HD,Og)=>{l();var MA=Ht(),_g=class extends MA{add(e,t){let i=t+e.name;if(e.parent.some(s=>s.name===i&&s.params===e.params))return;let a=this.clone(e,{name:i});return e.parent.insertBefore(e,a)}process(e){let t=this.parentPrefix(e);for(let i of this.prefixes)(!t||t===i)&&this.add(e,i)}};Og.exports=_g});var Pg=v((YD,Tg)=>{l();var BA=Jt(),ol=class extends BA{prefixed(e){return e==="-webkit-"?":-webkit-full-screen":e==="-moz-"?":-moz-full-screen":`:${e}fullscreen`}};ol.names=[":fullscreen"];Tg.exports=ol});var Ig=v((QD,Dg)=>{l();var FA=Jt(),ll=class extends FA{possible(){return super.possible().concat(["-moz- old","-ms- old"])}prefixed(e){return e==="-webkit-"?"::-webkit-input-placeholder":e==="-ms-"?"::-ms-input-placeholder":e==="-ms- old"?":-ms-input-placeholder":e==="-moz- old"?":-moz-placeholder":`::${e}placeholder`}};ll.names=["::placeholder"];Dg.exports=ll});var Rg=v((JD,qg)=>{l();var LA=Jt(),ul=class extends LA{prefixed(e){return e==="-ms-"?":-ms-input-placeholder":`:${e}placeholder-shown`}};ul.names=[":placeholder-shown"];qg.exports=ul});var Bg=v((XD,Mg)=>{l();var NA=Jt(),$A=le(),fl=class extends NA{constructor(e,t,i){super(e,t,i);this.prefixes&&(this.prefixes=$A.uniq(this.prefixes.map(n=>"-webkit-")))}prefixed(e){return e==="-webkit-"?"::-webkit-file-upload-button":`::${e}file-selector-button`}};fl.names=["::file-selector-button"];Mg.exports=fl});var pe=v((KD,Fg)=>{l();Fg.exports=function(r){let e;return r==="-webkit- 2009"||r==="-moz-"?e=2009:r==="-ms-"?e=2012:r==="-webkit-"&&(e="final"),r==="-webkit- 2009"&&(r="-webkit-"),[e,r]}});var zg=v((ZD,$g)=>{l();var Lg=ge().list,Ng=pe(),zA=M(),Xt=class extends zA{prefixed(e,t){let i;return[i,t]=Ng(t),i===2009?t+"box-flex":super.prefixed(e,t)}normalize(){return"flex"}set(e,t){let i=Ng(t)[0];if(i===2009)return e.value=Lg.space(e.value)[0],e.value=Xt.oldValues[e.value]||e.value,super.set(e,t);if(i===2012){let n=Lg.space(e.value);n.length===3&&n[2]==="0"&&(e.value=n.slice(0,2).concat("0px").join(" "))}return super.set(e,t)}};Xt.names=["flex","box-flex"];Xt.oldValues={auto:"1",none:"0"};$g.exports=Xt});var Ug=v((eI,Vg)=>{l();var jg=pe(),jA=M(),cl=class extends jA{prefixed(e,t){let i;return[i,t]=jg(t),i===2009?t+"box-ordinal-group":i===2012?t+"flex-order":super.prefixed(e,t)}normalize(){return"order"}set(e,t){return jg(t)[0]===2009&&/\d/.test(e.value)?(e.value=(parseInt(e.value)+1).toString(),super.set(e,t)):super.set(e,t)}};cl.names=["order","flex-order","box-ordinal-group"];Vg.exports=cl});var Gg=v((tI,Wg)=>{l();var VA=M(),pl=class extends VA{check(e){let t=e.value;return!t.toLowerCase().includes("alpha(")&&!t.includes("DXImageTransform.Microsoft")&&!t.includes("data:image/svg+xml")}};pl.names=["filter"];Wg.exports=pl});var Yg=v((rI,Hg)=>{l();var UA=M(),dl=class extends UA{insert(e,t,i,n){if(t!=="-ms-")return super.insert(e,t,i);let a=this.clone(e),s=e.prop.replace(/end$/,"start"),o=t+e.prop.replace(/end$/,"span");if(!e.parent.some(u=>u.prop===o)){if(a.prop=o,e.value.includes("span"))a.value=e.value.replace(/span\s/i,"");else{let u;if(e.parent.walkDecls(s,c=>{u=c}),u){let c=Number(e.value)-Number(u.value)+"";a.value=c}else e.warn(n,`Can not prefix ${e.prop} (${s} is not found)`)}e.cloneBefore(a)}}};dl.names=["grid-row-end","grid-column-end"];Hg.exports=dl});var Jg=v((iI,Qg)=>{l();var WA=M(),hl=class extends WA{check(e){return!e.value.split(/\s+/).some(t=>{let i=t.toLowerCase();return i==="reverse"||i==="alternate-reverse"})}};hl.names=["animation","animation-direction"];Qg.exports=hl});var Kg=v((nI,Xg)=>{l();var GA=pe(),HA=M(),ml=class extends HA{insert(e,t,i){let n;if([n,t]=GA(t),n!==2009)return super.insert(e,t,i);let a=e.value.split(/\s+/).filter(d=>d!=="wrap"&&d!=="nowrap"&&"wrap-reverse");if(a.length===0||e.parent.some(d=>d.prop===t+"box-orient"||d.prop===t+"box-direction"))return;let o=a[0],u=o.includes("row")?"horizontal":"vertical",c=o.includes("reverse")?"reverse":"normal",f=this.clone(e);return f.prop=t+"box-orient",f.value=u,this.needCascade(e)&&(f.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,f),f=this.clone(e),f.prop=t+"box-direction",f.value=c,this.needCascade(e)&&(f.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,f)}};ml.names=["flex-flow","box-direction","box-orient"];Xg.exports=ml});var ey=v((sI,Zg)=>{l();var YA=pe(),QA=M(),gl=class extends QA{normalize(){return"flex"}prefixed(e,t){let i;return[i,t]=YA(t),i===2009?t+"box-flex":i===2012?t+"flex-positive":super.prefixed(e,t)}};gl.names=["flex-grow","flex-positive"];Zg.exports=gl});var ry=v((aI,ty)=>{l();var JA=pe(),XA=M(),yl=class extends XA{set(e,t){if(JA(t)[0]!==2009)return super.set(e,t)}};yl.names=["flex-wrap"];ty.exports=yl});var ny=v((oI,iy)=>{l();var KA=M(),Kt=mt(),wl=class extends KA{insert(e,t,i,n){if(t!=="-ms-")return super.insert(e,t,i);let a=Kt.parse(e),[s,o]=Kt.translate(a,0,2),[u,c]=Kt.translate(a,1,3);[["grid-row",s],["grid-row-span",o],["grid-column",u],["grid-column-span",c]].forEach(([f,d])=>{Kt.insertDecl(e,f,d)}),Kt.warnTemplateSelectorNotFound(e,n),Kt.warnIfGridRowColumnExists(e,n)}};wl.names=["grid-area"];iy.exports=wl});var ay=v((lI,sy)=>{l();var ZA=M(),oi=mt(),bl=class extends ZA{insert(e,t,i){if(t!=="-ms-")return super.insert(e,t,i);if(e.parent.some(s=>s.prop==="-ms-grid-row-align"))return;let[[n,a]]=oi.parse(e);a?(oi.insertDecl(e,"grid-row-align",n),oi.insertDecl(e,"grid-column-align",a)):(oi.insertDecl(e,"grid-row-align",n),oi.insertDecl(e,"grid-column-align",n))}};bl.names=["place-self"];sy.exports=bl});var ly=v((uI,oy)=>{l();var e5=M(),vl=class extends e5{check(e){let t=e.value;return!t.includes("/")||t.includes("span")}normalize(e){return e.replace("-start","")}prefixed(e,t){let i=super.prefixed(e,t);return t==="-ms-"&&(i=i.replace("-start","")),i}};vl.names=["grid-row-start","grid-column-start"];oy.exports=vl});var cy=v((fI,fy)=>{l();var uy=pe(),t5=M(),Zt=class extends t5{check(e){return e.parent&&!e.parent.some(t=>t.prop&&t.prop.startsWith("grid-"))}prefixed(e,t){let i;return[i,t]=uy(t),i===2012?t+"flex-item-align":super.prefixed(e,t)}normalize(){return"align-self"}set(e,t){let i=uy(t)[0];if(i===2012)return e.value=Zt.oldValues[e.value]||e.value,super.set(e,t);if(i==="final")return super.set(e,t)}};Zt.names=["align-self","flex-item-align"];Zt.oldValues={"flex-end":"end","flex-start":"start"};fy.exports=Zt});var dy=v((cI,py)=>{l();var r5=M(),i5=le(),xl=class extends r5{constructor(e,t,i){super(e,t,i);this.prefixes&&(this.prefixes=i5.uniq(this.prefixes.map(n=>n==="-ms-"?"-webkit-":n)))}};xl.names=["appearance"];py.exports=xl});var gy=v((pI,my)=>{l();var hy=pe(),n5=M(),kl=class extends n5{normalize(){return"flex-basis"}prefixed(e,t){let i;return[i,t]=hy(t),i===2012?t+"flex-preferred-size":super.prefixed(e,t)}set(e,t){let i;if([i,t]=hy(t),i===2012||i==="final")return super.set(e,t)}};kl.names=["flex-basis","flex-preferred-size"];my.exports=kl});var wy=v((dI,yy)=>{l();var s5=M(),Sl=class extends s5{normalize(){return this.name.replace("box-image","border")}prefixed(e,t){let i=super.prefixed(e,t);return t==="-webkit-"&&(i=i.replace("border","box-image")),i}};Sl.names=["mask-border","mask-border-source","mask-border-slice","mask-border-width","mask-border-outset","mask-border-repeat","mask-box-image","mask-box-image-source","mask-box-image-slice","mask-box-image-width","mask-box-image-outset","mask-box-image-repeat"];yy.exports=Sl});var vy=v((hI,by)=>{l();var a5=M(),Ne=class extends a5{insert(e,t,i){let n=e.prop==="mask-composite",a;n?a=e.value.split(","):a=e.value.match(Ne.regexp)||[],a=a.map(c=>c.trim()).filter(c=>c);let s=a.length,o;if(s&&(o=this.clone(e),o.value=a.map(c=>Ne.oldValues[c]||c).join(", "),a.includes("intersect")&&(o.value+=", xor"),o.prop=t+"mask-composite"),n)return s?(this.needCascade(e)&&(o.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,o)):void 0;let u=this.clone(e);return u.prop=t+u.prop,s&&(u.value=u.value.replace(Ne.regexp,"")),this.needCascade(e)&&(u.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,u),s?(this.needCascade(e)&&(o.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,o)):e}};Ne.names=["mask","mask-composite"];Ne.oldValues={add:"source-over",subtract:"source-out",intersect:"source-in",exclude:"xor"};Ne.regexp=new RegExp(`\\s+(${Object.keys(Ne.oldValues).join("|")})\\b(?!\\))\\s*(?=[,])`,"ig");by.exports=Ne});var Sy=v((mI,ky)=>{l();var xy=pe(),o5=M(),er=class extends o5{prefixed(e,t){let i;return[i,t]=xy(t),i===2009?t+"box-align":i===2012?t+"flex-align":super.prefixed(e,t)}normalize(){return"align-items"}set(e,t){let i=xy(t)[0];return(i===2009||i===2012)&&(e.value=er.oldValues[e.value]||e.value),super.set(e,t)}};er.names=["align-items","flex-align","box-align"];er.oldValues={"flex-end":"end","flex-start":"start"};ky.exports=er});var Ay=v((gI,Cy)=>{l();var l5=M(),Cl=class extends l5{set(e,t){return t==="-ms-"&&e.value==="contain"&&(e.value="element"),super.set(e,t)}insert(e,t,i){if(!(e.value==="all"&&t==="-ms-"))return super.insert(e,t,i)}};Cl.names=["user-select"];Cy.exports=Cl});var Ey=v((yI,Oy)=>{l();var _y=pe(),u5=M(),Al=class extends u5{normalize(){return"flex-shrink"}prefixed(e,t){let i;return[i,t]=_y(t),i===2012?t+"flex-negative":super.prefixed(e,t)}set(e,t){let i;if([i,t]=_y(t),i===2012||i==="final")return super.set(e,t)}};Al.names=["flex-shrink","flex-negative"];Oy.exports=Al});var Py=v((wI,Ty)=>{l();var f5=M(),_l=class extends f5{prefixed(e,t){return`${t}column-${e}`}normalize(e){return e.includes("inside")?"break-inside":e.includes("before")?"break-before":"break-after"}set(e,t){return(e.prop==="break-inside"&&e.value==="avoid-column"||e.value==="avoid-page")&&(e.value="avoid"),super.set(e,t)}insert(e,t,i){if(e.prop!=="break-inside")return super.insert(e,t,i);if(!(/region/i.test(e.value)||/page/i.test(e.value)))return super.insert(e,t,i)}};_l.names=["break-inside","page-break-inside","column-break-inside","break-before","page-break-before","column-break-before","break-after","page-break-after","column-break-after"];Ty.exports=_l});var Iy=v((bI,Dy)=>{l();var c5=M(),Ol=class extends c5{prefixed(e,t){return t+"print-color-adjust"}normalize(){return"color-adjust"}};Ol.names=["color-adjust","print-color-adjust"];Dy.exports=Ol});var Ry=v((vI,qy)=>{l();var p5=M(),tr=class extends p5{insert(e,t,i){if(t==="-ms-"){let n=this.set(this.clone(e),t);this.needCascade(e)&&(n.raws.before=this.calcBefore(i,e,t));let a="ltr";return e.parent.nodes.forEach(s=>{s.prop==="direction"&&(s.value==="rtl"||s.value==="ltr")&&(a=s.value)}),n.value=tr.msValues[a][e.value]||e.value,e.parent.insertBefore(e,n)}return super.insert(e,t,i)}};tr.names=["writing-mode"];tr.msValues={ltr:{"horizontal-tb":"lr-tb","vertical-rl":"tb-rl","vertical-lr":"tb-lr"},rtl:{"horizontal-tb":"rl-tb","vertical-rl":"bt-rl","vertical-lr":"bt-lr"}};qy.exports=tr});var By=v((xI,My)=>{l();var d5=M(),El=class extends d5{set(e,t){return e.value=e.value.replace(/\s+fill(\s)/,"$1"),super.set(e,t)}};El.names=["border-image"];My.exports=El});var Ny=v((kI,Ly)=>{l();var Fy=pe(),h5=M(),rr=class extends h5{prefixed(e,t){let i;return[i,t]=Fy(t),i===2012?t+"flex-line-pack":super.prefixed(e,t)}normalize(){return"align-content"}set(e,t){let i=Fy(t)[0];if(i===2012)return e.value=rr.oldValues[e.value]||e.value,super.set(e,t);if(i==="final")return super.set(e,t)}};rr.names=["align-content","flex-line-pack"];rr.oldValues={"flex-end":"end","flex-start":"start","space-between":"justify","space-around":"distribute"};Ly.exports=rr});var zy=v((SI,$y)=>{l();var m5=M(),Se=class extends m5{prefixed(e,t){return t==="-moz-"?t+(Se.toMozilla[e]||e):super.prefixed(e,t)}normalize(e){return Se.toNormal[e]||e}};Se.names=["border-radius"];Se.toMozilla={};Se.toNormal={};for(let r of["top","bottom"])for(let e of["left","right"]){let t=`border-${r}-${e}-radius`,i=`border-radius-${r}${e}`;Se.names.push(t),Se.names.push(i),Se.toMozilla[t]=i,Se.toNormal[i]=t}$y.exports=Se});var Vy=v((CI,jy)=>{l();var g5=M(),Tl=class extends g5{prefixed(e,t){return e.includes("-start")?t+e.replace("-block-start","-before"):t+e.replace("-block-end","-after")}normalize(e){return e.includes("-before")?e.replace("-before","-block-start"):e.replace("-after","-block-end")}};Tl.names=["border-block-start","border-block-end","margin-block-start","margin-block-end","padding-block-start","padding-block-end","border-before","border-after","margin-before","margin-after","padding-before","padding-after"];jy.exports=Tl});var Wy=v((AI,Uy)=>{l();var y5=M(),{parseTemplate:w5,warnMissedAreas:b5,getGridGap:v5,warnGridGap:x5,inheritGridGap:k5}=mt(),Pl=class extends y5{insert(e,t,i,n){if(t!=="-ms-")return super.insert(e,t,i);if(e.parent.some(m=>m.prop==="-ms-grid-rows"))return;let a=v5(e),s=k5(e,a),{rows:o,columns:u,areas:c}=w5({decl:e,gap:s||a}),f=Object.keys(c).length>0,d=Boolean(o),p=Boolean(u);return x5({gap:a,hasColumns:p,decl:e,result:n}),b5(c,e,n),(d&&p||f)&&e.cloneBefore({prop:"-ms-grid-rows",value:o,raws:{}}),p&&e.cloneBefore({prop:"-ms-grid-columns",value:u,raws:{}}),e}};Pl.names=["grid-template"];Uy.exports=Pl});var Hy=v((_I,Gy)=>{l();var S5=M(),Dl=class extends S5{prefixed(e,t){return t+e.replace("-inline","")}normalize(e){return e.replace(/(margin|padding|border)-(start|end)/,"$1-inline-$2")}};Dl.names=["border-inline-start","border-inline-end","margin-inline-start","margin-inline-end","padding-inline-start","padding-inline-end","border-start","border-end","margin-start","margin-end","padding-start","padding-end"];Gy.exports=Dl});var Qy=v((OI,Yy)=>{l();var C5=M(),Il=class extends C5{check(e){return!e.value.includes("flex-")&&e.value!=="baseline"}prefixed(e,t){return t+"grid-row-align"}normalize(){return"align-self"}};Il.names=["grid-row-align"];Yy.exports=Il});var Xy=v((EI,Jy)=>{l();var A5=M(),ir=class extends A5{keyframeParents(e){let{parent:t}=e;for(;t;){if(t.type==="atrule"&&t.name==="keyframes")return!0;({parent:t}=t)}return!1}contain3d(e){if(e.prop==="transform-origin")return!1;for(let t of ir.functions3d)if(e.value.includes(`${t}(`))return!0;return!1}set(e,t){return e=super.set(e,t),t==="-ms-"&&(e.value=e.value.replace(/rotatez/gi,"rotate")),e}insert(e,t,i){if(t==="-ms-"){if(!this.contain3d(e)&&!this.keyframeParents(e))return super.insert(e,t,i)}else if(t==="-o-"){if(!this.contain3d(e))return super.insert(e,t,i)}else return super.insert(e,t,i)}};ir.names=["transform","transform-origin"];ir.functions3d=["matrix3d","translate3d","translateZ","scale3d","scaleZ","rotate3d","rotateX","rotateY","perspective"];Jy.exports=ir});var ew=v((TI,Zy)=>{l();var Ky=pe(),_5=M(),ql=class extends _5{normalize(){return"flex-direction"}insert(e,t,i){let n;if([n,t]=Ky(t),n!==2009)return super.insert(e,t,i);if(e.parent.some(f=>f.prop===t+"box-orient"||f.prop===t+"box-direction"))return;let s=e.value,o,u;s==="inherit"||s==="initial"||s==="unset"?(o=s,u=s):(o=s.includes("row")?"horizontal":"vertical",u=s.includes("reverse")?"reverse":"normal");let c=this.clone(e);return c.prop=t+"box-orient",c.value=o,this.needCascade(e)&&(c.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,c),c=this.clone(e),c.prop=t+"box-direction",c.value=u,this.needCascade(e)&&(c.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,c)}old(e,t){let i;return[i,t]=Ky(t),i===2009?[t+"box-orient",t+"box-direction"]:super.old(e,t)}};ql.names=["flex-direction","box-direction","box-orient"];Zy.exports=ql});var rw=v((PI,tw)=>{l();var O5=M(),Rl=class extends O5{check(e){return e.value==="pixelated"}prefixed(e,t){return t==="-ms-"?"-ms-interpolation-mode":super.prefixed(e,t)}set(e,t){return t!=="-ms-"?super.set(e,t):(e.prop="-ms-interpolation-mode",e.value="nearest-neighbor",e)}normalize(){return"image-rendering"}process(e,t){return super.process(e,t)}};Rl.names=["image-rendering","interpolation-mode"];tw.exports=Rl});var nw=v((DI,iw)=>{l();var E5=M(),T5=le(),Ml=class extends E5{constructor(e,t,i){super(e,t,i);this.prefixes&&(this.prefixes=T5.uniq(this.prefixes.map(n=>n==="-ms-"?"-webkit-":n)))}};Ml.names=["backdrop-filter"];iw.exports=Ml});var aw=v((II,sw)=>{l();var P5=M(),D5=le(),Bl=class extends P5{constructor(e,t,i){super(e,t,i);this.prefixes&&(this.prefixes=D5.uniq(this.prefixes.map(n=>n==="-ms-"?"-webkit-":n)))}check(e){return e.value.toLowerCase()==="text"}};Bl.names=["background-clip"];sw.exports=Bl});var lw=v((qI,ow)=>{l();var I5=M(),q5=["none","underline","overline","line-through","blink","inherit","initial","unset"],Fl=class extends I5{check(e){return e.value.split(/\s+/).some(t=>!q5.includes(t))}};Fl.names=["text-decoration"];ow.exports=Fl});var cw=v((RI,fw)=>{l();var uw=pe(),R5=M(),nr=class extends R5{prefixed(e,t){let i;return[i,t]=uw(t),i===2009?t+"box-pack":i===2012?t+"flex-pack":super.prefixed(e,t)}normalize(){return"justify-content"}set(e,t){let i=uw(t)[0];if(i===2009||i===2012){let n=nr.oldValues[e.value]||e.value;if(e.value=n,i!==2009||n!=="distribute")return super.set(e,t)}else if(i==="final")return super.set(e,t)}};nr.names=["justify-content","flex-pack","box-pack"];nr.oldValues={"flex-end":"end","flex-start":"start","space-between":"justify","space-around":"distribute"};fw.exports=nr});var dw=v((MI,pw)=>{l();var M5=M(),Ll=class extends M5{set(e,t){let i=e.value.toLowerCase();return t==="-webkit-"&&!i.includes(" ")&&i!=="contain"&&i!=="cover"&&(e.value=e.value+" "+e.value),super.set(e,t)}};Ll.names=["background-size"];pw.exports=Ll});var mw=v((BI,hw)=>{l();var B5=M(),Nl=mt(),$l=class extends B5{insert(e,t,i){if(t!=="-ms-")return super.insert(e,t,i);let n=Nl.parse(e),[a,s]=Nl.translate(n,0,1);n[0]&&n[0].includes("span")&&(s=n[0].join("").replace(/\D/g,"")),[[e.prop,a],[`${e.prop}-span`,s]].forEach(([u,c])=>{Nl.insertDecl(e,u,c)})}};$l.names=["grid-row","grid-column"];hw.exports=$l});var ww=v((FI,yw)=>{l();var F5=M(),{prefixTrackProp:gw,prefixTrackValue:L5,autoplaceGridItems:N5,getGridGap:$5,inheritGridGap:z5}=mt(),j5=sl(),zl=class extends F5{prefixed(e,t){return t==="-ms-"?gw({prop:e,prefix:t}):super.prefixed(e,t)}normalize(e){return e.replace(/^grid-(rows|columns)/,"grid-template-$1")}insert(e,t,i,n){if(t!=="-ms-")return super.insert(e,t,i);let{parent:a,prop:s,value:o}=e,u=s.includes("rows"),c=s.includes("columns"),f=a.some(k=>k.prop==="grid-template"||k.prop==="grid-template-areas");if(f&&u)return!1;let d=new j5({options:{}}),p=d.gridStatus(a,n),m=$5(e);m=z5(e,m)||m;let b=u?m.row:m.column;(p==="no-autoplace"||p===!0)&&!f&&(b=null);let x=L5({value:o,gap:b});e.cloneBefore({prop:gw({prop:s,prefix:t}),value:x});let y=a.nodes.find(k=>k.prop==="grid-auto-flow"),w="row";if(y&&!d.disabled(y,n)&&(w=y.value.trim()),p==="autoplace"){let k=a.nodes.find(_=>_.prop==="grid-template-rows");if(!k&&f)return;if(!k&&!f){e.warn(n,"Autoplacement does not work without grid-template-rows property");return}!a.nodes.find(_=>_.prop==="grid-template-columns")&&!f&&e.warn(n,"Autoplacement does not work without grid-template-columns property"),c&&!f&&N5(e,n,m,w)}}};zl.names=["grid-template-rows","grid-template-columns","grid-rows","grid-columns"];yw.exports=zl});var vw=v((LI,bw)=>{l();var V5=M(),jl=class extends V5{check(e){return!e.value.includes("flex-")&&e.value!=="baseline"}prefixed(e,t){return t+"grid-column-align"}normalize(){return"justify-self"}};jl.names=["grid-column-align"];bw.exports=jl});var kw=v((NI,xw)=>{l();var U5=M(),Vl=class extends U5{prefixed(e,t){return t+"scroll-chaining"}normalize(){return"overscroll-behavior"}set(e,t){return e.value==="auto"?e.value="chained":(e.value==="none"||e.value==="contain")&&(e.value="none"),super.set(e,t)}};Vl.names=["overscroll-behavior","scroll-chaining"];xw.exports=Vl});var Aw=v(($I,Cw)=>{l();var W5=M(),{parseGridAreas:G5,warnMissedAreas:H5,prefixTrackProp:Y5,prefixTrackValue:Sw,getGridGap:Q5,warnGridGap:J5,inheritGridGap:X5}=mt();function K5(r){return r.trim().slice(1,-1).split(/["']\s*["']?/g)}var Ul=class extends W5{insert(e,t,i,n){if(t!=="-ms-")return super.insert(e,t,i);let a=!1,s=!1,o=e.parent,u=Q5(e);u=X5(e,u)||u,o.walkDecls(/-ms-grid-rows/,d=>d.remove()),o.walkDecls(/grid-template-(rows|columns)/,d=>{if(d.prop==="grid-template-rows"){s=!0;let{prop:p,value:m}=d;d.cloneBefore({prop:Y5({prop:p,prefix:t}),value:Sw({value:m,gap:u.row})})}else a=!0});let c=K5(e.value);a&&!s&&u.row&&c.length>1&&e.cloneBefore({prop:"-ms-grid-rows",value:Sw({value:`repeat(${c.length}, auto)`,gap:u.row}),raws:{}}),J5({gap:u,hasColumns:a,decl:e,result:n});let f=G5({rows:c,gap:u});return H5(f,e,n),e}};Ul.names=["grid-template-areas"];Cw.exports=Ul});var Ow=v((zI,_w)=>{l();var Z5=M(),Wl=class extends Z5{set(e,t){return t==="-webkit-"&&(e.value=e.value.replace(/\s*(right|left)\s*/i,"")),super.set(e,t)}};Wl.names=["text-emphasis-position"];_w.exports=Wl});var Tw=v((jI,Ew)=>{l();var e_=M(),Gl=class extends e_{set(e,t){return e.prop==="text-decoration-skip-ink"&&e.value==="auto"?(e.prop=t+"text-decoration-skip",e.value="ink",e):super.set(e,t)}};Gl.names=["text-decoration-skip-ink","text-decoration-skip"];Ew.exports=Gl});var Mw=v((VI,Rw)=>{l();"use strict";Rw.exports={wrap:Pw,limit:Dw,validate:Iw,test:Hl,curry:t_,name:qw};function Pw(r,e,t){var i=e-r;return((t-r)%i+i)%i+r}function Dw(r,e,t){return Math.max(r,Math.min(e,t))}function Iw(r,e,t,i,n){if(!Hl(r,e,t,i,n))throw new Error(t+" is outside of range ["+r+","+e+")");return t}function Hl(r,e,t,i,n){return!(te||n&&t===e||i&&t===r)}function qw(r,e,t,i){return(t?"(":"[")+r+","+e+(i?")":"]")}function t_(r,e,t,i){var n=qw.bind(null,r,e,t,i);return{wrap:Pw.bind(null,r,e),limit:Dw.bind(null,r,e),validate:function(a){return Iw(r,e,a,t,i)},test:function(a){return Hl(r,e,a,t,i)},toString:n,name:n}}});var Lw=v((UI,Fw)=>{l();var Yl=Kn(),r_=Mw(),i_=Qt(),n_=ke(),s_=le(),Bw=/top|left|right|bottom/gi,Qe=class extends n_{replace(e,t){let i=Yl(e);for(let n of i.nodes)if(n.type==="function"&&n.value===this.name)if(n.nodes=this.newDirection(n.nodes),n.nodes=this.normalize(n.nodes),t==="-webkit- old"){if(!this.oldWebkit(n))return!1}else n.nodes=this.convertDirection(n.nodes),n.value=t+n.value;return i.toString()}replaceFirst(e,...t){return t.map(n=>n===" "?{type:"space",value:n}:{type:"word",value:n}).concat(e.slice(1))}normalizeUnit(e,t){return`${parseFloat(e)/t*360}deg`}normalize(e){if(!e[0])return e;if(/-?\d+(.\d+)?grad/.test(e[0].value))e[0].value=this.normalizeUnit(e[0].value,400);else if(/-?\d+(.\d+)?rad/.test(e[0].value))e[0].value=this.normalizeUnit(e[0].value,2*Math.PI);else if(/-?\d+(.\d+)?turn/.test(e[0].value))e[0].value=this.normalizeUnit(e[0].value,1);else if(e[0].value.includes("deg")){let t=parseFloat(e[0].value);t=r_.wrap(0,360,t),e[0].value=`${t}deg`}return e[0].value==="0deg"?e=this.replaceFirst(e,"to"," ","top"):e[0].value==="90deg"?e=this.replaceFirst(e,"to"," ","right"):e[0].value==="180deg"?e=this.replaceFirst(e,"to"," ","bottom"):e[0].value==="270deg"&&(e=this.replaceFirst(e,"to"," ","left")),e}newDirection(e){if(e[0].value==="to"||(Bw.lastIndex=0,!Bw.test(e[0].value)))return e;e.unshift({type:"word",value:"to"},{type:"space",value:" "});for(let t=2;t0&&(e[0].value==="to"?this.fixDirection(e):e[0].value.includes("deg")?this.fixAngle(e):this.isRadial(e)&&this.fixRadial(e)),e}fixDirection(e){e.splice(0,2);for(let t of e){if(t.type==="div")break;t.type==="word"&&(t.value=this.revertDirection(t.value))}}fixAngle(e){let t=e[0].value;t=parseFloat(t),t=Math.abs(450-t)%360,t=this.roundFloat(t,3),e[0].value=`${t}deg`}fixRadial(e){let t=[],i=[],n,a,s,o,u;for(o=0;o{l();var a_=Qt(),o_=ke();function Nw(r){return new RegExp(`(^|[\\s,(])(${r}($|[\\s),]))`,"gi")}var Ql=class extends o_{regexp(){return this.regexpCache||(this.regexpCache=Nw(this.name)),this.regexpCache}isStretch(){return this.name==="stretch"||this.name==="fill"||this.name==="fill-available"}replace(e,t){return t==="-moz-"&&this.isStretch()?e.replace(this.regexp(),"$1-moz-available$3"):t==="-webkit-"&&this.isStretch()?e.replace(this.regexp(),"$1-webkit-fill-available$3"):super.replace(e,t)}old(e){let t=e+this.name;return this.isStretch()&&(e==="-moz-"?t="-moz-available":e==="-webkit-"&&(t="-webkit-fill-available")),new a_(this.name,t,t,Nw(t))}add(e,t){if(!(e.prop.includes("grid")&&t!=="-webkit-"))return super.add(e,t)}};Ql.names=["max-content","min-content","fit-content","fill","fill-available","stretch"];$w.exports=Ql});var Uw=v((GI,Vw)=>{l();var jw=Qt(),l_=ke(),Jl=class extends l_{replace(e,t){return t==="-webkit-"?e.replace(this.regexp(),"$1-webkit-optimize-contrast"):t==="-moz-"?e.replace(this.regexp(),"$1-moz-crisp-edges"):super.replace(e,t)}old(e){return e==="-webkit-"?new jw(this.name,"-webkit-optimize-contrast"):e==="-moz-"?new jw(this.name,"-moz-crisp-edges"):super.old(e)}};Jl.names=["pixelated"];Vw.exports=Jl});var Gw=v((HI,Ww)=>{l();var u_=ke(),Xl=class extends u_{replace(e,t){let i=super.replace(e,t);return t==="-webkit-"&&(i=i.replace(/("[^"]+"|'[^']+')(\s+\d+\w)/gi,"url($1)$2")),i}};Xl.names=["image-set"];Ww.exports=Xl});var Yw=v((YI,Hw)=>{l();var f_=ge().list,c_=ke(),Kl=class extends c_{replace(e,t){return f_.space(e).map(i=>{if(i.slice(0,+this.name.length+1)!==this.name+"(")return i;let n=i.lastIndexOf(")"),a=i.slice(n+1),s=i.slice(this.name.length+1,n);if(t==="-webkit-"){let o=s.match(/\d*.?\d+%?/);o?(s=s.slice(o[0].length).trim(),s+=`, ${o[0]}`):s+=", 0.5"}return t+this.name+"("+s+")"+a}).join(" ")}};Kl.names=["cross-fade"];Hw.exports=Kl});var Jw=v((QI,Qw)=>{l();var p_=pe(),d_=Qt(),h_=ke(),Zl=class extends h_{constructor(e,t){super(e,t);e==="display-flex"&&(this.name="flex")}check(e){return e.prop==="display"&&e.value===this.name}prefixed(e){let t,i;return[t,e]=p_(e),t===2009?this.name==="flex"?i="box":i="inline-box":t===2012?this.name==="flex"?i="flexbox":i="inline-flexbox":t==="final"&&(i=this.name),e+i}replace(e,t){return this.prefixed(t)}old(e){let t=this.prefixed(e);if(!!t)return new d_(this.name,t)}};Zl.names=["display-flex","inline-flex"];Qw.exports=Zl});var Kw=v((JI,Xw)=>{l();var m_=ke(),eu=class extends m_{constructor(e,t){super(e,t);e==="display-grid"&&(this.name="grid")}check(e){return e.prop==="display"&&e.value===this.name}};eu.names=["display-grid","inline-grid"];Xw.exports=eu});var eb=v((XI,Zw)=>{l();var g_=ke(),tu=class extends g_{constructor(e,t){super(e,t);e==="filter-function"&&(this.name="filter")}};tu.names=["filter","filter-function"];Zw.exports=tu});var nb=v((KI,ib)=>{l();var tb=ai(),B=M(),rb=Fm(),y_=tg(),w_=sl(),b_=vg(),ru=dt(),sr=Jt(),v_=Eg(),$e=ke(),ar=le(),x_=Pg(),k_=Ig(),S_=Rg(),C_=Bg(),A_=zg(),__=Ug(),O_=Gg(),E_=Yg(),T_=Jg(),P_=Kg(),D_=ey(),I_=ry(),q_=ny(),R_=ay(),M_=ly(),B_=cy(),F_=dy(),L_=gy(),N_=wy(),$_=vy(),z_=Sy(),j_=Ay(),V_=Ey(),U_=Py(),W_=Iy(),G_=Ry(),H_=By(),Y_=Ny(),Q_=zy(),J_=Vy(),X_=Wy(),K_=Hy(),Z_=Qy(),eO=Xy(),tO=ew(),rO=rw(),iO=nw(),nO=aw(),sO=lw(),aO=cw(),oO=dw(),lO=mw(),uO=ww(),fO=vw(),cO=kw(),pO=Aw(),dO=Ow(),hO=Tw(),mO=Lw(),gO=zw(),yO=Uw(),wO=Gw(),bO=Yw(),vO=Jw(),xO=Kw(),kO=eb();sr.hack(x_);sr.hack(k_);sr.hack(S_);sr.hack(C_);B.hack(A_);B.hack(__);B.hack(O_);B.hack(E_);B.hack(T_);B.hack(P_);B.hack(D_);B.hack(I_);B.hack(q_);B.hack(R_);B.hack(M_);B.hack(B_);B.hack(F_);B.hack(L_);B.hack(N_);B.hack($_);B.hack(z_);B.hack(j_);B.hack(V_);B.hack(U_);B.hack(W_);B.hack(G_);B.hack(H_);B.hack(Y_);B.hack(Q_);B.hack(J_);B.hack(X_);B.hack(K_);B.hack(Z_);B.hack(eO);B.hack(tO);B.hack(rO);B.hack(iO);B.hack(nO);B.hack(sO);B.hack(aO);B.hack(oO);B.hack(lO);B.hack(uO);B.hack(fO);B.hack(cO);B.hack(pO);B.hack(dO);B.hack(hO);$e.hack(mO);$e.hack(gO);$e.hack(yO);$e.hack(wO);$e.hack(bO);$e.hack(vO);$e.hack(xO);$e.hack(kO);var iu=new Map,li=class{constructor(e,t,i={}){this.data=e,this.browsers=t,this.options=i,[this.add,this.remove]=this.preprocess(this.select(this.data)),this.transition=new y_(this),this.processor=new w_(this)}cleaner(){if(this.cleanerCache)return this.cleanerCache;if(this.browsers.selected.length){let e=new ru(this.browsers.data,[]);this.cleanerCache=new li(this.data,e,this.options)}else return this;return this.cleanerCache}select(e){let t={add:{},remove:{}};for(let i in e){let n=e[i],a=n.browsers.map(u=>{let c=u.split(" ");return{browser:`${c[0]} ${c[1]}`,note:c[2]}}),s=a.filter(u=>u.note).map(u=>`${this.browsers.prefix(u.browser)} ${u.note}`);s=ar.uniq(s),a=a.filter(u=>this.browsers.isSelected(u.browser)).map(u=>{let c=this.browsers.prefix(u.browser);return u.note?`${c} ${u.note}`:c}),a=this.sort(ar.uniq(a)),this.options.flexbox==="no-2009"&&(a=a.filter(u=>!u.includes("2009")));let o=n.browsers.map(u=>this.browsers.prefix(u));n.mistakes&&(o=o.concat(n.mistakes)),o=o.concat(s),o=ar.uniq(o),a.length?(t.add[i]=a,a.length!a.includes(u)))):t.remove[i]=o}return t}sort(e){return e.sort((t,i)=>{let n=ar.removeNote(t).length,a=ar.removeNote(i).length;return n===a?i.length-t.length:a-n})}preprocess(e){let t={selectors:[],"@supports":new b_(li,this)};for(let n in e.add){let a=e.add[n];if(n==="@keyframes"||n==="@viewport")t[n]=new v_(n,a,this);else if(n==="@resolution")t[n]=new rb(n,a,this);else if(this.data[n].selector)t.selectors.push(sr.load(n,a,this));else{let s=this.data[n].props;if(s){let o=$e.load(n,a,this);for(let u of s)t[u]||(t[u]={values:[]}),t[u].values.push(o)}else{let o=t[n]&&t[n].values||[];t[n]=B.load(n,a,this),t[n].values=o}}}let i={selectors:[]};for(let n in e.remove){let a=e.remove[n];if(this.data[n].selector){let s=sr.load(n,a);for(let o of a)i.selectors.push(s.old(o))}else if(n==="@keyframes"||n==="@viewport")for(let s of a){let o=`@${s}${n.slice(1)}`;i[o]={remove:!0}}else if(n==="@resolution")i[n]=new rb(n,a,this);else{let s=this.data[n].props;if(s){let o=$e.load(n,[],this);for(let u of a){let c=o.old(u);if(c)for(let f of s)i[f]||(i[f]={}),i[f].values||(i[f].values=[]),i[f].values.push(c)}}else for(let o of a){let u=this.decl(n).old(n,o);if(n==="align-self"){let c=t[n]&&t[n].prefixes;if(c){if(o==="-webkit- 2009"&&c.includes("-webkit-"))continue;if(o==="-webkit-"&&c.includes("-webkit- 2009"))continue}}for(let c of u)i[c]||(i[c]={}),i[c].remove=!0}}}return[t,i]}decl(e){return iu.has(e)||iu.set(e,B.load(e)),iu.get(e)}unprefixed(e){let t=this.normalize(tb.unprefixed(e));return t==="flex-direction"&&(t="flex-flow"),t}normalize(e){return this.decl(e).normalize(e)}prefixed(e,t){return e=tb.unprefixed(e),this.decl(e).prefixed(e,t)}values(e,t){let i=this[e],n=i["*"]&&i["*"].values,a=i[t]&&i[t].values;return n&&a?ar.uniq(n.concat(a)):n||a||[]}group(e){let t=e.parent,i=t.index(e),{length:n}=t.nodes,a=this.unprefixed(e.prop),s=(o,u)=>{for(i+=o;i>=0&&i{l();sb.exports={"backdrop-filter":{feature:"css-backdrop-filter",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5","safari 16.5"]},element:{props:["background","background-image","border-image","mask","list-style","list-style-image","content","mask-image"],feature:"css-element-function",browsers:["firefox 114"]},"user-select":{mistakes:["-khtml-"],feature:"user-select-none",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5","safari 16.5"]},"background-clip":{feature:"background-clip-text",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},hyphens:{feature:"css-hyphens",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5","safari 16.5"]},fill:{props:["width","min-width","max-width","height","min-height","max-height","inline-size","min-inline-size","max-inline-size","block-size","min-block-size","max-block-size","grid","grid-template","grid-template-rows","grid-template-columns","grid-auto-columns","grid-auto-rows"],feature:"intrinsic-width",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"fill-available":{props:["width","min-width","max-width","height","min-height","max-height","inline-size","min-inline-size","max-inline-size","block-size","min-block-size","max-block-size","grid","grid-template","grid-template-rows","grid-template-columns","grid-auto-columns","grid-auto-rows"],feature:"intrinsic-width",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},stretch:{props:["width","min-width","max-width","height","min-height","max-height","inline-size","min-inline-size","max-inline-size","block-size","min-block-size","max-block-size","grid","grid-template","grid-template-rows","grid-template-columns","grid-auto-columns","grid-auto-rows"],feature:"intrinsic-width",browsers:["firefox 114"]},"fit-content":{props:["width","min-width","max-width","height","min-height","max-height","inline-size","min-inline-size","max-inline-size","block-size","min-block-size","max-block-size","grid","grid-template","grid-template-rows","grid-template-columns","grid-auto-columns","grid-auto-rows"],feature:"intrinsic-width",browsers:["firefox 114"]},"text-decoration-style":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-decoration-color":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-decoration-line":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-decoration":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-decoration-skip":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-decoration-skip-ink":{feature:"text-decoration",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"text-size-adjust":{feature:"text-size-adjust",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5"]},"mask-clip":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-composite":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-image":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-origin":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-repeat":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border-repeat":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border-source":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},mask:{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-position":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-size":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border-outset":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border-width":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"mask-border-slice":{feature:"css-masks",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},"clip-path":{feature:"css-clip-path",browsers:["samsung 21"]},"box-decoration-break":{feature:"css-boxdecorationbreak",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5","opera 99","safari 16.5","samsung 21"]},appearance:{feature:"css-appearance",browsers:["samsung 21"]},"image-set":{props:["background","background-image","border-image","cursor","mask","mask-image","list-style","list-style-image","content"],feature:"css-image-set",browsers:["and_uc 15.5","chrome 109","samsung 21"]},"cross-fade":{props:["background","background-image","border-image","mask","list-style","list-style-image","content","mask-image"],feature:"css-cross-fade",browsers:["and_chr 114","and_uc 15.5","chrome 109","chrome 113","chrome 114","edge 114","opera 99","samsung 21"]},isolate:{props:["unicode-bidi"],feature:"css-unicode-bidi",browsers:["ios_saf 16.1","ios_saf 16.3","ios_saf 16.4","ios_saf 16.5","safari 16.5"]},"color-adjust":{feature:"css-color-adjust",browsers:["chrome 109","chrome 113","chrome 114","edge 114","opera 99"]}}});var lb=v((eq,ob)=>{l();ob.exports={}});var pb=v((tq,cb)=>{l();var SO=Ho(),{agents:CO}=(Gn(),Wn),nu=Sm(),AO=dt(),_O=nb(),OO=ab(),EO=lb(),ub={browsers:CO,prefixes:OO},fb=` +`); + w.push(` Use \`${r.replace("[", `[${_}:`)}\` for \`${E.trim()}\``); + break; + } + F.warn([ + `The class \`${r}\` is ambiguous and matches multiple utilities.`, + ...w, + `If this is content and not a class, replace it with \`${r.replace("[", "[").replace("]", "]")}\` to silence this warning.`, + ]); + continue; + } + } + o = o.map((p) => p.filter((m) => qd(m[1]))); + } + ((o = o.flat()), (o = Array.from(D2(o, i))), (o = k2(o, e)), a && (o = S2(o, i))); + for (let p of n) o = C2(p, o, e); + for (let p of o) + ((p[1].raws.tailwind = { ...p[1].raws.tailwind, candidate: r }), + (p = I2(p, { context: e, candidate: r })), + p !== null && (yield p)); + } + } + function I2(r, { context: e, candidate: t }) { + if (!r[0].collectedFormats) return r; + let i = !0, + n; + try { + n = Vt(r[0].collectedFormats, { context: e, candidate: t }); + } catch { + return null; + } + let a = j.root({ nodes: [r[1].clone()] }); + return ( + a.walkRules((s) => { + if (!An(s)) + try { + let o = kn(s.selector, n, { candidate: t, context: e }); + if (o === null) { + s.remove(); + return; + } + s.selector = o; + } catch { + return ((i = !1), !1); + } + }), + !i || a.nodes.length === 0 ? null : ((r[1] = a.nodes[0]), r) + ); + } + function An(r) { + return r.parent && r.parent.type === "atrule" && r.parent.name === "keyframes"; + } + function q2(r) { + if (r === !0) + return (e) => { + An(e) || + e.walkDecls((t) => { + t.parent.type === "rule" && !An(t.parent) && (t.important = !0); + }); + }; + if (typeof r == "string") + return (e) => { + An(e) || (e.selectors = e.selectors.map((t) => Sn(t, r))); + }; + } + function _n(r, e, t = !1) { + let i = [], + n = q2(e.tailwindConfig.important); + for (let a of r) { + if (e.notClassCache.has(a)) continue; + if (e.candidateRuleCache.has(a)) { + i = i.concat(Array.from(e.candidateRuleCache.get(a))); + continue; + } + let s = Array.from(fo(a, e)); + if (s.length === 0) { + e.notClassCache.add(a); + continue; + } + e.classCache.set(a, s); + let o = e.candidateRuleCache.get(a) ?? new Set(); + e.candidateRuleCache.set(a, o); + for (let u of s) { + let [{ sort: c, options: f }, d] = u; + if (f.respectImportant && n) { + let m = j.root({ nodes: [d.clone()] }); + (m.walkRules(n), (d = m.nodes[0])); + } + let p = [c, t ? d.clone() : d]; + (o.add(p), e.ruleCache.add(p), i.push(p)); + } + } + return i; + } + function co(r) { + return r.startsWith("[") && r.endsWith("]"); + } + var Cn, + v2, + A2, + On = C(() => { + l(); + st(); + Cn = X(Me()); + Qa(); + At(); + dn(); + hr(); + Oe(); + lt(); + so(); + Xa(); + dr(); + ei(); + eo(); + _t(); + je(); + oo(); + v2 = (0, Cn.default)((r) => r.first.filter(({ type: e }) => e === "class").pop().value); + A2 = /^[a-z_-]/; + }); + var Md, + Bd = C(() => { + l(); + Md = {}; + }); + function R2(r) { + try { + return Md.createHash("md5").update(r, "utf-8").digest("binary"); + } catch (e) { + return ""; + } + } + function Fd(r, e) { + let t = e.toString(); + if (!t.includes("@tailwind")) return !1; + let i = Za.get(r), + n = R2(t), + a = i !== n; + return (Za.set(r, n), a); + } + var Ld = C(() => { + l(); + Bd(); + lt(); + }); + function Tn(r) { + return (r > 0n) - (r < 0n); + } + var Nd = C(() => { + l(); + }); + function $d(r, e) { + let t = 0n, + i = 0n; + for (let [n, a] of e) r & n && ((t = t | n), (i = i | a)); + return (r & ~t) | i; + } + var zd = C(() => { + l(); + }); + function jd(r) { + let e = null; + for (let t of r) ((e = e ?? t), (e = e > t ? e : t)); + return e; + } + function M2(r, e) { + let t = r.length, + i = e.length, + n = t < i ? t : i; + for (let a = 0; a < n; a++) { + let s = r.charCodeAt(a) - e.charCodeAt(a); + if (s !== 0) return s; + } + return t - i; + } + var po, + Vd = C(() => { + l(); + Nd(); + zd(); + po = class { + constructor() { + ((this.offsets = { defaults: 0n, base: 0n, components: 0n, utilities: 0n, variants: 0n, user: 0n }), + (this.layerPositions = { + defaults: 0n, + base: 1n, + components: 2n, + utilities: 3n, + user: 4n, + variants: 5n, + }), + (this.reservedVariantBits = 0n), + (this.variantOffsets = new Map())); + } + create(e) { + return { + layer: e, + parentLayer: e, + arbitrary: 0n, + variants: 0n, + parallelIndex: 0n, + index: this.offsets[e]++, + propertyOffset: 0n, + property: "", + options: [], + }; + } + arbitraryProperty(e) { + return { ...this.create("utilities"), arbitrary: 1n, property: e }; + } + forVariant(e, t = 0) { + let i = this.variantOffsets.get(e); + if (i === void 0) throw new Error(`Cannot find offset for unknown variant ${e}`); + return { ...this.create("variants"), variants: i << BigInt(t) }; + } + applyVariantOffset(e, t, i) { + return ( + (i.variant = t.variants), + { + ...e, + layer: "variants", + parentLayer: e.layer === "variants" ? e.parentLayer : e.layer, + variants: e.variants | t.variants, + options: i.sort ? [].concat(i, e.options) : e.options, + parallelIndex: jd([e.parallelIndex, t.parallelIndex]), + } + ); + } + applyParallelOffset(e, t) { + return { ...e, parallelIndex: BigInt(t) }; + } + recordVariants(e, t) { + for (let i of e) this.recordVariant(i, t(i)); + } + recordVariant(e, t = 1) { + return ( + this.variantOffsets.set(e, 1n << this.reservedVariantBits), + (this.reservedVariantBits += BigInt(t)), + { ...this.create("variants"), variants: this.variantOffsets.get(e) } + ); + } + compare(e, t) { + if (e.layer !== t.layer) return this.layerPositions[e.layer] - this.layerPositions[t.layer]; + if (e.parentLayer !== t.parentLayer) + return this.layerPositions[e.parentLayer] - this.layerPositions[t.parentLayer]; + for (let i of e.options) + for (let n of t.options) { + if (i.id !== n.id || !i.sort || !n.sort) continue; + let a = jd([i.variant, n.variant]) ?? 0n, + s = ~(a | (a - 1n)), + o = e.variants & s, + u = t.variants & s; + if (o !== u) continue; + let c = i.sort( + { value: i.value, modifier: i.modifier }, + { value: n.value, modifier: n.modifier } + ); + if (c !== 0) return c; + } + return e.variants !== t.variants + ? e.variants - t.variants + : e.parallelIndex !== t.parallelIndex + ? e.parallelIndex - t.parallelIndex + : e.arbitrary !== t.arbitrary + ? e.arbitrary - t.arbitrary + : e.propertyOffset !== t.propertyOffset + ? e.propertyOffset - t.propertyOffset + : e.index - t.index; + } + recalculateVariantOffsets() { + let e = Array.from(this.variantOffsets.entries()) + .filter(([n]) => n.startsWith("[")) + .sort(([n], [a]) => M2(n, a)), + t = e.map(([, n]) => n).sort((n, a) => Tn(n - a)); + return e.map(([, n], a) => [n, t[a]]).filter(([n, a]) => n !== a); + } + remapArbitraryVariantOffsets(e) { + let t = this.recalculateVariantOffsets(); + return t.length === 0 + ? e + : e.map((i) => { + let [n, a] = i; + return ((n = { ...n, variants: $d(n.variants, t) }), [n, a]); + }); + } + sortArbitraryProperties(e) { + let t = new Set(); + for (let [s] of e) s.arbitrary === 1n && t.add(s.property); + if (t.size === 0) return e; + let i = Array.from(t).sort(), + n = new Map(), + a = 1n; + for (let s of i) n.set(s, a++); + return e.map((s) => { + let [o, u] = s; + return ((o = { ...o, propertyOffset: n.get(o.property) ?? 0n }), [o, u]); + }); + } + sort(e) { + return ( + (e = this.remapArbitraryVariantOffsets(e)), + (e = this.sortArbitraryProperties(e)), + e.sort(([t], [i]) => Tn(this.compare(t, i))) + ); + } + }; + }); + function yo(r, e) { + let t = r.tailwindConfig.prefix; + return typeof t == "function" ? t(e) : t + e; + } + function Wd({ type: r = "any", ...e }) { + let t = [].concat(r); + return { + ...e, + types: t.map((i) => (Array.isArray(i) ? { type: i[0], ...i[1] } : { type: i, preferOnConflict: !1 })), + }; + } + function B2(r) { + let e = [], + t = "", + i = 0; + for (let n = 0; n < r.length; n++) { + let a = r[n]; + if (a === "\\") t += "\\" + r[++n]; + else if (a === "{") (++i, e.push(t.trim()), (t = "")); + else if (a === "}") { + if (--i < 0) throw new Error("Your { and } are unbalanced."); + (e.push(t.trim()), (t = "")); + } else t += a; + } + return (t.length > 0 && e.push(t.trim()), (e = e.filter((n) => n !== "")), e); + } + function F2(r, e, { before: t = [] } = {}) { + if (((t = [].concat(t)), t.length <= 0)) { + r.push(e); + return; + } + let i = r.length - 1; + for (let n of t) { + let a = r.indexOf(n); + a !== -1 && (i = Math.min(i, a)); + } + r.splice(i, 0, e); + } + function Gd(r) { + return Array.isArray(r) ? r.flatMap((e) => (!Array.isArray(e) && !ie(e) ? e : Lt(e))) : Gd([r]); + } + function L2(r, e) { + return (0, ho.default)((i) => { + let n = []; + return ( + e && e(i), + i.walkClasses((a) => { + n.push(a.value); + }), + n + ); + }).transformSync(r); + } + function N2(r) { + r.walkPseudos((e) => { + e.value === ":not" && e.remove(); + }); + } + function $2(r, e = { containsNonOnDemandable: !1 }, t = 0) { + let i = [], + n = []; + r.type === "rule" ? n.push(...r.selectors) : r.type === "atrule" && r.walkRules((a) => n.push(...a.selectors)); + for (let a of n) { + let s = L2(a, N2); + s.length === 0 && (e.containsNonOnDemandable = !0); + for (let o of s) i.push(o); + } + return t === 0 ? [e.containsNonOnDemandable || i.length === 0, i] : i; + } + function Pn(r) { + return Gd(r).flatMap((e) => { + let t = new Map(), + [i, n] = $2(e); + return (i && n.unshift(He), n.map((a) => (t.has(e) || t.set(e, e), [a, t.get(e)]))); + }); + } + function En(r) { + return r.startsWith("@") || r.includes("&"); + } + function ri(r) { + r = r + .replace(/\n+/g, "") + .replace(/\s{1,}/g, " ") + .trim(); + let e = B2(r) + .map((t) => { + if (!t.startsWith("@")) return ({ format: a }) => a(t); + let [, i, n] = /@(\S*)( .+|[({].*)?/g.exec(t); + return ({ wrap: a }) => a(j.atRule({ name: i, params: n?.trim() ?? "" })); + }) + .reverse(); + return (t) => { + for (let i of e) i(t); + }; + } + function z2(r, e, { variantList: t, variantMap: i, offsets: n, classList: a }) { + function s(p, m) { + return p ? (0, Ud.default)(r, p, m) : r; + } + function o(p) { + return Nt(r.prefix, p); + } + function u(p, m) { + return p === He ? He : m.respectPrefix ? e.tailwindConfig.prefix + p : p; + } + function c(p, m, b = {}) { + let x = Ze(p), + y = s(["theme", ...x], m); + return Ge(x[0])(y, b); + } + let f = 0, + d = { + postcss: j, + prefix: o, + e: ce, + config: s, + theme: c, + corePlugins: (p) => + Array.isArray(r.corePlugins) ? r.corePlugins.includes(p) : s(["corePlugins", p], !0), + variants: () => [], + addBase(p) { + for (let [m, b] of Pn(p)) { + let x = u(m, {}), + y = n.create("base"); + (e.candidateRuleMap.has(x) || e.candidateRuleMap.set(x, []), + e.candidateRuleMap.get(x).push([{ sort: y, layer: "base" }, b])); + } + }, + addDefaults(p, m) { + let b = { [`@defaults ${p}`]: m }; + for (let [x, y] of Pn(b)) { + let w = u(x, {}); + (e.candidateRuleMap.has(w) || e.candidateRuleMap.set(w, []), + e.candidateRuleMap.get(w).push([{ sort: n.create("defaults"), layer: "defaults" }, y])); + } + }, + addComponents(p, m) { + m = Object.assign( + {}, + { preserveSource: !1, respectPrefix: !0, respectImportant: !1 }, + Array.isArray(m) ? {} : m + ); + for (let [x, y] of Pn(p)) { + let w = u(x, m); + (a.add(w), + e.candidateRuleMap.has(w) || e.candidateRuleMap.set(w, []), + e.candidateRuleMap + .get(w) + .push([{ sort: n.create("components"), layer: "components", options: m }, y])); + } + }, + addUtilities(p, m) { + m = Object.assign( + {}, + { preserveSource: !1, respectPrefix: !0, respectImportant: !0 }, + Array.isArray(m) ? {} : m + ); + for (let [x, y] of Pn(p)) { + let w = u(x, m); + (a.add(w), + e.candidateRuleMap.has(w) || e.candidateRuleMap.set(w, []), + e.candidateRuleMap + .get(w) + .push([{ sort: n.create("utilities"), layer: "utilities", options: m }, y])); + } + }, + matchUtilities: function (p, m) { + m = Wd({ ...{ respectPrefix: !0, respectImportant: !0, modifiers: !1 }, ...m }); + let x = n.create("utilities"); + for (let y in p) { + let S = function (E, { isOnlyPlugin: I }) { + let [q, R, J] = gs(m.types, E, m, r); + if (q === void 0) return []; + if (!m.types.some(({ type: ee }) => ee === R)) + if (I) + F.warn([ + `Unnecessary typehint \`${R}\` in \`${y}-${E}\`.`, + `You can safely update it to \`${y}-${E.replace(R + ":", "")}\`.`, + ]); + else return []; + if (!zt(q)) return []; + let ue = { + get modifier() { + return ( + m.modifiers || + F.warn(`modifier-used-without-options-for-${y}`, [ + "Your plugin must set `modifiers: true` in its options to support modifiers.", + ]), + J + ); + }, + }, + de = K(r, "generalizedModifiers"); + return [] + .concat(de ? k(q, ue) : k(q)) + .filter(Boolean) + .map((ee) => ({ [hn(y, E)]: ee })); + }, + w = u(y, m), + k = p[y]; + a.add([w, m]); + let _ = [{ sort: x, layer: "utilities", options: m }, S]; + (e.candidateRuleMap.has(w) || e.candidateRuleMap.set(w, []), e.candidateRuleMap.get(w).push(_)); + } + }, + matchComponents: function (p, m) { + m = Wd({ ...{ respectPrefix: !0, respectImportant: !1, modifiers: !1 }, ...m }); + let x = n.create("components"); + for (let y in p) { + let S = function (E, { isOnlyPlugin: I }) { + let [q, R, J] = gs(m.types, E, m, r); + if (q === void 0) return []; + if (!m.types.some(({ type: ee }) => ee === R)) + if (I) + F.warn([ + `Unnecessary typehint \`${R}\` in \`${y}-${E}\`.`, + `You can safely update it to \`${y}-${E.replace(R + ":", "")}\`.`, + ]); + else return []; + if (!zt(q)) return []; + let ue = { + get modifier() { + return ( + m.modifiers || + F.warn(`modifier-used-without-options-for-${y}`, [ + "Your plugin must set `modifiers: true` in its options to support modifiers.", + ]), + J + ); + }, + }, + de = K(r, "generalizedModifiers"); + return [] + .concat(de ? k(q, ue) : k(q)) + .filter(Boolean) + .map((ee) => ({ [hn(y, E)]: ee })); + }, + w = u(y, m), + k = p[y]; + a.add([w, m]); + let _ = [{ sort: x, layer: "components", options: m }, S]; + (e.candidateRuleMap.has(w) || e.candidateRuleMap.set(w, []), e.candidateRuleMap.get(w).push(_)); + } + }, + addVariant(p, m, b = {}) { + ((m = [].concat(m).map((x) => { + if (typeof x != "string") + return (y = {}) => { + let { args: w, modifySelectors: k, container: S, separator: _, wrap: E, format: I } = y, + q = x( + Object.assign( + { modifySelectors: k, container: S, separator: _ }, + b.type === mo.MatchVariant && { args: w, wrap: E, format: I } + ) + ); + if (typeof q == "string" && !En(q)) + throw new Error( + `Your custom variant \`${p}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.` + ); + return Array.isArray(q) + ? q.filter((R) => typeof R == "string").map((R) => ri(R)) + : q && typeof q == "string" && ri(q)(y); + }; + if (!En(x)) + throw new Error( + `Your custom variant \`${p}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.` + ); + return ri(x); + })), + F2(t, p, b), + i.set(p, m), + e.variantOptions.set(p, b)); + }, + matchVariant(p, m, b) { + let x = b?.id ?? ++f, + y = p === "@", + w = K(r, "generalizedModifiers"); + for (let [S, _] of Object.entries(b?.values ?? {})) + S !== "DEFAULT" && + d.addVariant( + y ? `${p}${S}` : `${p}-${S}`, + ({ args: E, container: I }) => + m(_, w ? { modifier: E?.modifier, container: I } : { container: I }), + { ...b, value: _, id: x, type: mo.MatchVariant, variantInfo: go.Base } + ); + let k = "DEFAULT" in (b?.values ?? {}); + d.addVariant( + p, + ({ args: S, container: _ }) => + S?.value === ti && !k + ? null + : m( + S?.value === ti + ? b.values.DEFAULT + : (S?.value ?? (typeof S == "string" ? S : "")), + w ? { modifier: S?.modifier, container: _ } : { container: _ } + ), + { ...b, id: x, type: mo.MatchVariant, variantInfo: go.Dynamic } + ); + }, + }; + return d; + } + function Dn(r) { + return (wo.has(r) || wo.set(r, new Map()), wo.get(r)); + } + function Hd(r, e) { + let t = !1, + i = new Map(); + for (let n of r) { + if (!n) continue; + let a = Ss.parse(n), + s = a.hash ? a.href.replace(a.hash, "") : a.href; + s = a.search ? s.replace(a.search, "") : s; + let o = te.statSync(decodeURIComponent(s), { throwIfNoEntry: !1 })?.mtimeMs; + !o || ((!e.has(n) || o > e.get(n)) && (t = !0), i.set(n, o)); + } + return [t, i]; + } + function Yd(r) { + r.walkAtRules((e) => { + ["responsive", "variants"].includes(e.name) && (Yd(e), e.before(e.nodes), e.remove()); + }); + } + function j2(r) { + let e = []; + return ( + r.each((t) => { + t.type === "atrule" && + ["responsive", "variants"].includes(t.name) && + ((t.name = "layer"), (t.params = "utilities")); + }), + r.walkAtRules("layer", (t) => { + if ((Yd(t), t.params === "base")) { + for (let i of t.nodes) + e.push(function ({ addBase: n }) { + n(i, { respectPrefix: !1 }); + }); + t.remove(); + } else if (t.params === "components") { + for (let i of t.nodes) + e.push(function ({ addComponents: n }) { + n(i, { respectPrefix: !1, preserveSource: !0 }); + }); + t.remove(); + } else if (t.params === "utilities") { + for (let i of t.nodes) + e.push(function ({ addUtilities: n }) { + n(i, { respectPrefix: !1, preserveSource: !0 }); + }); + t.remove(); + } + }), + e + ); + } + function V2(r, e) { + let t = Object.entries({ ...H, ...Sd }) + .map(([u, c]) => (r.tailwindConfig.corePlugins.includes(u) ? c : null)) + .filter(Boolean), + i = r.tailwindConfig.plugins.map( + (u) => (u.__isOptionsFunction && (u = u()), typeof u == "function" ? u : u.handler) + ), + n = j2(e), + a = [ + H.childVariant, + H.pseudoElementVariants, + H.pseudoClassVariants, + H.hasVariants, + H.ariaVariants, + H.dataVariants, + ], + s = [ + H.supportsVariants, + H.reducedMotionVariants, + H.prefersContrastVariants, + H.screenVariants, + H.orientationVariants, + H.directionVariants, + H.darkVariants, + H.forcedColorsVariants, + H.printVariant, + ]; + return ( + (r.tailwindConfig.darkMode === "class" || + (Array.isArray(r.tailwindConfig.darkMode) && r.tailwindConfig.darkMode[0] === "class")) && + (s = [ + H.supportsVariants, + H.reducedMotionVariants, + H.prefersContrastVariants, + H.darkVariants, + H.screenVariants, + H.orientationVariants, + H.directionVariants, + H.forcedColorsVariants, + H.printVariant, + ]), + [...t, ...a, ...i, ...s, ...n] + ); + } + function U2(r, e) { + let t = [], + i = new Map(); + e.variantMap = i; + let n = new po(); + e.offsets = n; + let a = new Set(), + s = z2(e.tailwindConfig, e, { variantList: t, variantMap: i, offsets: n, classList: a }); + for (let f of r) + if (Array.isArray(f)) for (let d of f) d(s); + else f?.(s); + n.recordVariants(t, (f) => i.get(f).length); + for (let [f, d] of i.entries()) + e.variantMap.set( + f, + d.map((p, m) => [n.forVariant(f, m), p]) + ); + let o = (e.tailwindConfig.safelist ?? []).filter(Boolean); + if (o.length > 0) { + let f = []; + for (let d of o) { + if (typeof d == "string") { + e.changedContent.push({ content: d, extension: "html" }); + continue; + } + if (d instanceof RegExp) { + F.warn("root-regex", [ + "Regular expressions in `safelist` work differently in Tailwind CSS v3.0.", + "Update your `safelist` configuration to eliminate this warning.", + "https://tailwindcss.com/docs/content-configuration#safelisting-classes", + ]); + continue; + } + f.push(d); + } + if (f.length > 0) { + let d = new Map(), + p = e.tailwindConfig.prefix.length, + m = f.some((b) => b.pattern.source.includes("!")); + for (let b of a) { + let x = Array.isArray(b) + ? (() => { + let [y, w] = b, + S = Object.keys(w?.values ?? {}).map((_) => Kr(y, _)); + return ( + w?.supportsNegativeValues && + ((S = [...S, ...S.map((_) => "-" + _)]), + (S = [...S, ...S.map((_) => _.slice(0, p) + "-" + _.slice(p))])), + w.types.some(({ type: _ }) => _ === "color") && + (S = [ + ...S, + ...S.flatMap((_) => + Object.keys(e.tailwindConfig.theme.opacity).map((E) => `${_}/${E}`) + ), + ]), + m && w?.respectImportant && (S = [...S, ...S.map((_) => "!" + _)]), + S + ); + })() + : [b]; + for (let y of x) + for (let { pattern: w, variants: k = [] } of f) + if (((w.lastIndex = 0), d.has(w) || d.set(w, 0), !!w.test(y))) { + (d.set(w, d.get(w) + 1), e.changedContent.push({ content: y, extension: "html" })); + for (let S of k) + e.changedContent.push({ + content: S + e.tailwindConfig.separator + y, + extension: "html", + }); + } + } + for (let [b, x] of d.entries()) + x === 0 && + F.warn([ + `The safelist pattern \`${b}\` doesn't match any Tailwind CSS classes.`, + "Fix this pattern or remove it from your `safelist` configuration.", + "https://tailwindcss.com/docs/content-configuration#safelisting-classes", + ]); + } + } + let u = [].concat(e.tailwindConfig.darkMode ?? "media")[1] ?? "dark", + c = [yo(e, u), yo(e, "group"), yo(e, "peer")]; + ((e.getClassOrder = function (d) { + let p = [...d].sort((y, w) => (y === w ? 0 : y < w ? -1 : 1)), + m = new Map(p.map((y) => [y, null])), + b = _n(new Set(p), e, !0); + b = e.offsets.sort(b); + let x = BigInt(c.length); + for (let [, y] of b) { + let w = y.raws.tailwind.candidate; + m.set(w, m.get(w) ?? x++); + } + return d.map((y) => { + let w = m.get(y) ?? null, + k = c.indexOf(y); + return (w === null && k !== -1 && (w = BigInt(k)), [y, w]); + }); + }), + (e.getClassList = function (d = {}) { + let p = []; + for (let m of a) + if (Array.isArray(m)) { + let [b, x] = m, + y = [], + w = Object.keys(x?.modifiers ?? {}); + x?.types?.some(({ type: _ }) => _ === "color") && + w.push(...Object.keys(e.tailwindConfig.theme.opacity ?? {})); + let k = { modifiers: w }, + S = d.includeMetadata && w.length > 0; + for (let [_, E] of Object.entries(x?.values ?? {})) { + if (E == null) continue; + let I = Kr(b, _); + if ((p.push(S ? [I, k] : I), x?.supportsNegativeValues && Ke(E))) { + let q = Kr(b, `-${_}`); + y.push(S ? [q, k] : q); + } + } + p.push(...y); + } else p.push(m); + return p; + }), + (e.getVariants = function () { + let d = Math.random().toString(36).substring(7).toUpperCase(), + p = []; + for (let [m, b] of e.variantOptions.entries()) + b.variantInfo !== go.Base && + p.push({ + name: m, + isArbitrary: b.type === Symbol.for("MATCH_VARIANT"), + values: Object.keys(b.values ?? {}), + hasDash: m !== "@", + selectors({ modifier: x, value: y } = {}) { + let w = `TAILWINDPLACEHOLDER${d}`, + k = j.rule({ selector: `.${w}` }), + S = j.root({ nodes: [k.clone()] }), + _ = S.toString(), + E = (e.variantMap.get(m) ?? []).flatMap(([oe, he]) => he), + I = []; + for (let oe of E) { + let he = [], + ui = { + args: { modifier: x, value: b.values?.[y] ?? y }, + separator: e.tailwindConfig.separator, + modifySelectors(Ce) { + return ( + S.each((ts) => { + ts.type === "rule" && + (ts.selectors = ts.selectors.map((mu) => + Ce({ + get className() { + return lo(mu); + }, + selector: mu, + }) + )); + }), + S + ); + }, + format(Ce) { + he.push(Ce); + }, + wrap(Ce) { + he.push(`@${Ce.name} ${Ce.params} { & }`); + }, + container: S, + }, + fi = oe(ui); + if ((he.length > 0 && I.push(he), Array.isArray(fi))) + for (let Ce of fi) ((he = []), Ce(ui), I.push(he)); + } + let q = [], + R = S.toString(); + _ !== R && + (S.walkRules((oe) => { + let he = oe.selector, + ui = (0, ho.default)((fi) => { + fi.walkClasses((Ce) => { + Ce.value = `${m}${e.tailwindConfig.separator}${Ce.value}`; + }); + }).processSync(he); + q.push(he.replace(ui, "&").replace(w, "&")); + }), + S.walkAtRules((oe) => { + q.push(`@${oe.name} (${oe.params}) { & }`); + })); + let J = !(y in (b.values ?? {})), + ue = b[Zr] ?? {}, + de = (() => !(J || ue.respectPrefix === !1))(); + ((I = I.map((oe) => oe.map((he) => ({ format: he, respectPrefix: de })))), + (q = q.map((oe) => ({ format: oe, respectPrefix: de })))); + let De = { candidate: w, context: e }, + ee = I.map((oe) => + kn(`.${w}`, Vt(oe, De), De).replace(`.${w}`, "&").replace("{ & }", "").trim() + ); + return (q.length > 0 && ee.push(Vt(q, De).toString().replace(`.${w}`, "&")), ee); + }, + }); + return p; + })); + } + function Qd(r, e) { + !r.classCache.has(e) || + (r.notClassCache.add(e), + r.classCache.delete(e), + r.applyClassCache.delete(e), + r.candidateRuleMap.delete(e), + r.candidateRuleCache.delete(e), + (r.stylesheetCache = null)); + } + function W2(r, e) { + let t = e.raws.tailwind.candidate; + if (!!t) { + for (let i of r.ruleCache) i[1].raws.tailwind.candidate === t && r.ruleCache.delete(i); + Qd(r, t); + } + } + function bo(r, e = [], t = j.root()) { + let i = { + disposables: [], + ruleCache: new Set(), + candidateRuleCache: new Map(), + classCache: new Map(), + applyClassCache: new Map(), + notClassCache: new Set(r.blocklist ?? []), + postCssNodeCache: new Map(), + candidateRuleMap: new Map(), + tailwindConfig: r, + changedContent: e, + variantMap: new Map(), + stylesheetCache: null, + variantOptions: new Map(), + markInvalidUtilityCandidate: (a) => Qd(i, a), + markInvalidUtilityNode: (a) => W2(i, a), + }, + n = V2(i, t); + return (U2(n, i), i); + } + function Jd(r, e, t, i, n, a) { + let s = e.opts.from, + o = i !== null; + Pe.DEBUG && console.log("Source path:", s); + let u; + if (o && Ut.has(s)) u = Ut.get(s); + else if (ii.has(n)) { + let p = ii.get(n); + (ut.get(p).add(s), Ut.set(s, p), (u = p)); + } + let c = Fd(s, r); + if (u) { + let [p, m] = Hd([...a], Dn(u)); + if (!p && !c) return [u, !1, m]; + } + if (Ut.has(s)) { + let p = Ut.get(s); + if (ut.has(p) && (ut.get(p).delete(s), ut.get(p).size === 0)) { + ut.delete(p); + for (let [m, b] of ii) b === p && ii.delete(m); + for (let m of p.disposables.splice(0)) m(p); + } + } + Pe.DEBUG && console.log("Setting up new context..."); + let f = bo(t, [], r); + Object.assign(f, { userConfigPath: i }); + let [, d] = Hd([...a], Dn(f)); + return (ii.set(n, f), Ut.set(s, f), ut.has(f) || ut.set(f, new Set()), ut.get(f).add(s), [f, !0, d]); + } + var Ud, + ho, + Zr, + mo, + go, + wo, + Ut, + ii, + ut, + ei = C(() => { + l(); + ze(); + Cs(); + st(); + ((Ud = X(Gs())), (ho = X(Me()))); + Jr(); + Qa(); + dn(); + At(); + $t(); + Xa(); + hr(); + Cd(); + lt(); + lt(); + gi(); + Oe(); + di(); + eo(); + On(); + Ld(); + Vd(); + je(); + so(); + ((Zr = Symbol()), + (mo = { AddVariant: Symbol.for("ADD_VARIANT"), MatchVariant: Symbol.for("MATCH_VARIANT") }), + (go = { Base: 1 << 0, Dynamic: 1 << 1 })); + wo = new WeakMap(); + ((Ut = Ad), (ii = _d), (ut = vn)); + }); + function vo(r) { + return r.ignore + ? [] + : r.glob + ? h.env.ROLLUP_WATCH === "true" + ? [{ type: "dependency", file: r.base }] + : [{ type: "dir-dependency", dir: r.base, glob: r.glob }] + : [{ type: "dependency", file: r.base }]; + } + var Xd = C(() => { + l(); + }); + function Kd(r, e) { + return { handler: r, config: e }; + } + var Zd, + eh = C(() => { + l(); + Kd.withOptions = function (r, e = () => ({})) { + let t = function (i) { + return { __options: i, handler: r(i), config: e(i) }; + }; + return ((t.__isOptionsFunction = !0), (t.__pluginFunction = r), (t.__configFunction = e), t); + }; + Zd = Kd; + }); + var In = {}; + Ae(In, { default: () => G2 }); + var G2, + qn = C(() => { + l(); + eh(); + G2 = Zd; + }); + var rh = v((M6, th) => { + l(); + var H2 = (qn(), In).default, + Y2 = { overflow: "hidden", display: "-webkit-box", "-webkit-box-orient": "vertical" }, + Q2 = H2( + function ({ matchUtilities: r, addUtilities: e, theme: t, variants: i }) { + let n = t("lineClamp"); + (r({ "line-clamp": (a) => ({ ...Y2, "-webkit-line-clamp": `${a}` }) }, { values: n }), + e([{ ".line-clamp-none": { "-webkit-line-clamp": "unset" } }], i("lineClamp"))); + }, + { + theme: { lineClamp: { 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6" } }, + variants: { lineClamp: ["responsive"] }, + } + ); + th.exports = Q2; + }); + function xo(r) { + r.content.files.length === 0 && + F.warn("content-problems", [ + "The `content` option in your Tailwind CSS configuration is missing or empty.", + "Configure your content sources or your generated CSS will be missing styles.", + "https://tailwindcss.com/docs/content-configuration", + ]); + try { + let e = rh(); + r.plugins.includes(e) && + (F.warn("line-clamp-in-core", [ + "As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default.", + "Remove it from the `plugins` array in your configuration to eliminate this warning.", + ]), + (r.plugins = r.plugins.filter((t) => t !== e))); + } catch {} + return r; + } + var ih = C(() => { + l(); + Oe(); + }); + var nh, + sh = C(() => { + l(); + nh = () => !1; + }); + var Rn, + ah = C(() => { + l(); + Rn = { + sync: (r) => [].concat(r), + generateTasks: (r) => [ + { dynamic: !1, base: ".", negative: [], positive: [].concat(r), patterns: [].concat(r) }, + ], + escapePath: (r) => r, + }; + }); + var ko, + oh = C(() => { + l(); + ko = (r) => r; + }); + var lh, + uh = C(() => { + l(); + lh = () => ""; + }); + function fh(r) { + let e = r, + t = lh(r); + return ( + t !== "." && ((e = r.substr(t.length)), e.charAt(0) === "/" && (e = e.substr(1))), + e.substr(0, 2) === "./" && (e = e.substr(2)), + e.charAt(0) === "/" && (e = e.substr(1)), + { base: t, glob: e } + ); + } + var ch = C(() => { + l(); + uh(); + }); + function ph(r, e) { + let t = e.content.files; + ((t = t.filter((o) => typeof o == "string")), (t = t.map(ko))); + let i = Rn.generateTasks(t), + n = [], + a = []; + for (let o of i) (n.push(...o.positive.map((u) => dh(u, !1))), a.push(...o.negative.map((u) => dh(u, !0)))); + let s = [...n, ...a]; + return ((s = X2(r, s)), (s = s.flatMap(K2)), (s = s.map(J2)), s); + } + function dh(r, e) { + let t = { original: r, base: r, ignore: e, pattern: r, glob: null }; + return (nh(r) && Object.assign(t, fh(r)), t); + } + function J2(r) { + let e = ko(r.base); + return ( + (e = Rn.escapePath(e)), + (r.pattern = r.glob ? `${e}/${r.glob}` : e), + (r.pattern = r.ignore ? `!${r.pattern}` : r.pattern), + r + ); + } + function X2(r, e) { + let t = []; + return ( + r.userConfigPath && r.tailwindConfig.content.relative && (t = [Z.dirname(r.userConfigPath)]), + e.map((i) => ((i.base = Z.resolve(...t, i.base)), i)) + ); + } + function K2(r) { + let e = [r]; + try { + let t = te.realpathSync(r.base); + t !== r.base && e.push({ ...r, base: t }); + } catch {} + return e; + } + function hh(r, e, t) { + let i = r.tailwindConfig.content.files + .filter((s) => typeof s.raw == "string") + .map(({ raw: s, extension: o = "html" }) => ({ content: s, extension: o })), + [n, a] = Z2(e, t); + for (let s of n) { + let o = Z.extname(s).slice(1); + i.push({ file: s, extension: o }); + } + return [i, a]; + } + function Z2(r, e) { + let t = r.map((s) => s.pattern), + i = new Map(), + n = new Set(); + Pe.DEBUG && console.time("Finding changed files"); + let a = Rn.sync(t, { absolute: !0 }); + for (let s of a) { + let o = e.get(s) || -1 / 0, + u = te.statSync(s).mtimeMs; + u > o && (n.add(s), i.set(s, u)); + } + return (Pe.DEBUG && console.timeEnd("Finding changed files"), [n, i]); + } + var mh = C(() => { + l(); + ze(); + bt(); + sh(); + ah(); + oh(); + ch(); + lt(); + }); + function gh() {} + var yh = C(() => { + l(); + }); + function iC(r, e) { + for (let t of e) { + let i = `${r}${t}`; + if (te.existsSync(i) && te.statSync(i).isFile()) return i; + } + for (let t of e) { + let i = `${r}/index${t}`; + if (te.existsSync(i)) return i; + } + return null; + } + function* wh(r, e, t, i = Z.extname(r)) { + let n = iC(Z.resolve(e, r), eC.includes(i) ? tC : rC); + if (n === null || t.has(n)) return; + (t.add(n), yield n, (e = Z.dirname(n)), (i = Z.extname(n))); + let a = te.readFileSync(n, "utf-8"); + for (let s of [ + ...a.matchAll(/import[\s\S]*?['"](.{3,}?)['"]/gi), + ...a.matchAll(/import[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi), + ...a.matchAll(/require\(['"`](.+)['"`]\)/gi), + ]) + !s[1].startsWith(".") || (yield* wh(s[1], e, t, i)); + } + function So(r) { + return r === null ? new Set() : new Set(wh(r, Z.dirname(r), new Set())); + } + var eC, + tC, + rC, + bh = C(() => { + l(); + ze(); + bt(); + ((eC = [".js", ".cjs", ".mjs"]), + (tC = ["", ".js", ".cjs", ".mjs", ".ts", ".cts", ".mts", ".jsx", ".tsx"]), + (rC = ["", ".ts", ".cts", ".mts", ".tsx", ".js", ".cjs", ".mjs", ".jsx"])); + }); + function nC(r, e) { + if (Co.has(r)) return Co.get(r); + let t = ph(r, e); + return Co.set(r, t).get(r); + } + function sC(r) { + let e = ks(r); + if (e !== null) { + let [i, n, a, s] = xh.get(e) || [], + o = So(e), + u = !1, + c = new Map(); + for (let p of o) { + let m = te.statSync(p).mtimeMs; + (c.set(p, m), (!s || !s.has(p) || m > s.get(p)) && (u = !0)); + } + if (!u) return [i, e, n, a]; + for (let p of o) delete yu.cache[p]; + let f = xo(gr(gh(e))), + d = pi(f); + return (xh.set(e, [f, d, o, c]), [f, e, d, o]); + } + let t = gr(r?.config ?? r ?? {}); + return ((t = xo(t)), [t, null, pi(t), []]); + } + function Ao(r) { + return ({ tailwindDirectives: e, registerDependency: t }) => + (i, n) => { + let [a, s, o, u] = sC(r), + c = new Set(u); + if (e.size > 0) { + c.add(n.opts.from); + for (let b of n.messages) b.type === "dependency" && c.add(b.file); + } + let [f, , d] = Jd(i, n, a, s, o, c), + p = Dn(f), + m = nC(f, a); + if (e.size > 0) { + for (let y of m) for (let w of vo(y)) t(w); + let [b, x] = hh(f, m, p); + for (let y of b) f.changedContent.push(y); + for (let [y, w] of x.entries()) d.set(y, w); + } + for (let b of u) t({ type: "dependency", file: b }); + for (let [b, x] of d.entries()) p.set(b, x); + return f; + }; + } + var vh, + xh, + Co, + kh = C(() => { + l(); + ze(); + vh = X(rs()); + ku(); + xs(); + cf(); + ei(); + Xd(); + ih(); + mh(); + yh(); + bh(); + ((xh = new vh.default({ maxSize: 100 })), (Co = new WeakMap())); + }); + function _o(r) { + let e = new Set(), + t = new Set(), + i = new Set(); + if ( + (r.walkAtRules((n) => { + (n.name === "apply" && i.add(n), + n.name === "import" && + (n.params === '"tailwindcss/base"' || n.params === "'tailwindcss/base'" + ? ((n.name = "tailwind"), (n.params = "base")) + : n.params === '"tailwindcss/components"' || n.params === "'tailwindcss/components'" + ? ((n.name = "tailwind"), (n.params = "components")) + : n.params === '"tailwindcss/utilities"' || n.params === "'tailwindcss/utilities'" + ? ((n.name = "tailwind"), (n.params = "utilities")) + : (n.params === '"tailwindcss/screens"' || + n.params === "'tailwindcss/screens'" || + n.params === '"tailwindcss/variants"' || + n.params === "'tailwindcss/variants'") && + ((n.name = "tailwind"), (n.params = "variants"))), + n.name === "tailwind" && (n.params === "screens" && (n.params = "variants"), e.add(n.params)), + ["layer", "responsive", "variants"].includes(n.name) && + (["responsive", "variants"].includes(n.name) && + F.warn(`${n.name}-at-rule-deprecated`, [ + `The \`@${n.name}\` directive has been deprecated in Tailwind CSS v3.0.`, + "Use `@layer utilities` or `@layer components` instead.", + "https://tailwindcss.com/docs/upgrade-guide#replace-variants-with-layer", + ]), + t.add(n))); + }), + !e.has("base") || !e.has("components") || !e.has("utilities")) + ) { + for (let n of t) + if (n.name === "layer" && ["base", "components", "utilities"].includes(n.params)) { + if (!e.has(n.params)) + throw n.error( + `\`@layer ${n.params}\` is used but no matching \`@tailwind ${n.params}\` directive is present.` + ); + } else if (n.name === "responsive") { + if (!e.has("utilities")) + throw n.error("`@responsive` is used but `@tailwind utilities` is missing."); + } else if (n.name === "variants" && !e.has("utilities")) + throw n.error("`@variants` is used but `@tailwind utilities` is missing."); + } + return { tailwindDirectives: e, applyDirectives: i }; + } + var Sh = C(() => { + l(); + Oe(); + }); + function St(r, e = void 0, t = void 0) { + return r.map((i) => { + let n = i.clone(); + return ( + t !== void 0 && (n.raws.tailwind = { ...n.raws.tailwind, ...t }), + e !== void 0 && + Ch(n, (a) => { + if (a.raws.tailwind?.preserveSource === !0 && a.source) return !1; + a.source = e; + }), + n + ); + }); + } + function Ch(r, e) { + e(r) !== !1 && r.each?.((t) => Ch(t, e)); + } + var Ah = C(() => { + l(); + }); + function Oo(r) { + return ((r = Array.isArray(r) ? r : [r]), (r = r.map((e) => (e instanceof RegExp ? e.source : e))), r.join("")); + } + function ye(r) { + return new RegExp(Oo(r), "g"); + } + function ft(r) { + return `(?:${r.map(Oo).join("|")})`; + } + function Eo(r) { + return `(?:${Oo(r)})?`; + } + function Oh(r) { + return r && aC.test(r) ? r.replace(_h, "\\$&") : r || ""; + } + var _h, + aC, + Eh = C(() => { + l(); + ((_h = /[\\^$.*+?()[\]{}|]/g), (aC = RegExp(_h.source))); + }); + function Th(r) { + let e = Array.from(oC(r)); + return (t) => { + let i = []; + for (let n of e) for (let a of t.match(n) ?? []) i.push(fC(a)); + return i; + }; + } + function* oC(r) { + let e = r.tailwindConfig.separator, + t = r.tailwindConfig.prefix !== "" ? Eo(ye([/-?/, Oh(r.tailwindConfig.prefix)])) : "", + i = ft([ + /\[[^\s:'"`]+:[^\s\[\]]+\]/, + /\[[^\s:'"`\]]+:[^\s]+?\[[^\s]+\][^\s]+?\]/, + ye([ + ft([/-?(?:\w+)/, /@(?:\w+)/]), + Eo( + ft([ + ye([ + ft([ + /-(?:\w+-)*\['[^\s]+'\]/, + /-(?:\w+-)*\["[^\s]+"\]/, + /-(?:\w+-)*\[`[^\s]+`\]/, + /-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s:\[\]]+\]/, + ]), + /(?![{([]])/, + /(?:\/[^\s'"`\\><$]*)?/, + ]), + ye([ + ft([ + /-(?:\w+-)*\['[^\s]+'\]/, + /-(?:\w+-)*\["[^\s]+"\]/, + /-(?:\w+-)*\[`[^\s]+`\]/, + /-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s\[\]]+\]/, + ]), + /(?![{([]])/, + /(?:\/[^\s'"`\\$]*)?/, + ]), + /[-\/][^\s'"`\\$={><]*/, + ]) + ), + ]), + ]), + n = [ + ft([ + ye([/@\[[^\s"'`]+\](\/[^\s"'`]+)?/, e]), + ye([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/[\w_-]+/, e]), + ye([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, e]), + ye([/[^\s"'`\[\\]+/, e]), + ]), + ft([ + ye([/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/[\w_-]+/, e]), + ye([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, e]), + ye([/[^\s`\[\\]+/, e]), + ]), + ]; + for (let a of n) yield ye(["((?=((", a, ")+))\\2)?", /!?/, t, i]); + yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g; + } + function fC(r) { + if (!r.includes("-[")) return r; + let e = 0, + t = [], + i = r.matchAll(lC); + i = Array.from(i).flatMap((n) => { + let [, ...a] = n; + return a.map((s, o) => Object.assign([], n, { index: n.index + o, 0: s })); + }); + for (let n of i) { + let a = n[0], + s = t[t.length - 1]; + if ((a === s ? t.pop() : (a === "'" || a === '"' || a === "`") && t.push(a), !s)) { + if (a === "[") { + e++; + continue; + } else if (a === "]") { + e--; + continue; + } + if (e < 0) return r.substring(0, n.index - 1); + if (e === 0 && !uC.test(a)) return r.substring(0, n.index); + } + } + return r; + } + var lC, + uC, + Ph = C(() => { + l(); + Eh(); + ((lC = /([\[\]'"`])([^\[\]'"`])?/g), (uC = /[^"'`\s<>\]]+/)); + }); + function cC(r, e) { + let t = r.tailwindConfig.content.extract; + return t[e] || t.DEFAULT || Ih[e] || Ih.DEFAULT(r); + } + function pC(r, e) { + let t = r.content.transform; + return t[e] || t.DEFAULT || qh[e] || qh.DEFAULT; + } + function dC(r, e, t, i) { + ni.has(e) || ni.set(e, new Dh.default({ maxSize: 25e3 })); + for (let n of r.split(` +`)) + if (((n = n.trim()), !i.has(n))) + if ((i.add(n), ni.get(e).has(n))) for (let a of ni.get(e).get(n)) t.add(a); + else { + let a = e(n).filter((o) => o !== "!*"), + s = new Set(a); + for (let o of s) t.add(o); + ni.get(e).set(n, s); + } + } + function hC(r, e) { + let t = e.offsets.sort(r), + i = { + base: new Set(), + defaults: new Set(), + components: new Set(), + utilities: new Set(), + variants: new Set(), + }; + for (let [n, a] of t) i[n.layer].add(a); + return i; + } + function To(r) { + return async (e) => { + let t = { base: null, components: null, utilities: null, variants: null }; + if ( + (e.walkAtRules((y) => { + y.name === "tailwind" && Object.keys(t).includes(y.params) && (t[y.params] = y); + }), + Object.values(t).every((y) => y === null)) + ) + return e; + let i = new Set([...(r.candidates ?? []), He]), + n = new Set(); + Ye.DEBUG && console.time("Reading changed files"); + let a = []; + for (let y of r.changedContent) { + let w = pC(r.tailwindConfig, y.extension), + k = cC(r, y.extension); + a.push([y, { transformer: w, extractor: k }]); + } + let s = 500; + for (let y = 0; y < a.length; y += s) { + let w = a.slice(y, y + s); + await Promise.all( + w.map(async ([{ file: k, content: S }, { transformer: _, extractor: E }]) => { + ((S = k ? await te.promises.readFile(k, "utf8") : S), dC(_(S), E, i, n)); + }) + ); + } + Ye.DEBUG && console.timeEnd("Reading changed files"); + let o = r.classCache.size; + (Ye.DEBUG && console.time("Generate rules"), Ye.DEBUG && console.time("Sorting candidates")); + let u = new Set([...i].sort((y, w) => (y === w ? 0 : y < w ? -1 : 1))); + (Ye.DEBUG && console.timeEnd("Sorting candidates"), + _n(u, r), + Ye.DEBUG && console.timeEnd("Generate rules"), + Ye.DEBUG && console.time("Build stylesheet"), + (r.stylesheetCache === null || r.classCache.size !== o) && + (r.stylesheetCache = hC([...r.ruleCache], r)), + Ye.DEBUG && console.timeEnd("Build stylesheet")); + let { defaults: c, base: f, components: d, utilities: p, variants: m } = r.stylesheetCache; + (t.base && (t.base.before(St([...f, ...c], t.base.source, { layer: "base" })), t.base.remove()), + t.components && + (t.components.before(St([...d], t.components.source, { layer: "components" })), + t.components.remove()), + t.utilities && + (t.utilities.before(St([...p], t.utilities.source, { layer: "utilities" })), t.utilities.remove())); + let b = Array.from(m).filter((y) => { + let w = y.raws.tailwind?.parentLayer; + return w === "components" ? t.components !== null : w === "utilities" ? t.utilities !== null : !0; + }); + (t.variants + ? (t.variants.before(St(b, t.variants.source, { layer: "variants" })), t.variants.remove()) + : b.length > 0 && e.append(St(b, e.source, { layer: "variants" })), + (e.source.end = e.source.end ?? e.source.start)); + let x = b.some((y) => y.raws.tailwind?.parentLayer === "utilities"); + (t.utilities && + p.size === 0 && + !x && + F.warn("content-problems", [ + "No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.", + "https://tailwindcss.com/docs/content-configuration", + ]), + Ye.DEBUG && (console.log("Potential classes: ", i.size), console.log("Active contexts: ", vn.size)), + (r.changedContent = []), + e.walkAtRules("layer", (y) => { + Object.keys(t).includes(y.params) && y.remove(); + })); + }; + } + var Dh, + Ye, + Ih, + qh, + ni, + Rh = C(() => { + l(); + ze(); + Dh = X(rs()); + lt(); + On(); + Oe(); + Ah(); + Ph(); + ((Ye = Pe), + (Ih = { DEFAULT: Th }), + (qh = { DEFAULT: (r) => r, svelte: (r) => r.replace(/(?:^|\s)class:/g, " ") })); + ni = new WeakMap(); + }); + function Bn(r) { + let e = new Map(); + j.root({ nodes: [r.clone()] }).walkRules((a) => { + (0, Mn.default)((s) => { + s.walkClasses((o) => { + let u = o.parent.toString(), + c = e.get(u); + (c || e.set(u, (c = new Set())), c.add(o.value)); + }); + }).processSync(a.selector); + }); + let i = Array.from(e.values(), (a) => Array.from(a)), + n = i.flat(); + return Object.assign(n, { groups: i }); + } + function Po(r) { + return mC.astSync(r); + } + function Mh(r, e) { + let t = new Set(); + for (let i of r) t.add(i.split(e).pop()); + return Array.from(t); + } + function Bh(r, e) { + let t = r.tailwindConfig.prefix; + return typeof t == "function" ? t(e) : t + e; + } + function* Fh(r) { + for (yield r; r.parent; ) (yield r.parent, (r = r.parent)); + } + function gC(r, e = {}) { + let t = r.nodes; + r.nodes = []; + let i = r.clone(e); + return ((r.nodes = t), i); + } + function yC(r) { + for (let e of Fh(r)) + if (r !== e) { + if (e.type === "root") break; + r = gC(e, { nodes: [r] }); + } + return r; + } + function wC(r, e) { + let t = new Map(); + return ( + r.walkRules((i) => { + for (let s of Fh(i)) if (s.raws.tailwind?.layer !== void 0) return; + let n = yC(i), + a = e.offsets.create("user"); + for (let s of Bn(i)) { + let o = t.get(s) || []; + (t.set(s, o), o.push([{ layer: "user", sort: a, important: !1 }, n])); + } + }), + t + ); + } + function bC(r, e) { + for (let t of r) { + if (e.notClassCache.has(t) || e.applyClassCache.has(t)) continue; + if (e.classCache.has(t)) { + e.applyClassCache.set( + t, + e.classCache.get(t).map(([n, a]) => [n, a.clone()]) + ); + continue; + } + let i = Array.from(fo(t, e)); + if (i.length === 0) { + e.notClassCache.add(t); + continue; + } + e.applyClassCache.set(t, i); + } + return e.applyClassCache; + } + function vC(r) { + let e = null; + return { get: (t) => ((e = e || r()), e.get(t)), has: (t) => ((e = e || r()), e.has(t)) }; + } + function xC(r) { + return { get: (e) => r.flatMap((t) => t.get(e) || []), has: (e) => r.some((t) => t.has(e)) }; + } + function Lh(r) { + let e = r.split(/[\s\t\n]+/g); + return e[e.length - 1] === "!important" ? [e.slice(0, -1), !0] : [e, !1]; + } + function Nh(r, e, t) { + let i = new Set(), + n = []; + if ( + (r.walkAtRules("apply", (u) => { + let [c] = Lh(u.params); + for (let f of c) i.add(f); + n.push(u); + }), + n.length === 0) + ) + return; + let a = xC([t, bC(i, e)]); + function s(u, c, f) { + let d = Po(u), + p = Po(c), + b = Po(`.${ce(f)}`).nodes[0].nodes[0]; + return ( + d.each((x) => { + let y = new Set(); + p.each((w) => { + let k = !1; + ((w = w.clone()), + w.walkClasses((S) => { + S.value === b.value && + (k || (S.replaceWith(...x.nodes.map((_) => _.clone())), y.add(w), (k = !0))); + })); + }); + for (let w of y) { + let k = [[]]; + for (let S of w.nodes) + S.type === "combinator" ? (k.push(S), k.push([])) : k[k.length - 1].push(S); + w.nodes = []; + for (let S of k) + (Array.isArray(S) && + S.sort((_, E) => + _.type === "tag" && E.type === "class" + ? -1 + : _.type === "class" && E.type === "tag" + ? 1 + : _.type === "class" && E.type === "pseudo" && E.value.startsWith("::") + ? -1 + : _.type === "pseudo" && _.value.startsWith("::") && E.type === "class" + ? 1 + : 0 + ), + (w.nodes = w.nodes.concat(S))); + } + x.replaceWith(...y); + }), + d.toString() + ); + } + let o = new Map(); + for (let u of n) { + let [c] = o.get(u.parent) || [[], u.source]; + o.set(u.parent, [c, u.source]); + let [f, d] = Lh(u.params); + if (u.parent.type === "atrule") { + if (u.parent.name === "screen") { + let p = u.parent.params; + throw u.error( + `@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${f.map((m) => `${p}:${m}`).join(" ")} instead.` + ); + } + throw u.error( + `@apply is not supported within nested at-rules like @${u.parent.name}. You can fix this by un-nesting @${u.parent.name}.` + ); + } + for (let p of f) { + if ([Bh(e, "group"), Bh(e, "peer")].includes(p)) + throw u.error(`@apply should not be used with the '${p}' utility`); + if (!a.has(p)) + throw u.error( + `The \`${p}\` class does not exist. If \`${p}\` is a custom class, make sure it is defined within a \`@layer\` directive.` + ); + let m = a.get(p); + for (let [, b] of m) + b.type !== "atrule" && + b.walkRules(() => { + throw u.error( + [ + `The \`${p}\` class cannot be used with \`@apply\` because \`@apply\` does not currently support nested CSS.`, + "Rewrite the selector without nesting or configure the `tailwindcss/nesting` plugin:", + "https://tailwindcss.com/docs/using-with-preprocessors#nesting", + ].join(` +`) + ); + }); + c.push([p, d, m]); + } + } + for (let [u, [c, f]] of o) { + let d = []; + for (let [m, b, x] of c) { + let y = [m, ...Mh([m], e.tailwindConfig.separator)]; + for (let [w, k] of x) { + let S = Bn(u), + _ = Bn(k); + if ( + ((_ = _.groups.filter((R) => R.some((J) => y.includes(J))).flat()), + (_ = _.concat(Mh(_, e.tailwindConfig.separator))), + S.some((R) => _.includes(R))) + ) + throw k.error( + `You cannot \`@apply\` the \`${m}\` utility here because it creates a circular dependency.` + ); + let I = j.root({ nodes: [k.clone()] }); + (I.walk((R) => { + R.source = f; + }), + (k.type !== "atrule" || (k.type === "atrule" && k.name !== "keyframes")) && + I.walkRules((R) => { + if (!Bn(R).some((ee) => ee === m)) { + R.remove(); + return; + } + let J = + typeof e.tailwindConfig.important == "string" + ? e.tailwindConfig.important + : null, + de = + u.raws.tailwind !== void 0 && J && u.selector.indexOf(J) === 0 + ? u.selector.slice(J.length) + : u.selector; + (de === "" && (de = u.selector), + (R.selector = s(de, R.selector, m)), + J && de !== u.selector && (R.selector = Sn(R.selector, J)), + R.walkDecls((ee) => { + ee.important = w.important || b; + })); + let De = (0, Mn.default)().astSync(R.selector); + (De.each((ee) => jt(ee)), (R.selector = De.toString())); + }), + !!I.nodes[0] && d.push([w.sort, I.nodes[0]])); + } + } + let p = e.offsets.sort(d).map((m) => m[1]); + u.after(p); + } + for (let u of n) u.parent.nodes.length > 1 ? u.remove() : u.parent.remove(); + Nh(r, e, t); + } + function Do(r) { + return (e) => { + let t = vC(() => wC(e, r)); + Nh(e, r, t); + }; + } + var Mn, + mC, + $h = C(() => { + l(); + st(); + Mn = X(Me()); + On(); + $t(); + oo(); + xn(); + mC = (0, Mn.default)(); + }); + var zh = v((I4, Fn) => { + l(); + (function () { + "use strict"; + function r(i, n, a) { + if (!i) return null; + r.caseSensitive || (i = i.toLowerCase()); + var s = r.threshold === null ? null : r.threshold * i.length, + o = r.thresholdAbsolute, + u; + s !== null && o !== null + ? (u = Math.min(s, o)) + : s !== null + ? (u = s) + : o !== null + ? (u = o) + : (u = null); + var c, + f, + d, + p, + m, + b = n.length; + for (m = 0; m < b; m++) + if ( + ((f = n[m]), + a && (f = f[a]), + !!f && + (r.caseSensitive ? (d = f) : (d = f.toLowerCase()), + (p = t(i, d, u)), + (u === null || p < u) && + ((u = p), a && r.returnWinningObject ? (c = n[m]) : (c = f), r.returnFirstMatch))) + ) + return c; + return c || r.nullResultValue; + } + ((r.threshold = 0.4), + (r.thresholdAbsolute = 20), + (r.caseSensitive = !1), + (r.nullResultValue = null), + (r.returnWinningObject = null), + (r.returnFirstMatch = !1), + typeof Fn != "undefined" && Fn.exports ? (Fn.exports = r) : (window.didYouMean = r)); + var e = Math.pow(2, 32) - 1; + function t(i, n, a) { + a = a || a === 0 ? a : e; + var s = i.length, + o = n.length; + if (s === 0) return Math.min(a + 1, o); + if (o === 0) return Math.min(a + 1, s); + if (Math.abs(s - o) > a) return a + 1; + var u = [], + c, + f, + d, + p, + m; + for (c = 0; c <= o; c++) u[c] = [c]; + for (f = 0; f <= s; f++) u[0][f] = f; + for (c = 1; c <= o; c++) { + for (d = e, p = 1, c > a && (p = c - a), m = o + 1, m > a + c && (m = a + c), f = 1; f <= s; f++) + (f < p || f > m + ? (u[c][f] = a + 1) + : n.charAt(c - 1) === i.charAt(f - 1) + ? (u[c][f] = u[c - 1][f - 1]) + : (u[c][f] = Math.min(u[c - 1][f - 1] + 1, Math.min(u[c][f - 1] + 1, u[c - 1][f] + 1))), + u[c][f] < d && (d = u[c][f])); + if (d > a) return a + 1; + } + return u[o][s]; + } + })(); + }); + var Vh = v((q4, jh) => { + l(); + var Io = "(".charCodeAt(0), + qo = ")".charCodeAt(0), + Ln = "'".charCodeAt(0), + Ro = '"'.charCodeAt(0), + Mo = "\\".charCodeAt(0), + Wt = "/".charCodeAt(0), + Bo = ",".charCodeAt(0), + Fo = ":".charCodeAt(0), + Nn = "*".charCodeAt(0), + kC = "u".charCodeAt(0), + SC = "U".charCodeAt(0), + CC = "+".charCodeAt(0), + AC = /^[a-f0-9?-]+$/i; + jh.exports = function (r) { + for ( + var e = [], + t = r, + i, + n, + a, + s, + o, + u, + c, + f, + d = 0, + p = t.charCodeAt(d), + m = t.length, + b = [{ nodes: e }], + x = 0, + y, + w = "", + k = "", + S = ""; + d < m; + ) + if (p <= 32) { + i = d; + do ((i += 1), (p = t.charCodeAt(i))); + while (p <= 32); + ((s = t.slice(d, i)), + (a = e[e.length - 1]), + p === qo && x + ? (S = s) + : a && a.type === "div" + ? ((a.after = s), (a.sourceEndIndex += s.length)) + : p === Bo || + p === Fo || + (p === Wt && t.charCodeAt(i + 1) !== Nn && (!y || (y && y.type === "function" && !1))) + ? (k = s) + : e.push({ type: "space", sourceIndex: d, sourceEndIndex: i, value: s }), + (d = i)); + } else if (p === Ln || p === Ro) { + ((i = d), (n = p === Ln ? "'" : '"'), (s = { type: "string", sourceIndex: d, quote: n })); + do + if (((o = !1), (i = t.indexOf(n, i + 1)), ~i)) + for (u = i; t.charCodeAt(u - 1) === Mo; ) ((u -= 1), (o = !o)); + else ((t += n), (i = t.length - 1), (s.unclosed = !0)); + while (o); + ((s.value = t.slice(d + 1, i)), + (s.sourceEndIndex = s.unclosed ? i : i + 1), + e.push(s), + (d = i + 1), + (p = t.charCodeAt(d))); + } else if (p === Wt && t.charCodeAt(d + 1) === Nn) + ((i = t.indexOf("*/", d)), + (s = { type: "comment", sourceIndex: d, sourceEndIndex: i + 2 }), + i === -1 && ((s.unclosed = !0), (i = t.length), (s.sourceEndIndex = i)), + (s.value = t.slice(d + 2, i)), + e.push(s), + (d = i + 2), + (p = t.charCodeAt(d))); + else if ((p === Wt || p === Nn) && y && y.type === "function") + ((s = t[d]), + e.push({ type: "word", sourceIndex: d - k.length, sourceEndIndex: d + s.length, value: s }), + (d += 1), + (p = t.charCodeAt(d))); + else if (p === Wt || p === Bo || p === Fo) + ((s = t[d]), + e.push({ + type: "div", + sourceIndex: d - k.length, + sourceEndIndex: d + s.length, + value: s, + before: k, + after: "", + }), + (k = ""), + (d += 1), + (p = t.charCodeAt(d))); + else if (Io === p) { + i = d; + do ((i += 1), (p = t.charCodeAt(i))); + while (p <= 32); + if ( + ((f = d), + (s = { type: "function", sourceIndex: d - w.length, value: w, before: t.slice(f + 1, i) }), + (d = i), + w === "url" && p !== Ln && p !== Ro) + ) { + i -= 1; + do + if (((o = !1), (i = t.indexOf(")", i + 1)), ~i)) + for (u = i; t.charCodeAt(u - 1) === Mo; ) ((u -= 1), (o = !o)); + else ((t += ")"), (i = t.length - 1), (s.unclosed = !0)); + while (o); + c = i; + do ((c -= 1), (p = t.charCodeAt(c))); + while (p <= 32); + (f < c + ? (d !== c + 1 + ? (s.nodes = [ + { + type: "word", + sourceIndex: d, + sourceEndIndex: c + 1, + value: t.slice(d, c + 1), + }, + ]) + : (s.nodes = []), + s.unclosed && c + 1 !== i + ? ((s.after = ""), + s.nodes.push({ + type: "space", + sourceIndex: c + 1, + sourceEndIndex: i, + value: t.slice(c + 1, i), + })) + : ((s.after = t.slice(c + 1, i)), (s.sourceEndIndex = i))) + : ((s.after = ""), (s.nodes = [])), + (d = i + 1), + (s.sourceEndIndex = s.unclosed ? i : d), + (p = t.charCodeAt(d)), + e.push(s)); + } else + ((x += 1), + (s.after = ""), + (s.sourceEndIndex = d + 1), + e.push(s), + b.push(s), + (e = s.nodes = []), + (y = s)); + w = ""; + } else if (qo === p && x) + ((d += 1), + (p = t.charCodeAt(d)), + (y.after = S), + (y.sourceEndIndex += S.length), + (S = ""), + (x -= 1), + (b[b.length - 1].sourceEndIndex = d), + b.pop(), + (y = b[x]), + (e = y.nodes)); + else { + i = d; + do (p === Mo && (i += 1), (i += 1), (p = t.charCodeAt(i))); + while ( + i < m && + !( + p <= 32 || + p === Ln || + p === Ro || + p === Bo || + p === Fo || + p === Wt || + p === Io || + (p === Nn && y && y.type === "function" && !0) || + (p === Wt && y.type === "function" && !0) || + (p === qo && x) + ) + ); + ((s = t.slice(d, i)), + Io === p + ? (w = s) + : (kC === s.charCodeAt(0) || SC === s.charCodeAt(0)) && + CC === s.charCodeAt(1) && + AC.test(s.slice(2)) + ? e.push({ type: "unicode-range", sourceIndex: d, sourceEndIndex: i, value: s }) + : e.push({ type: "word", sourceIndex: d, sourceEndIndex: i, value: s }), + (d = i)); + } + for (d = b.length - 1; d; d -= 1) ((b[d].unclosed = !0), (b[d].sourceEndIndex = t.length)); + return b[0].nodes; + }; + }); + var Wh = v((R4, Uh) => { + l(); + Uh.exports = function r(e, t, i) { + var n, a, s, o; + for (n = 0, a = e.length; n < a; n += 1) + ((s = e[n]), + i || (o = t(s, n, e)), + o !== !1 && s.type === "function" && Array.isArray(s.nodes) && r(s.nodes, t, i), + i && t(s, n, e)); + }; + }); + var Qh = v((M4, Yh) => { + l(); + function Gh(r, e) { + var t = r.type, + i = r.value, + n, + a; + return e && (a = e(r)) !== void 0 + ? a + : t === "word" || t === "space" + ? i + : t === "string" + ? ((n = r.quote || ""), n + i + (r.unclosed ? "" : n)) + : t === "comment" + ? "/*" + i + (r.unclosed ? "" : "*/") + : t === "div" + ? (r.before || "") + i + (r.after || "") + : Array.isArray(r.nodes) + ? ((n = Hh(r.nodes, e)), + t !== "function" + ? n + : i + "(" + (r.before || "") + n + (r.after || "") + (r.unclosed ? "" : ")")) + : i; + } + function Hh(r, e) { + var t, i; + if (Array.isArray(r)) { + for (t = "", i = r.length - 1; ~i; i -= 1) t = Gh(r[i], e) + t; + return t; + } + return Gh(r, e); + } + Yh.exports = Hh; + }); + var Xh = v((B4, Jh) => { + l(); + var $n = "-".charCodeAt(0), + zn = "+".charCodeAt(0), + Lo = ".".charCodeAt(0), + _C = "e".charCodeAt(0), + OC = "E".charCodeAt(0); + function EC(r) { + var e = r.charCodeAt(0), + t; + if (e === zn || e === $n) { + if (((t = r.charCodeAt(1)), t >= 48 && t <= 57)) return !0; + var i = r.charCodeAt(2); + return t === Lo && i >= 48 && i <= 57; + } + return e === Lo ? ((t = r.charCodeAt(1)), t >= 48 && t <= 57) : e >= 48 && e <= 57; + } + Jh.exports = function (r) { + var e = 0, + t = r.length, + i, + n, + a; + if (t === 0 || !EC(r)) return !1; + for ( + i = r.charCodeAt(e), (i === zn || i === $n) && e++; + e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); + ) + e += 1; + if (((i = r.charCodeAt(e)), (n = r.charCodeAt(e + 1)), i === Lo && n >= 48 && n <= 57)) + for (e += 2; e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); ) e += 1; + if ( + ((i = r.charCodeAt(e)), + (n = r.charCodeAt(e + 1)), + (a = r.charCodeAt(e + 2)), + (i === _C || i === OC) && ((n >= 48 && n <= 57) || ((n === zn || n === $n) && a >= 48 && a <= 57))) + ) + for (e += n === zn || n === $n ? 3 : 2; e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); ) e += 1; + return { number: r.slice(0, e), unit: r.slice(e) }; + }; + }); + var tm = v((F4, em) => { + l(); + var TC = Vh(), + Kh = Wh(), + Zh = Qh(); + function ct(r) { + return this instanceof ct ? ((this.nodes = TC(r)), this) : new ct(r); + } + ct.prototype.toString = function () { + return Array.isArray(this.nodes) ? Zh(this.nodes) : ""; + }; + ct.prototype.walk = function (r, e) { + return (Kh(this.nodes, r, e), this); + }; + ct.unit = Xh(); + ct.walk = Kh; + ct.stringify = Zh; + em.exports = ct; + }); + function $o(r) { + return typeof r == "object" && r !== null; + } + function PC(r, e) { + let t = Ze(e); + do if ((t.pop(), (0, si.default)(r, t) !== void 0)) break; + while (t.length); + return t.length ? t : void 0; + } + function Gt(r) { + return typeof r == "string" + ? r + : r.reduce((e, t, i) => (t.includes(".") ? `${e}[${t}]` : i === 0 ? t : `${e}.${t}`), ""); + } + function im(r) { + return r.map((e) => `'${e}'`).join(", "); + } + function nm(r) { + return im(Object.keys(r)); + } + function zo(r, e, t, i = {}) { + let n = Array.isArray(e) ? Gt(e) : e.replace(/^['"]+|['"]+$/g, ""), + a = Array.isArray(e) ? e : Ze(n), + s = (0, si.default)(r.theme, a, t); + if (s === void 0) { + let u = `'${n}' does not exist in your theme config.`, + c = a.slice(0, -1), + f = (0, si.default)(r.theme, c); + if ($o(f)) { + let d = Object.keys(f).filter((m) => zo(r, [...c, m]).isValid), + p = (0, rm.default)(a[a.length - 1], d); + p + ? (u += ` Did you mean '${Gt([...c, p])}'?`) + : d.length > 0 && (u += ` '${Gt(c)}' has the following valid keys: ${im(d)}`); + } else { + let d = PC(r.theme, n); + if (d) { + let p = (0, si.default)(r.theme, d); + $o(p) + ? (u += ` '${Gt(d)}' has the following keys: ${nm(p)}`) + : (u += ` '${Gt(d)}' is not an object.`); + } else u += ` Your theme has the following top-level keys: ${nm(r.theme)}`; + } + return { isValid: !1, error: u }; + } + if ( + !( + typeof s == "string" || + typeof s == "number" || + typeof s == "function" || + s instanceof String || + s instanceof Number || + Array.isArray(s) + ) + ) { + let u = `'${n}' was found but does not resolve to a string.`; + if ($o(s)) { + let c = Object.keys(s).filter((f) => zo(r, [...a, f]).isValid); + c.length && (u += ` Did you mean something like '${Gt([...a, c[0]])}'?`); + } + return { isValid: !1, error: u }; + } + let [o] = a; + return { isValid: !0, value: Ge(o)(s, i) }; + } + function DC(r, e, t) { + e = e.map((n) => sm(r, n, t)); + let i = [""]; + for (let n of e) + n.type === "div" && n.value === "," ? i.push("") : (i[i.length - 1] += No.default.stringify(n)); + return i; + } + function sm(r, e, t) { + if (e.type === "function" && t[e.value] !== void 0) { + let i = DC(r, e.nodes, t); + ((e.type = "word"), (e.value = t[e.value](r, ...i))); + } + return e; + } + function IC(r, e, t) { + return Object.keys(t).some((n) => e.includes(`${n}(`)) + ? (0, No.default)(e) + .walk((n) => { + sm(r, n, t); + }) + .toString() + : e; + } + function* RC(r) { + r = r.replace(/^['"]+|['"]+$/g, ""); + let e = r.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/), + t; + (yield [r, void 0], e && ((r = e[1]), (t = e[2]), yield [r, t])); + } + function MC(r, e, t) { + let i = Array.from(RC(e)).map(([n, a]) => + Object.assign(zo(r, n, t, { opacityValue: a }), { resolvedPath: n, alpha: a }) + ); + return i.find((n) => n.isValid) ?? i[0]; + } + function am(r) { + let e = r.tailwindConfig, + t = { + theme: (i, n, ...a) => { + let { isValid: s, value: o, error: u, alpha: c } = MC(e, n, a.length ? a : void 0); + if (!s) { + let p = i.parent, + m = p?.raws.tailwind?.candidate; + if (p && m !== void 0) { + (r.markInvalidUtilityNode(p), + p.remove(), + F.warn("invalid-theme-key-in-class", [ + `The utility \`${m}\` contains an invalid theme value and was not generated.`, + ])); + return; + } + throw i.error(u); + } + let f = Ot(o), + d = f !== void 0 && typeof f == "function"; + return ((c !== void 0 || d) && (c === void 0 && (c = 1), (o = Ie(f, c, f))), o); + }, + screen: (i, n) => { + n = n.replace(/^['"]+/g, "").replace(/['"]+$/g, ""); + let s = ot(e.theme.screens).find(({ name: o }) => o === n); + if (!s) throw i.error(`The '${n}' screen does not exist in your theme.`); + return at(s); + }, + }; + return (i) => { + i.walk((n) => { + let a = qC[n.type]; + a !== void 0 && (n[a] = IC(n, n[a], t)); + }); + }; + } + var si, + rm, + No, + qC, + om = C(() => { + l(); + ((si = X(Gs())), (rm = X(zh()))); + Jr(); + No = X(tm()); + wn(); + mn(); + gi(); + fr(); + hr(); + Oe(); + qC = { atrule: "params", decl: "value" }; + }); + function lm({ tailwindConfig: { theme: r } }) { + return function (e) { + e.walkAtRules("screen", (t) => { + let i = t.params, + a = ot(r.screens).find(({ name: s }) => s === i); + if (!a) throw t.error(`No \`${i}\` screen found.`); + ((t.name = "media"), (t.params = at(a))); + }); + }; + } + var um = C(() => { + l(); + wn(); + mn(); + }); + function BC(r) { + let e = r + .filter((o) => + o.type !== "pseudo" || o.nodes.length > 0 + ? !0 + : o.value.startsWith("::") || + [":before", ":after", ":first-line", ":first-letter"].includes(o.value) + ) + .reverse(), + t = new Set(["tag", "class", "id", "attribute"]), + i = e.findIndex((o) => t.has(o.type)); + if (i === -1) return e.reverse().join("").trim(); + let n = e[i], + a = fm[n.type] ? fm[n.type](n) : n; + e = e.slice(0, i); + let s = e.findIndex((o) => o.type === "combinator" && o.value === ">"); + return (s !== -1 && (e.splice(0, s), e.unshift(jn.default.universal())), [a, ...e.reverse()].join("").trim()); + } + function LC(r) { + return (jo.has(r) || jo.set(r, FC.transformSync(r)), jo.get(r)); + } + function Vo({ tailwindConfig: r }) { + return (e) => { + let t = new Map(), + i = new Set(); + if ( + (e.walkAtRules("defaults", (n) => { + if (n.nodes && n.nodes.length > 0) { + i.add(n); + return; + } + let a = n.params; + (t.has(a) || t.set(a, new Set()), t.get(a).add(n.parent), n.remove()); + }), + K(r, "optimizeUniversalDefaults")) + ) + for (let n of i) { + let a = new Map(), + s = t.get(n.params) ?? []; + for (let o of s) + for (let u of LC(o.selector)) { + let c = u.includes(":-") || u.includes("::-") || u.includes(":has") ? u : "__DEFAULT__", + f = a.get(c) ?? new Set(); + (a.set(c, f), f.add(u)); + } + if (K(r, "optimizeUniversalDefaults")) { + if (a.size === 0) { + n.remove(); + continue; + } + for (let [, o] of a) { + let u = j.rule({ source: n.source }); + ((u.selectors = [...o]), u.append(n.nodes.map((c) => c.clone())), n.before(u)); + } + } + n.remove(); + } + else if (i.size) { + let n = j.rule({ selectors: ["*", "::before", "::after"] }); + for (let s of i) + (n.append(s.nodes), n.parent || s.before(n), n.source || (n.source = s.source), s.remove()); + let a = n.clone({ selectors: ["::backdrop"] }); + n.after(a); + } + }; + } + var jn, + fm, + FC, + jo, + cm = C(() => { + l(); + st(); + jn = X(Me()); + je(); + fm = { + id(r) { + return jn.default.attribute({ attribute: "id", operator: "=", value: r.value, quoteMark: '"' }); + }, + }; + ((FC = (0, jn.default)((r) => + r.map((e) => { + let t = e.split((i) => i.type === "combinator" && i.value === " ").pop(); + return BC(t); + }) + )), + (jo = new Map())); + }); + function Uo() { + function r(e) { + let t = null; + (e.each((i) => { + if (!NC.has(i.type)) { + t = null; + return; + } + if (t === null) { + t = i; + return; + } + let n = pm[i.type]; + i.type === "atrule" && i.name === "font-face" + ? (t = i) + : n.every((a) => (i[a] ?? "").replace(/\s+/g, " ") === (t[a] ?? "").replace(/\s+/g, " ")) + ? (i.nodes && t.append(i.nodes), i.remove()) + : (t = i); + }), + e.each((i) => { + i.type === "atrule" && r(i); + })); + } + return (e) => { + r(e); + }; + } + var pm, + NC, + dm = C(() => { + l(); + ((pm = { atrule: ["name", "params"], rule: ["selector"] }), (NC = new Set(Object.keys(pm)))); + }); + function Wo() { + return (r) => { + r.walkRules((e) => { + let t = new Map(), + i = new Set([]), + n = new Map(); + e.walkDecls((a) => { + if (a.parent === e) { + if (t.has(a.prop)) { + if (t.get(a.prop).value === a.value) { + (i.add(t.get(a.prop)), t.set(a.prop, a)); + return; + } + (n.has(a.prop) || n.set(a.prop, new Set()), + n.get(a.prop).add(t.get(a.prop)), + n.get(a.prop).add(a)); + } + t.set(a.prop, a); + } + }); + for (let a of i) a.remove(); + for (let a of n.values()) { + let s = new Map(); + for (let o of a) { + let u = zC(o.value); + u !== null && (s.has(u) || s.set(u, new Set()), s.get(u).add(o)); + } + for (let o of s.values()) { + let u = Array.from(o).slice(0, -1); + for (let c of u) c.remove(); + } + } + }); + }; + } + function zC(r) { + let e = /^-?\d*.?\d+([\w%]+)?$/g.exec(r); + return e ? (e[1] ?? $C) : null; + } + var $C, + hm = C(() => { + l(); + $C = Symbol("unitless-number"); + }); + function jC(r) { + if (!r.walkAtRules) return; + let e = new Set(); + if ( + (r.walkAtRules("apply", (t) => { + e.add(t.parent); + }), + e.size !== 0) + ) + for (let t of e) { + let i = [], + n = []; + for (let a of t.nodes) + a.type === "atrule" && a.name === "apply" + ? (n.length > 0 && (i.push(n), (n = [])), i.push([a])) + : n.push(a); + if ((n.length > 0 && i.push(n), i.length !== 1)) { + for (let a of [...i].reverse()) { + let s = t.clone({ nodes: [] }); + (s.append(a), t.after(s)); + } + t.remove(); + } + } + } + function Vn() { + return (r) => { + jC(r); + }; + } + var mm = C(() => { + l(); + }); + function Un(r) { + return async function (e, t) { + let { tailwindDirectives: i, applyDirectives: n } = _o(e); + Vn()(e, t); + let a = r({ + tailwindDirectives: i, + applyDirectives: n, + registerDependency(s) { + t.messages.push({ plugin: "tailwindcss", parent: t.opts.from, ...s }); + }, + createContext(s, o) { + return bo(s, o, e); + }, + })(e, t); + if (a.tailwindConfig.separator === "-") + throw new Error( + "The '-' character cannot be used as a custom separator in JIT mode due to parsing ambiguity. Please use another character like '_' instead." + ); + (Iu(a.tailwindConfig), + await To(a)(e, t), + Vn()(e, t), + Do(a)(e, t), + am(a)(e, t), + lm(a)(e, t), + Vo(a)(e, t), + Uo(a)(e, t), + Wo(a)(e, t)); + }; + } + var gm = C(() => { + l(); + Sh(); + Rh(); + $h(); + om(); + um(); + cm(); + dm(); + hm(); + mm(); + ei(); + je(); + }); + function ym(r, e) { + let t = null, + i = null; + return ( + r.walkAtRules("config", (n) => { + if (((i = n.source?.input.file ?? e.opts.from ?? null), i === null)) + throw n.error( + "The `@config` directive cannot be used without setting `from` in your PostCSS config." + ); + if (t) throw n.error("Only one `@config` directive is allowed per file."); + let a = n.params.match(/(['"])(.*?)\1/); + if (!a) throw n.error("A path is required when using the `@config` directive."); + let s = a[2]; + if (Z.isAbsolute(s)) throw n.error("The `@config` directive cannot be used with an absolute path."); + if (((t = Z.resolve(Z.dirname(i), s)), !te.existsSync(t))) + throw n.error( + `The config file at "${s}" does not exist. Make sure the path is correct and the file exists.` + ); + n.remove(); + }), + t || null + ); + } + var wm = C(() => { + l(); + ze(); + bt(); + }); + var bm = v((vD, Go) => { + l(); + kh(); + gm(); + lt(); + wm(); + Go.exports = function (e) { + return { + postcssPlugin: "tailwindcss", + plugins: [ + Pe.DEBUG && + function (t) { + return ( + console.log(` +`), + console.time("JIT TOTAL"), + t + ); + }, + async function (t, i) { + e = ym(t, i) ?? e; + let n = Ao(e); + if (t.type === "document") { + let a = t.nodes.filter((s) => s.type === "root"); + for (let s of a) s.type === "root" && (await Un(n)(s, i)); + return; + } + await Un(n)(t, i); + }, + Pe.DEBUG && + function (t) { + return ( + console.timeEnd("JIT TOTAL"), + console.log(` +`), + t + ); + }, + ].filter(Boolean), + }; + }; + Go.exports.postcss = !0; + }); + var xm = v((xD, vm) => { + l(); + vm.exports = bm(); + }); + var Ho = v((kD, km) => { + l(); + km.exports = () => [ + "and_chr 114", + "and_uc 15.5", + "chrome 114", + "chrome 113", + "chrome 109", + "edge 114", + "firefox 114", + "ios_saf 16.5", + "ios_saf 16.4", + "ios_saf 16.3", + "ios_saf 16.1", + "opera 99", + "safari 16.5", + "samsung 21", + ]; + }); + var Wn = {}; + Ae(Wn, { agents: () => VC, feature: () => UC }); + function UC() { + return { + status: "cr", + title: "CSS Feature Queries", + stats: { + ie: { 6: "n", 7: "n", 8: "n", 9: "n", 10: "n", 11: "n", 5.5: "n" }, + edge: { + 12: "y", + 13: "y", + 14: "y", + 15: "y", + 16: "y", + 17: "y", + 18: "y", + 79: "y", + 80: "y", + 81: "y", + 83: "y", + 84: "y", + 85: "y", + 86: "y", + 87: "y", + 88: "y", + 89: "y", + 90: "y", + 91: "y", + 92: "y", + 93: "y", + 94: "y", + 95: "y", + 96: "y", + 97: "y", + 98: "y", + 99: "y", + 100: "y", + 101: "y", + 102: "y", + 103: "y", + 104: "y", + 105: "y", + 106: "y", + 107: "y", + 108: "y", + 109: "y", + 110: "y", + 111: "y", + 112: "y", + 113: "y", + 114: "y", + }, + firefox: { + 2: "n", + 3: "n", + 4: "n", + 5: "n", + 6: "n", + 7: "n", + 8: "n", + 9: "n", + 10: "n", + 11: "n", + 12: "n", + 13: "n", + 14: "n", + 15: "n", + 16: "n", + 17: "n", + 18: "n", + 19: "n", + 20: "n", + 21: "n", + 22: "y", + 23: "y", + 24: "y", + 25: "y", + 26: "y", + 27: "y", + 28: "y", + 29: "y", + 30: "y", + 31: "y", + 32: "y", + 33: "y", + 34: "y", + 35: "y", + 36: "y", + 37: "y", + 38: "y", + 39: "y", + 40: "y", + 41: "y", + 42: "y", + 43: "y", + 44: "y", + 45: "y", + 46: "y", + 47: "y", + 48: "y", + 49: "y", + 50: "y", + 51: "y", + 52: "y", + 53: "y", + 54: "y", + 55: "y", + 56: "y", + 57: "y", + 58: "y", + 59: "y", + 60: "y", + 61: "y", + 62: "y", + 63: "y", + 64: "y", + 65: "y", + 66: "y", + 67: "y", + 68: "y", + 69: "y", + 70: "y", + 71: "y", + 72: "y", + 73: "y", + 74: "y", + 75: "y", + 76: "y", + 77: "y", + 78: "y", + 79: "y", + 80: "y", + 81: "y", + 82: "y", + 83: "y", + 84: "y", + 85: "y", + 86: "y", + 87: "y", + 88: "y", + 89: "y", + 90: "y", + 91: "y", + 92: "y", + 93: "y", + 94: "y", + 95: "y", + 96: "y", + 97: "y", + 98: "y", + 99: "y", + 100: "y", + 101: "y", + 102: "y", + 103: "y", + 104: "y", + 105: "y", + 106: "y", + 107: "y", + 108: "y", + 109: "y", + 110: "y", + 111: "y", + 112: "y", + 113: "y", + 114: "y", + 115: "y", + 116: "y", + 117: "y", + 3.5: "n", + 3.6: "n", + }, + chrome: { + 4: "n", + 5: "n", + 6: "n", + 7: "n", + 8: "n", + 9: "n", + 10: "n", + 11: "n", + 12: "n", + 13: "n", + 14: "n", + 15: "n", + 16: "n", + 17: "n", + 18: "n", + 19: "n", + 20: "n", + 21: "n", + 22: "n", + 23: "n", + 24: "n", + 25: "n", + 26: "n", + 27: "n", + 28: "y", + 29: "y", + 30: "y", + 31: "y", + 32: "y", + 33: "y", + 34: "y", + 35: "y", + 36: "y", + 37: "y", + 38: "y", + 39: "y", + 40: "y", + 41: "y", + 42: "y", + 43: "y", + 44: "y", + 45: "y", + 46: "y", + 47: "y", + 48: "y", + 49: "y", + 50: "y", + 51: "y", + 52: "y", + 53: "y", + 54: "y", + 55: "y", + 56: "y", + 57: "y", + 58: "y", + 59: "y", + 60: "y", + 61: "y", + 62: "y", + 63: "y", + 64: "y", + 65: "y", + 66: "y", + 67: "y", + 68: "y", + 69: "y", + 70: "y", + 71: "y", + 72: "y", + 73: "y", + 74: "y", + 75: "y", + 76: "y", + 77: "y", + 78: "y", + 79: "y", + 80: "y", + 81: "y", + 83: "y", + 84: "y", + 85: "y", + 86: "y", + 87: "y", + 88: "y", + 89: "y", + 90: "y", + 91: "y", + 92: "y", + 93: "y", + 94: "y", + 95: "y", + 96: "y", + 97: "y", + 98: "y", + 99: "y", + 100: "y", + 101: "y", + 102: "y", + 103: "y", + 104: "y", + 105: "y", + 106: "y", + 107: "y", + 108: "y", + 109: "y", + 110: "y", + 111: "y", + 112: "y", + 113: "y", + 114: "y", + 115: "y", + 116: "y", + 117: "y", + }, + safari: { + 4: "n", + 5: "n", + 6: "n", + 7: "n", + 8: "n", + 9: "y", + 10: "y", + 11: "y", + 12: "y", + 13: "y", + 14: "y", + 15: "y", + 17: "y", + 9.1: "y", + 10.1: "y", + 11.1: "y", + 12.1: "y", + 13.1: "y", + 14.1: "y", + 15.1: "y", + "15.2-15.3": "y", + 15.4: "y", + 15.5: "y", + 15.6: "y", + "16.0": "y", + 16.1: "y", + 16.2: "y", + 16.3: "y", + 16.4: "y", + 16.5: "y", + 16.6: "y", + TP: "y", + 3.1: "n", + 3.2: "n", + 5.1: "n", + 6.1: "n", + 7.1: "n", + }, + opera: { + 9: "n", + 11: "n", + 12: "n", + 15: "y", + 16: "y", + 17: "y", + 18: "y", + 19: "y", + 20: "y", + 21: "y", + 22: "y", + 23: "y", + 24: "y", + 25: "y", + 26: "y", + 27: "y", + 28: "y", + 29: "y", + 30: "y", + 31: "y", + 32: "y", + 33: "y", + 34: "y", + 35: "y", + 36: "y", + 37: "y", + 38: "y", + 39: "y", + 40: "y", + 41: "y", + 42: "y", + 43: "y", + 44: "y", + 45: "y", + 46: "y", + 47: "y", + 48: "y", + 49: "y", + 50: "y", + 51: "y", + 52: "y", + 53: "y", + 54: "y", + 55: "y", + 56: "y", + 57: "y", + 58: "y", + 60: "y", + 62: "y", + 63: "y", + 64: "y", + 65: "y", + 66: "y", + 67: "y", + 68: "y", + 69: "y", + 70: "y", + 71: "y", + 72: "y", + 73: "y", + 74: "y", + 75: "y", + 76: "y", + 77: "y", + 78: "y", + 79: "y", + 80: "y", + 81: "y", + 82: "y", + 83: "y", + 84: "y", + 85: "y", + 86: "y", + 87: "y", + 88: "y", + 89: "y", + 90: "y", + 91: "y", + 92: "y", + 93: "y", + 94: "y", + 95: "y", + 96: "y", + 97: "y", + 98: "y", + 99: "y", + 100: "y", + 12.1: "y", + "9.5-9.6": "n", + "10.0-10.1": "n", + 10.5: "n", + 10.6: "n", + 11.1: "n", + 11.5: "n", + 11.6: "n", + }, + ios_saf: { + 8: "n", + 17: "y", + "9.0-9.2": "y", + 9.3: "y", + "10.0-10.2": "y", + 10.3: "y", + "11.0-11.2": "y", + "11.3-11.4": "y", + "12.0-12.1": "y", + "12.2-12.5": "y", + "13.0-13.1": "y", + 13.2: "y", + 13.3: "y", + "13.4-13.7": "y", + "14.0-14.4": "y", + "14.5-14.8": "y", + "15.0-15.1": "y", + "15.2-15.3": "y", + 15.4: "y", + 15.5: "y", + 15.6: "y", + "16.0": "y", + 16.1: "y", + 16.2: "y", + 16.3: "y", + 16.4: "y", + 16.5: "y", + 16.6: "y", + 3.2: "n", + "4.0-4.1": "n", + "4.2-4.3": "n", + "5.0-5.1": "n", + "6.0-6.1": "n", + "7.0-7.1": "n", + "8.1-8.4": "n", + }, + op_mini: { all: "y" }, + android: { + 3: "n", + 4: "n", + 114: "y", + 4.4: "y", + "4.4.3-4.4.4": "y", + 2.1: "n", + 2.2: "n", + 2.3: "n", + 4.1: "n", + "4.2-4.3": "n", + }, + bb: { 7: "n", 10: "n" }, + op_mob: { 10: "n", 11: "n", 12: "n", 73: "y", 11.1: "n", 11.5: "n", 12.1: "n" }, + and_chr: { 114: "y" }, + and_ff: { 115: "y" }, + ie_mob: { 10: "n", 11: "n" }, + and_uc: { 15.5: "y" }, + samsung: { + 4: "y", + 20: "y", + 21: "y", + "5.0-5.4": "y", + "6.2-6.4": "y", + "7.2-7.4": "y", + 8.2: "y", + 9.2: "y", + 10.1: "y", + "11.1-11.2": "y", + "12.0": "y", + "13.0": "y", + "14.0": "y", + "15.0": "y", + "16.0": "y", + "17.0": "y", + "18.0": "y", + "19.0": "y", + }, + and_qq: { 13.1: "y" }, + baidu: { 13.18: "y" }, + kaios: { 2.5: "y", "3.0-3.1": "y" }, + }, + }; + } + var VC, + Gn = C(() => { + l(); + VC = { + ie: { prefix: "ms" }, + edge: { + prefix: "webkit", + prefix_exceptions: { 12: "ms", 13: "ms", 14: "ms", 15: "ms", 16: "ms", 17: "ms", 18: "ms" }, + }, + firefox: { prefix: "moz" }, + chrome: { prefix: "webkit" }, + safari: { prefix: "webkit" }, + opera: { + prefix: "webkit", + prefix_exceptions: { + 9: "o", + 11: "o", + 12: "o", + "9.5-9.6": "o", + "10.0-10.1": "o", + 10.5: "o", + 10.6: "o", + 11.1: "o", + 11.5: "o", + 11.6: "o", + 12.1: "o", + }, + }, + ios_saf: { prefix: "webkit" }, + op_mini: { prefix: "o" }, + android: { prefix: "webkit" }, + bb: { prefix: "webkit" }, + op_mob: { prefix: "o", prefix_exceptions: { 73: "webkit" } }, + and_chr: { prefix: "webkit" }, + and_ff: { prefix: "moz" }, + ie_mob: { prefix: "ms" }, + and_uc: { prefix: "webkit", prefix_exceptions: { 15.5: "webkit" } }, + samsung: { prefix: "webkit" }, + and_qq: { prefix: "webkit" }, + baidu: { prefix: "webkit" }, + kaios: { prefix: "moz" }, + }; + }); + var Sm = v(() => { + l(); + }); + var le = v((AD, pt) => { + l(); + var { list: Yo } = ge(); + pt.exports.error = function (r) { + let e = new Error(r); + throw ((e.autoprefixer = !0), e); + }; + pt.exports.uniq = function (r) { + return [...new Set(r)]; + }; + pt.exports.removeNote = function (r) { + return r.includes(" ") ? r.split(" ")[0] : r; + }; + pt.exports.escapeRegexp = function (r) { + return r.replace(/[$()*+-.?[\\\]^{|}]/g, "\\$&"); + }; + pt.exports.regexp = function (r, e = !0) { + return (e && (r = this.escapeRegexp(r)), new RegExp(`(^|[\\s,(])(${r}($|[\\s(,]))`, "gi")); + }; + pt.exports.editList = function (r, e) { + let t = Yo.comma(r), + i = e(t, []); + if (t === i) return r; + let n = r.match(/,\s*/); + return ((n = n ? n[0] : ", "), i.join(n)); + }; + pt.exports.splitSelector = function (r) { + return Yo.comma(r).map((e) => Yo.space(e).map((t) => t.split(/(?=\.|#)/g))); + }; + }); + var dt = v((_D, _m) => { + l(); + var WC = Ho(), + Cm = (Gn(), Wn).agents, + GC = le(), + Am = class { + static prefixes() { + if (this.prefixesCache) return this.prefixesCache; + this.prefixesCache = []; + for (let e in Cm) this.prefixesCache.push(`-${Cm[e].prefix}-`); + return ( + (this.prefixesCache = GC.uniq(this.prefixesCache).sort((e, t) => t.length - e.length)), + this.prefixesCache + ); + } + static withPrefix(e) { + return ( + this.prefixesRegexp || (this.prefixesRegexp = new RegExp(this.prefixes().join("|"))), + this.prefixesRegexp.test(e) + ); + } + constructor(e, t, i, n) { + ((this.data = e), + (this.options = i || {}), + (this.browserslistOpts = n || {}), + (this.selected = this.parse(t))); + } + parse(e) { + let t = {}; + for (let i in this.browserslistOpts) t[i] = this.browserslistOpts[i]; + return ((t.path = this.options.from), WC(e, t)); + } + prefix(e) { + let [t, i] = e.split(" "), + n = this.data[t], + a = n.prefix_exceptions && n.prefix_exceptions[i]; + return (a || (a = n.prefix), `-${a}-`); + } + isSelected(e) { + return this.selected.includes(e); + } + }; + _m.exports = Am; + }); + var ai = v((OD, Om) => { + l(); + Om.exports = { + prefix(r) { + let e = r.match(/^(-\w+-)/); + return e ? e[0] : ""; + }, + unprefixed(r) { + return r.replace(/^-\w+-/, ""); + }, + }; + }); + var Ht = v((ED, Tm) => { + l(); + var HC = dt(), + Em = ai(), + YC = le(); + function Qo(r, e) { + let t = new r.constructor(); + for (let i of Object.keys(r || {})) { + let n = r[i]; + i === "parent" && typeof n == "object" + ? e && (t[i] = e) + : i === "source" || i === null + ? (t[i] = n) + : Array.isArray(n) + ? (t[i] = n.map((a) => Qo(a, t))) + : i !== "_autoprefixerPrefix" && + i !== "_autoprefixerValues" && + i !== "proxyCache" && + (typeof n == "object" && n !== null && (n = Qo(n, t)), (t[i] = n)); + } + return t; + } + var Hn = class { + static hack(e) { + return (this.hacks || (this.hacks = {}), e.names.map((t) => ((this.hacks[t] = e), this.hacks[t]))); + } + static load(e, t, i) { + let n = this.hacks && this.hacks[e]; + return n ? new n(e, t, i) : new this(e, t, i); + } + static clone(e, t) { + let i = Qo(e); + for (let n in t) i[n] = t[n]; + return i; + } + constructor(e, t, i) { + ((this.prefixes = t), (this.name = e), (this.all = i)); + } + parentPrefix(e) { + let t; + return ( + typeof e._autoprefixerPrefix != "undefined" + ? (t = e._autoprefixerPrefix) + : e.type === "decl" && e.prop[0] === "-" + ? (t = Em.prefix(e.prop)) + : e.type === "root" + ? (t = !1) + : e.type === "rule" && e.selector.includes(":-") && /:(-\w+-)/.test(e.selector) + ? (t = e.selector.match(/:(-\w+-)/)[1]) + : e.type === "atrule" && e.name[0] === "-" + ? (t = Em.prefix(e.name)) + : (t = this.parentPrefix(e.parent)), + HC.prefixes().includes(t) || (t = !1), + (e._autoprefixerPrefix = t), + e._autoprefixerPrefix + ); + } + process(e, t) { + if (!this.check(e)) return; + let i = this.parentPrefix(e), + n = this.prefixes.filter((s) => !i || i === YC.removeNote(s)), + a = []; + for (let s of n) this.add(e, s, a.concat([s]), t) && a.push(s); + return a; + } + clone(e, t) { + return Hn.clone(e, t); + } + }; + Tm.exports = Hn; + }); + var M = v((TD, Im) => { + l(); + var QC = Ht(), + JC = dt(), + Pm = le(), + Dm = class extends QC { + check() { + return !0; + } + prefixed(e, t) { + return t + e; + } + normalize(e) { + return e; + } + otherPrefixes(e, t) { + for (let i of JC.prefixes()) if (i !== t && e.includes(i)) return !0; + return !1; + } + set(e, t) { + return ((e.prop = this.prefixed(e.prop, t)), e); + } + needCascade(e) { + return ( + e._autoprefixerCascade || + (e._autoprefixerCascade = + this.all.options.cascade !== !1 && + e.raw("before").includes(` +`)), + e._autoprefixerCascade + ); + } + maxPrefixed(e, t) { + if (t._autoprefixerMax) return t._autoprefixerMax; + let i = 0; + for (let n of e) ((n = Pm.removeNote(n)), n.length > i && (i = n.length)); + return ((t._autoprefixerMax = i), t._autoprefixerMax); + } + calcBefore(e, t, i = "") { + let a = this.maxPrefixed(e, t) - Pm.removeNote(i).length, + s = t.raw("before"); + return (a > 0 && (s += Array(a).fill(" ").join("")), s); + } + restoreBefore(e) { + let t = e.raw("before").split(` +`), + i = t[t.length - 1]; + (this.all.group(e).up((n) => { + let a = n.raw("before").split(` +`), + s = a[a.length - 1]; + s.length < i.length && (i = s); + }), + (t[t.length - 1] = i), + (e.raws.before = t.join(` +`))); + } + insert(e, t, i) { + let n = this.set(this.clone(e), t); + if (!(!n || e.parent.some((s) => s.prop === n.prop && s.value === n.value))) + return ( + this.needCascade(e) && (n.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, n) + ); + } + isAlready(e, t) { + let i = this.all.group(e).up((n) => n.prop === t); + return (i || (i = this.all.group(e).down((n) => n.prop === t)), i); + } + add(e, t, i, n) { + let a = this.prefixed(e.prop, t); + if (!(this.isAlready(e, a) || this.otherPrefixes(e.value, t))) return this.insert(e, t, i, n); + } + process(e, t) { + if (!this.needCascade(e)) { + super.process(e, t); + return; + } + let i = super.process(e, t); + !i || !i.length || (this.restoreBefore(e), (e.raws.before = this.calcBefore(i, e))); + } + old(e, t) { + return [this.prefixed(e, t)]; + } + }; + Im.exports = Dm; + }); + var Rm = v((PD, qm) => { + l(); + qm.exports = function r(e) { + return { + mul: (t) => new r(e * t), + div: (t) => new r(e / t), + simplify: () => new r(e), + toString: () => e.toString(), + }; + }; + }); + var Fm = v((DD, Bm) => { + l(); + var XC = Rm(), + KC = Ht(), + Jo = le(), + ZC = /(min|max)-resolution\s*:\s*\d*\.?\d+(dppx|dpcm|dpi|x)/gi, + eA = /(min|max)-resolution(\s*:\s*)(\d*\.?\d+)(dppx|dpcm|dpi|x)/i, + Mm = class extends KC { + prefixName(e, t) { + return e === "-moz-" ? t + "--moz-device-pixel-ratio" : e + t + "-device-pixel-ratio"; + } + prefixQuery(e, t, i, n, a) { + return ( + (n = new XC(n)), + a === "dpi" ? (n = n.div(96)) : a === "dpcm" && (n = n.mul(2.54).div(96)), + (n = n.simplify()), + e === "-o-" && (n = n.n + "/" + n.d), + this.prefixName(e, t) + i + n + ); + } + clean(e) { + if (!this.bad) { + this.bad = []; + for (let t of this.prefixes) + (this.bad.push(this.prefixName(t, "min")), this.bad.push(this.prefixName(t, "max"))); + } + e.params = Jo.editList(e.params, (t) => t.filter((i) => this.bad.every((n) => !i.includes(n)))); + } + process(e) { + let t = this.parentPrefix(e), + i = t ? [t] : this.prefixes; + e.params = Jo.editList(e.params, (n, a) => { + for (let s of n) { + if (!s.includes("min-resolution") && !s.includes("max-resolution")) { + a.push(s); + continue; + } + for (let o of i) { + let u = s.replace(ZC, (c) => { + let f = c.match(eA); + return this.prefixQuery(o, f[1], f[2], f[3], f[4]); + }); + a.push(u); + } + a.push(s); + } + return Jo.uniq(a); + }); + } + }; + Bm.exports = Mm; + }); + var Nm = v((ID, Lm) => { + l(); + var Xo = "(".charCodeAt(0), + Ko = ")".charCodeAt(0), + Yn = "'".charCodeAt(0), + Zo = '"'.charCodeAt(0), + el = "\\".charCodeAt(0), + Yt = "/".charCodeAt(0), + tl = ",".charCodeAt(0), + rl = ":".charCodeAt(0), + Qn = "*".charCodeAt(0), + tA = "u".charCodeAt(0), + rA = "U".charCodeAt(0), + iA = "+".charCodeAt(0), + nA = /^[a-f0-9?-]+$/i; + Lm.exports = function (r) { + for ( + var e = [], + t = r, + i, + n, + a, + s, + o, + u, + c, + f, + d = 0, + p = t.charCodeAt(d), + m = t.length, + b = [{ nodes: e }], + x = 0, + y, + w = "", + k = "", + S = ""; + d < m; + ) + if (p <= 32) { + i = d; + do ((i += 1), (p = t.charCodeAt(i))); + while (p <= 32); + ((s = t.slice(d, i)), + (a = e[e.length - 1]), + p === Ko && x + ? (S = s) + : a && a.type === "div" + ? ((a.after = s), (a.sourceEndIndex += s.length)) + : p === tl || + p === rl || + (p === Yt && + t.charCodeAt(i + 1) !== Qn && + (!y || (y && y.type === "function" && y.value !== "calc"))) + ? (k = s) + : e.push({ type: "space", sourceIndex: d, sourceEndIndex: i, value: s }), + (d = i)); + } else if (p === Yn || p === Zo) { + ((i = d), (n = p === Yn ? "'" : '"'), (s = { type: "string", sourceIndex: d, quote: n })); + do + if (((o = !1), (i = t.indexOf(n, i + 1)), ~i)) + for (u = i; t.charCodeAt(u - 1) === el; ) ((u -= 1), (o = !o)); + else ((t += n), (i = t.length - 1), (s.unclosed = !0)); + while (o); + ((s.value = t.slice(d + 1, i)), + (s.sourceEndIndex = s.unclosed ? i : i + 1), + e.push(s), + (d = i + 1), + (p = t.charCodeAt(d))); + } else if (p === Yt && t.charCodeAt(d + 1) === Qn) + ((i = t.indexOf("*/", d)), + (s = { type: "comment", sourceIndex: d, sourceEndIndex: i + 2 }), + i === -1 && ((s.unclosed = !0), (i = t.length), (s.sourceEndIndex = i)), + (s.value = t.slice(d + 2, i)), + e.push(s), + (d = i + 2), + (p = t.charCodeAt(d))); + else if ((p === Yt || p === Qn) && y && y.type === "function" && y.value === "calc") + ((s = t[d]), + e.push({ type: "word", sourceIndex: d - k.length, sourceEndIndex: d + s.length, value: s }), + (d += 1), + (p = t.charCodeAt(d))); + else if (p === Yt || p === tl || p === rl) + ((s = t[d]), + e.push({ + type: "div", + sourceIndex: d - k.length, + sourceEndIndex: d + s.length, + value: s, + before: k, + after: "", + }), + (k = ""), + (d += 1), + (p = t.charCodeAt(d))); + else if (Xo === p) { + i = d; + do ((i += 1), (p = t.charCodeAt(i))); + while (p <= 32); + if ( + ((f = d), + (s = { type: "function", sourceIndex: d - w.length, value: w, before: t.slice(f + 1, i) }), + (d = i), + w === "url" && p !== Yn && p !== Zo) + ) { + i -= 1; + do + if (((o = !1), (i = t.indexOf(")", i + 1)), ~i)) + for (u = i; t.charCodeAt(u - 1) === el; ) ((u -= 1), (o = !o)); + else ((t += ")"), (i = t.length - 1), (s.unclosed = !0)); + while (o); + c = i; + do ((c -= 1), (p = t.charCodeAt(c))); + while (p <= 32); + (f < c + ? (d !== c + 1 + ? (s.nodes = [ + { + type: "word", + sourceIndex: d, + sourceEndIndex: c + 1, + value: t.slice(d, c + 1), + }, + ]) + : (s.nodes = []), + s.unclosed && c + 1 !== i + ? ((s.after = ""), + s.nodes.push({ + type: "space", + sourceIndex: c + 1, + sourceEndIndex: i, + value: t.slice(c + 1, i), + })) + : ((s.after = t.slice(c + 1, i)), (s.sourceEndIndex = i))) + : ((s.after = ""), (s.nodes = [])), + (d = i + 1), + (s.sourceEndIndex = s.unclosed ? i : d), + (p = t.charCodeAt(d)), + e.push(s)); + } else + ((x += 1), + (s.after = ""), + (s.sourceEndIndex = d + 1), + e.push(s), + b.push(s), + (e = s.nodes = []), + (y = s)); + w = ""; + } else if (Ko === p && x) + ((d += 1), + (p = t.charCodeAt(d)), + (y.after = S), + (y.sourceEndIndex += S.length), + (S = ""), + (x -= 1), + (b[b.length - 1].sourceEndIndex = d), + b.pop(), + (y = b[x]), + (e = y.nodes)); + else { + i = d; + do (p === el && (i += 1), (i += 1), (p = t.charCodeAt(i))); + while ( + i < m && + !( + p <= 32 || + p === Yn || + p === Zo || + p === tl || + p === rl || + p === Yt || + p === Xo || + (p === Qn && y && y.type === "function" && y.value === "calc") || + (p === Yt && y.type === "function" && y.value === "calc") || + (p === Ko && x) + ) + ); + ((s = t.slice(d, i)), + Xo === p + ? (w = s) + : (tA === s.charCodeAt(0) || rA === s.charCodeAt(0)) && + iA === s.charCodeAt(1) && + nA.test(s.slice(2)) + ? e.push({ type: "unicode-range", sourceIndex: d, sourceEndIndex: i, value: s }) + : e.push({ type: "word", sourceIndex: d, sourceEndIndex: i, value: s }), + (d = i)); + } + for (d = b.length - 1; d; d -= 1) ((b[d].unclosed = !0), (b[d].sourceEndIndex = t.length)); + return b[0].nodes; + }; + }); + var zm = v((qD, $m) => { + l(); + $m.exports = function r(e, t, i) { + var n, a, s, o; + for (n = 0, a = e.length; n < a; n += 1) + ((s = e[n]), + i || (o = t(s, n, e)), + o !== !1 && s.type === "function" && Array.isArray(s.nodes) && r(s.nodes, t, i), + i && t(s, n, e)); + }; + }); + var Wm = v((RD, Um) => { + l(); + function jm(r, e) { + var t = r.type, + i = r.value, + n, + a; + return e && (a = e(r)) !== void 0 + ? a + : t === "word" || t === "space" + ? i + : t === "string" + ? ((n = r.quote || ""), n + i + (r.unclosed ? "" : n)) + : t === "comment" + ? "/*" + i + (r.unclosed ? "" : "*/") + : t === "div" + ? (r.before || "") + i + (r.after || "") + : Array.isArray(r.nodes) + ? ((n = Vm(r.nodes, e)), + t !== "function" + ? n + : i + "(" + (r.before || "") + n + (r.after || "") + (r.unclosed ? "" : ")")) + : i; + } + function Vm(r, e) { + var t, i; + if (Array.isArray(r)) { + for (t = "", i = r.length - 1; ~i; i -= 1) t = jm(r[i], e) + t; + return t; + } + return jm(r, e); + } + Um.exports = Vm; + }); + var Hm = v((MD, Gm) => { + l(); + var Jn = "-".charCodeAt(0), + Xn = "+".charCodeAt(0), + il = ".".charCodeAt(0), + sA = "e".charCodeAt(0), + aA = "E".charCodeAt(0); + function oA(r) { + var e = r.charCodeAt(0), + t; + if (e === Xn || e === Jn) { + if (((t = r.charCodeAt(1)), t >= 48 && t <= 57)) return !0; + var i = r.charCodeAt(2); + return t === il && i >= 48 && i <= 57; + } + return e === il ? ((t = r.charCodeAt(1)), t >= 48 && t <= 57) : e >= 48 && e <= 57; + } + Gm.exports = function (r) { + var e = 0, + t = r.length, + i, + n, + a; + if (t === 0 || !oA(r)) return !1; + for ( + i = r.charCodeAt(e), (i === Xn || i === Jn) && e++; + e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); + ) + e += 1; + if (((i = r.charCodeAt(e)), (n = r.charCodeAt(e + 1)), i === il && n >= 48 && n <= 57)) + for (e += 2; e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); ) e += 1; + if ( + ((i = r.charCodeAt(e)), + (n = r.charCodeAt(e + 1)), + (a = r.charCodeAt(e + 2)), + (i === sA || i === aA) && ((n >= 48 && n <= 57) || ((n === Xn || n === Jn) && a >= 48 && a <= 57))) + ) + for (e += n === Xn || n === Jn ? 3 : 2; e < t && ((i = r.charCodeAt(e)), !(i < 48 || i > 57)); ) e += 1; + return { number: r.slice(0, e), unit: r.slice(e) }; + }; + }); + var Kn = v((BD, Jm) => { + l(); + var lA = Nm(), + Ym = zm(), + Qm = Wm(); + function ht(r) { + return this instanceof ht ? ((this.nodes = lA(r)), this) : new ht(r); + } + ht.prototype.toString = function () { + return Array.isArray(this.nodes) ? Qm(this.nodes) : ""; + }; + ht.prototype.walk = function (r, e) { + return (Ym(this.nodes, r, e), this); + }; + ht.unit = Hm(); + ht.walk = Ym; + ht.stringify = Qm; + Jm.exports = ht; + }); + var tg = v((FD, eg) => { + l(); + var { list: uA } = ge(), + Xm = Kn(), + fA = dt(), + Km = ai(), + Zm = class { + constructor(e) { + ((this.props = ["transition", "transition-property"]), (this.prefixes = e)); + } + add(e, t) { + let i, + n, + a = this.prefixes.add[e.prop], + s = this.ruleVendorPrefixes(e), + o = s || (a && a.prefixes) || [], + u = this.parse(e.value), + c = u.map((m) => this.findProp(m)), + f = []; + if (c.some((m) => m[0] === "-")) return; + for (let m of u) { + if (((n = this.findProp(m)), n[0] === "-")) continue; + let b = this.prefixes.add[n]; + if (!(!b || !b.prefixes)) + for (i of b.prefixes) { + if (s && !s.some((y) => i.includes(y))) continue; + let x = this.prefixes.prefixed(n, i); + x !== "-ms-transform" && + !c.includes(x) && + (this.disabled(n, i) || f.push(this.clone(n, x, m))); + } + } + u = u.concat(f); + let d = this.stringify(u), + p = this.stringify(this.cleanFromUnprefixed(u, "-webkit-")); + if ( + (o.includes("-webkit-") && this.cloneBefore(e, `-webkit-${e.prop}`, p), + this.cloneBefore(e, e.prop, p), + o.includes("-o-")) + ) { + let m = this.stringify(this.cleanFromUnprefixed(u, "-o-")); + this.cloneBefore(e, `-o-${e.prop}`, m); + } + for (i of o) + if (i !== "-webkit-" && i !== "-o-") { + let m = this.stringify(this.cleanOtherPrefixes(u, i)); + this.cloneBefore(e, i + e.prop, m); + } + d !== e.value && + !this.already(e, e.prop, d) && + (this.checkForWarning(t, e), e.cloneBefore(), (e.value = d)); + } + findProp(e) { + let t = e[0].value; + if (/^\d/.test(t)) { + for (let [i, n] of e.entries()) if (i !== 0 && n.type === "word") return n.value; + } + return t; + } + already(e, t, i) { + return e.parent.some((n) => n.prop === t && n.value === i); + } + cloneBefore(e, t, i) { + this.already(e, t, i) || e.cloneBefore({ prop: t, value: i }); + } + checkForWarning(e, t) { + if (t.prop !== "transition-property") return; + let i = !1, + n = !1; + (t.parent.each((a) => { + if (a.type !== "decl" || a.prop.indexOf("transition-") !== 0) return; + let s = uA.comma(a.value); + if (a.prop === "transition-property") { + s.forEach((o) => { + let u = this.prefixes.add[o]; + u && u.prefixes && u.prefixes.length > 0 && (i = !0); + }); + return; + } + return ((n = n || s.length > 1), !1); + }), + i && + n && + t.warn( + e, + "Replace transition-property to transition, because Autoprefixer could not support any cases of transition-property and other transition-*" + )); + } + remove(e) { + let t = this.parse(e.value); + t = t.filter((s) => { + let o = this.prefixes.remove[this.findProp(s)]; + return !o || !o.remove; + }); + let i = this.stringify(t); + if (e.value === i) return; + if (t.length === 0) { + e.remove(); + return; + } + let n = e.parent.some((s) => s.prop === e.prop && s.value === i), + a = e.parent.some((s) => s !== e && s.prop === e.prop && s.value.length > i.length); + if (n || a) { + e.remove(); + return; + } + e.value = i; + } + parse(e) { + let t = Xm(e), + i = [], + n = []; + for (let a of t.nodes) (n.push(a), a.type === "div" && a.value === "," && (i.push(n), (n = []))); + return (i.push(n), i.filter((a) => a.length > 0)); + } + stringify(e) { + if (e.length === 0) return ""; + let t = []; + for (let i of e) (i[i.length - 1].type !== "div" && i.push(this.div(e)), (t = t.concat(i))); + return ( + t[0].type === "div" && (t = t.slice(1)), + t[t.length - 1].type === "div" && (t = t.slice(0, -2 + 1 || void 0)), + Xm.stringify({ nodes: t }) + ); + } + clone(e, t, i) { + let n = [], + a = !1; + for (let s of i) + !a && s.type === "word" && s.value === e + ? (n.push({ type: "word", value: t }), (a = !0)) + : n.push(s); + return n; + } + div(e) { + for (let t of e) for (let i of t) if (i.type === "div" && i.value === ",") return i; + return { type: "div", value: ",", after: " " }; + } + cleanOtherPrefixes(e, t) { + return e.filter((i) => { + let n = Km.prefix(this.findProp(i)); + return n === "" || n === t; + }); + } + cleanFromUnprefixed(e, t) { + let i = e + .map((a) => this.findProp(a)) + .filter((a) => a.slice(0, t.length) === t) + .map((a) => this.prefixes.unprefixed(a)), + n = []; + for (let a of e) { + let s = this.findProp(a), + o = Km.prefix(s); + !i.includes(s) && (o === t || o === "") && n.push(a); + } + return n; + } + disabled(e, t) { + let i = ["order", "justify-content", "align-self", "align-content"]; + if (e.includes("flex") || i.includes(e)) { + if (this.prefixes.options.flexbox === !1) return !0; + if (this.prefixes.options.flexbox === "no-2009") return t.includes("2009"); + } + } + ruleVendorPrefixes(e) { + let { parent: t } = e; + if (t.type !== "rule") return !1; + if (!t.selector.includes(":-")) return !1; + let i = fA.prefixes().filter((n) => t.selector.includes(":" + n)); + return i.length > 0 ? i : !1; + } + }; + eg.exports = Zm; + }); + var Qt = v((LD, ig) => { + l(); + var cA = le(), + rg = class { + constructor(e, t, i, n) { + ((this.unprefixed = e), + (this.prefixed = t), + (this.string = i || t), + (this.regexp = n || cA.regexp(t))); + } + check(e) { + return e.includes(this.string) ? !!e.match(this.regexp) : !1; + } + }; + ig.exports = rg; + }); + var ke = v((ND, sg) => { + l(); + var pA = Ht(), + dA = Qt(), + hA = ai(), + mA = le(), + ng = class extends pA { + static save(e, t) { + let i = t.prop, + n = []; + for (let a in t._autoprefixerValues) { + let s = t._autoprefixerValues[a]; + if (s === t.value) continue; + let o, + u = hA.prefix(i); + if (u === "-pie-") continue; + if (u === a) { + ((o = t.value = s), n.push(o)); + continue; + } + let c = e.prefixed(i, a), + f = t.parent; + if (!f.every((b) => b.prop !== c)) { + n.push(o); + continue; + } + let d = s.replace(/\s+/, " "); + if (f.some((b) => b.prop === t.prop && b.value.replace(/\s+/, " ") === d)) { + n.push(o); + continue; + } + let m = this.clone(t, { value: s }); + ((o = t.parent.insertBefore(t, m)), n.push(o)); + } + return n; + } + check(e) { + let t = e.value; + return t.includes(this.name) ? !!t.match(this.regexp()) : !1; + } + regexp() { + return this.regexpCache || (this.regexpCache = mA.regexp(this.name)); + } + replace(e, t) { + return e.replace(this.regexp(), `$1${t}$2`); + } + value(e) { + return e.raws.value && e.raws.value.value === e.value ? e.raws.value.raw : e.value; + } + add(e, t) { + e._autoprefixerValues || (e._autoprefixerValues = {}); + let i = e._autoprefixerValues[t] || this.value(e), + n; + do if (((n = i), (i = this.replace(i, t)), i === !1)) return; + while (i !== n); + e._autoprefixerValues[t] = i; + } + old(e) { + return new dA(this.name, e + this.name); + } + }; + sg.exports = ng; + }); + var mt = v(($D, ag) => { + l(); + ag.exports = {}; + }); + var sl = v((zD, ug) => { + l(); + var og = Kn(), + gA = ke(), + yA = mt().insertAreas, + wA = /(^|[^-])linear-gradient\(\s*(top|left|right|bottom)/i, + bA = /(^|[^-])radial-gradient\(\s*\d+(\w*|%)\s+\d+(\w*|%)\s*,/i, + vA = /(!\s*)?autoprefixer:\s*ignore\s+next/i, + xA = /(!\s*)?autoprefixer\s*grid:\s*(on|off|(no-)?autoplace)/i, + kA = [ + "width", + "height", + "min-width", + "max-width", + "min-height", + "max-height", + "inline-size", + "min-inline-size", + "max-inline-size", + "block-size", + "min-block-size", + "max-block-size", + ]; + function nl(r) { + return r.parent.some((e) => e.prop === "grid-template" || e.prop === "grid-template-areas"); + } + function SA(r) { + let e = r.parent.some((i) => i.prop === "grid-template-rows"), + t = r.parent.some((i) => i.prop === "grid-template-columns"); + return e && t; + } + var lg = class { + constructor(e) { + this.prefixes = e; + } + add(e, t) { + let i = this.prefixes.add["@resolution"], + n = this.prefixes.add["@keyframes"], + a = this.prefixes.add["@viewport"], + s = this.prefixes.add["@supports"]; + (e.walkAtRules((f) => { + if (f.name === "keyframes") { + if (!this.disabled(f, t)) return n && n.process(f); + } else if (f.name === "viewport") { + if (!this.disabled(f, t)) return a && a.process(f); + } else if (f.name === "supports") { + if (this.prefixes.options.supports !== !1 && !this.disabled(f, t)) return s.process(f); + } else if (f.name === "media" && f.params.includes("-resolution") && !this.disabled(f, t)) + return i && i.process(f); + }), + e.walkRules((f) => { + if (!this.disabled(f, t)) return this.prefixes.add.selectors.map((d) => d.process(f, t)); + })); + function o(f) { + return f.parent.nodes.some((d) => { + if (d.type !== "decl") return !1; + let p = d.prop === "display" && /(inline-)?grid/.test(d.value), + m = d.prop.startsWith("grid-template"), + b = /^grid-([A-z]+-)?gap/.test(d.prop); + return p || m || b; + }); + } + function u(f) { + return f.parent.some((d) => d.prop === "display" && /(inline-)?flex/.test(d.value)); + } + let c = + this.gridStatus(e, t) && this.prefixes.add["grid-area"] && this.prefixes.add["grid-area"].prefixes; + return ( + e.walkDecls((f) => { + if (this.disabledDecl(f, t)) return; + let d = f.parent, + p = f.prop, + m = f.value; + if (p === "grid-row-span") { + t.warn("grid-row-span is not part of final Grid Layout. Use grid-row.", { node: f }); + return; + } else if (p === "grid-column-span") { + t.warn("grid-column-span is not part of final Grid Layout. Use grid-column.", { node: f }); + return; + } else if (p === "display" && m === "box") { + t.warn("You should write display: flex by final spec instead of display: box", { node: f }); + return; + } else if (p === "text-emphasis-position") + (m === "under" || m === "over") && + t.warn( + "You should use 2 values for text-emphasis-position For example, `under left` instead of just `under`.", + { node: f } + ); + else if (/^(align|justify|place)-(items|content)$/.test(p) && u(f)) + (m === "start" || m === "end") && + t.warn(`${m} value has mixed support, consider using flex-${m} instead`, { node: f }); + else if (p === "text-decoration-skip" && m === "ink") + t.warn( + "Replace text-decoration-skip: ink to text-decoration-skip-ink: auto, because spec had been changed", + { node: f } + ); + else { + if (c && this.gridStatus(f, t)) + if ( + (f.value === "subgrid" && t.warn("IE does not support subgrid", { node: f }), + /^(align|justify|place)-items$/.test(p) && o(f)) + ) { + let x = p.replace("-items", "-self"); + t.warn( + `IE does not support ${p} on grid containers. Try using ${x} on child elements instead: ${f.parent.selector} > * { ${x}: ${f.value} }`, + { node: f } + ); + } else if (/^(align|justify|place)-content$/.test(p) && o(f)) + t.warn(`IE does not support ${f.prop} on grid containers`, { node: f }); + else if (p === "display" && f.value === "contents") { + t.warn("Please do not use display: contents; if you have grid setting enabled", { + node: f, + }); + return; + } else if (f.prop === "grid-gap") { + let x = this.gridStatus(f, t); + x === "autoplace" && !SA(f) && !nl(f) + ? t.warn( + "grid-gap only works if grid-template(-areas) is being used or both rows and columns have been declared and cells have not been manually placed inside the explicit grid", + { node: f } + ) + : (x === !0 || x === "no-autoplace") && + !nl(f) && + t.warn("grid-gap only works if grid-template(-areas) is being used", { + node: f, + }); + } else if (p === "grid-auto-columns") { + t.warn("grid-auto-columns is not supported by IE", { node: f }); + return; + } else if (p === "grid-auto-rows") { + t.warn("grid-auto-rows is not supported by IE", { node: f }); + return; + } else if (p === "grid-auto-flow") { + let x = d.some((w) => w.prop === "grid-template-rows"), + y = d.some((w) => w.prop === "grid-template-columns"); + nl(f) + ? t.warn("grid-auto-flow is not supported by IE", { node: f }) + : m.includes("dense") + ? t.warn("grid-auto-flow: dense is not supported by IE", { node: f }) + : !x && + !y && + t.warn( + "grid-auto-flow works only if grid-template-rows and grid-template-columns are present in the same rule", + { node: f } + ); + return; + } else if (m.includes("auto-fit")) { + t.warn("auto-fit value is not supported by IE", { node: f, word: "auto-fit" }); + return; + } else if (m.includes("auto-fill")) { + t.warn("auto-fill value is not supported by IE", { node: f, word: "auto-fill" }); + return; + } else + p.startsWith("grid-template") && + m.includes("[") && + t.warn( + "Autoprefixer currently does not support line names. Try using grid-template-areas instead.", + { node: f, word: "[" } + ); + if (m.includes("radial-gradient")) + if (bA.test(f.value)) + t.warn( + "Gradient has outdated direction syntax. New syntax is like `closest-side at 0 0` instead of `0 0, closest-side`.", + { node: f } + ); + else { + let x = og(m); + for (let y of x.nodes) + if (y.type === "function" && y.value === "radial-gradient") + for (let w of y.nodes) + w.type === "word" && + (w.value === "cover" + ? t.warn( + "Gradient has outdated direction syntax. Replace `cover` to `farthest-corner`.", + { node: f } + ) + : w.value === "contain" && + t.warn( + "Gradient has outdated direction syntax. Replace `contain` to `closest-side`.", + { node: f } + )); + } + m.includes("linear-gradient") && + wA.test(m) && + t.warn( + "Gradient has outdated direction syntax. New syntax is like `to left` instead of `right`.", + { node: f } + ); + } + kA.includes(f.prop) && + (f.value.includes("-fill-available") || + (f.value.includes("fill-available") + ? t.warn("Replace fill-available to stretch, because spec had been changed", { + node: f, + }) + : f.value.includes("fill") && + og(m).nodes.some((y) => y.type === "word" && y.value === "fill") && + t.warn("Replace fill to stretch, because spec had been changed", { node: f }))); + let b; + if (f.prop === "transition" || f.prop === "transition-property") + return this.prefixes.transition.add(f, t); + if (f.prop === "align-self") { + if ( + (this.displayType(f) !== "grid" && + this.prefixes.options.flexbox !== !1 && + ((b = this.prefixes.add["align-self"]), b && b.prefixes && b.process(f)), + this.gridStatus(f, t) !== !1 && + ((b = this.prefixes.add["grid-row-align"]), b && b.prefixes)) + ) + return b.process(f, t); + } else if (f.prop === "justify-self") { + if ( + this.gridStatus(f, t) !== !1 && + ((b = this.prefixes.add["grid-column-align"]), b && b.prefixes) + ) + return b.process(f, t); + } else if (f.prop === "place-self") { + if ( + ((b = this.prefixes.add["place-self"]), b && b.prefixes && this.gridStatus(f, t) !== !1) + ) + return b.process(f, t); + } else if (((b = this.prefixes.add[f.prop]), b && b.prefixes)) return b.process(f, t); + }), + this.gridStatus(e, t) && yA(e, this.disabled), + e.walkDecls((f) => { + if (this.disabledValue(f, t)) return; + let d = this.prefixes.unprefixed(f.prop), + p = this.prefixes.values("add", d); + if (Array.isArray(p)) for (let m of p) m.process && m.process(f, t); + gA.save(this.prefixes, f); + }) + ); + } + remove(e, t) { + let i = this.prefixes.remove["@resolution"]; + e.walkAtRules((n, a) => { + this.prefixes.remove[`@${n.name}`] + ? this.disabled(n, t) || n.parent.removeChild(a) + : n.name === "media" && n.params.includes("-resolution") && i && i.clean(n); + }); + for (let n of this.prefixes.remove.selectors) + e.walkRules((a, s) => { + n.check(a) && (this.disabled(a, t) || a.parent.removeChild(s)); + }); + return e.walkDecls((n, a) => { + if (this.disabled(n, t)) return; + let s = n.parent, + o = this.prefixes.unprefixed(n.prop); + if ( + ((n.prop === "transition" || n.prop === "transition-property") && + this.prefixes.transition.remove(n), + this.prefixes.remove[n.prop] && this.prefixes.remove[n.prop].remove) + ) { + let u = this.prefixes.group(n).down((c) => this.prefixes.normalize(c.prop) === o); + if ((o === "flex-flow" && (u = !0), n.prop === "-webkit-box-orient")) { + let c = { "flex-direction": !0, "flex-flow": !0 }; + if (!n.parent.some((f) => c[f.prop])) return; + } + if (u && !this.withHackValue(n)) { + (n.raw("before").includes(` +`) && this.reduceSpaces(n), + s.removeChild(a)); + return; + } + } + for (let u of this.prefixes.values("remove", o)) { + if (!u.check || !u.check(n.value)) continue; + if (((o = u.unprefixed), this.prefixes.group(n).down((f) => f.value.includes(o)))) { + s.removeChild(a); + return; + } + } + }); + } + withHackValue(e) { + return e.prop === "-webkit-background-clip" && e.value === "text"; + } + disabledValue(e, t) { + return (this.gridStatus(e, t) === !1 && + e.type === "decl" && + e.prop === "display" && + e.value.includes("grid")) || + (this.prefixes.options.flexbox === !1 && + e.type === "decl" && + e.prop === "display" && + e.value.includes("flex")) || + (e.type === "decl" && e.prop === "content") + ? !0 + : this.disabled(e, t); + } + disabledDecl(e, t) { + if ( + this.gridStatus(e, t) === !1 && + e.type === "decl" && + (e.prop.includes("grid") || e.prop === "justify-items") + ) + return !0; + if (this.prefixes.options.flexbox === !1 && e.type === "decl") { + let i = ["order", "justify-content", "align-items", "align-content"]; + if (e.prop.includes("flex") || i.includes(e.prop)) return !0; + } + return this.disabled(e, t); + } + disabled(e, t) { + if (!e) return !1; + if (e._autoprefixerDisabled !== void 0) return e._autoprefixerDisabled; + if (e.parent) { + let n = e.prev(); + if (n && n.type === "comment" && vA.test(n.text)) + return ((e._autoprefixerDisabled = !0), (e._autoprefixerSelfDisabled = !0), !0); + } + let i = null; + if (e.nodes) { + let n; + (e.each((a) => { + a.type === "comment" && + /(!\s*)?autoprefixer:\s*(off|on)/i.test(a.text) && + (typeof n != "undefined" + ? t.warn( + "Second Autoprefixer control comment was ignored. Autoprefixer applies control comment to whole block, not to next rules.", + { node: a } + ) + : (n = /on/i.test(a.text))); + }), + n !== void 0 && (i = !n)); + } + if (!e.nodes || i === null) + if (e.parent) { + let n = this.disabled(e.parent, t); + e.parent._autoprefixerSelfDisabled === !0 ? (i = !1) : (i = n); + } else i = !1; + return ((e._autoprefixerDisabled = i), i); + } + reduceSpaces(e) { + let t = !1; + if ((this.prefixes.group(e).up(() => ((t = !0), !0)), t)) return; + let i = e.raw("before").split(` +`), + n = i[i.length - 1].length, + a = !1; + this.prefixes.group(e).down((s) => { + i = s.raw("before").split(` +`); + let o = i.length - 1; + i[o].length > n && + (a === !1 && (a = i[o].length - n), + (i[o] = i[o].slice(0, -a)), + (s.raws.before = i.join(` +`))); + }); + } + displayType(e) { + for (let t of e.parent.nodes) + if (t.prop === "display") { + if (t.value.includes("flex")) return "flex"; + if (t.value.includes("grid")) return "grid"; + } + return !1; + } + gridStatus(e, t) { + if (!e) return !1; + if (e._autoprefixerGridStatus !== void 0) return e._autoprefixerGridStatus; + let i = null; + if (e.nodes) { + let n; + (e.each((a) => { + if (a.type === "comment" && xA.test(a.text)) { + let s = /:\s*autoplace/i.test(a.text), + o = /no-autoplace/i.test(a.text); + typeof n != "undefined" + ? t.warn( + "Second Autoprefixer grid control comment was ignored. Autoprefixer applies control comments to the whole block, not to the next rules.", + { node: a } + ) + : s + ? (n = "autoplace") + : o + ? (n = !0) + : (n = /on/i.test(a.text)); + } + }), + n !== void 0 && (i = n)); + } + if (e.type === "atrule" && e.name === "supports") { + let n = e.params; + n.includes("grid") && n.includes("auto") && (i = !1); + } + if (!e.nodes || i === null) + if (e.parent) { + let n = this.gridStatus(e.parent, t); + e.parent._autoprefixerSelfDisabled === !0 ? (i = !1) : (i = n); + } else + typeof this.prefixes.options.grid != "undefined" + ? (i = this.prefixes.options.grid) + : typeof h.env.AUTOPREFIXER_GRID != "undefined" + ? h.env.AUTOPREFIXER_GRID === "autoplace" + ? (i = "autoplace") + : (i = !0) + : (i = !1); + return ((e._autoprefixerGridStatus = i), i); + } + }; + ug.exports = lg; + }); + var cg = v((jD, fg) => { + l(); + fg.exports = { + A: { + A: { 2: "K E F G A B JC" }, + B: { 1: "C L M H N D O P Q R S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I" }, + C: { + 1: "2 3 4 5 6 7 8 9 AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB 0B dB 1B eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R 2B S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I uB 3B 4B", + 2: "0 1 KC zB J K E F G A B C L M H N D O k l LC MC", + }, + D: { + 1: "8 9 AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB 0B dB 1B eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I uB 3B 4B", + 2: "0 1 2 3 4 5 6 7 J K E F G A B C L M H N D O k l", + }, + E: { + 1: "G A B C L M H D RC 6B vB wB 7B SC TC 8B 9B xB AC yB BC CC DC EC FC GC UC", + 2: "0 J K E F NC 5B OC PC QC", + }, + F: { + 1: "1 2 3 4 5 6 7 8 9 H N D O k l AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R 2B S T U V W X Y Z a b c d e f g h i j wB", + 2: "G B C VC WC XC YC vB HC ZC", + }, + G: { + 1: "D fC gC hC iC jC kC lC mC nC oC pC qC rC sC tC 8B 9B xB AC yB BC CC DC EC FC GC", + 2: "F 5B aC IC bC cC dC eC", + }, + H: { 1: "uC" }, + I: { 1: "I zC 0C", 2: "zB J vC wC xC yC IC" }, + J: { 2: "E A" }, + K: { 1: "m", 2: "A B C vB HC wB" }, + L: { 1: "I" }, + M: { 1: "uB" }, + N: { 2: "A B" }, + O: { 1: "xB" }, + P: { 1: "J k l 1C 2C 3C 4C 5C 6B 6C 7C 8C 9C AD yB BD CD DD" }, + Q: { 1: "7B" }, + R: { 1: "ED" }, + S: { 1: "FD GD" }, + }, + B: 4, + C: "CSS Feature Queries", + }; + }); + var mg = v((VD, hg) => { + l(); + function pg(r) { + return r[r.length - 1]; + } + var dg = { + parse(r) { + let e = [""], + t = [e]; + for (let i of r) { + if (i === "(") { + ((e = [""]), pg(t).push(e), t.push(e)); + continue; + } + if (i === ")") { + (t.pop(), (e = pg(t)), e.push("")); + continue; + } + e[e.length - 1] += i; + } + return t[0]; + }, + stringify(r) { + let e = ""; + for (let t of r) { + if (typeof t == "object") { + e += `(${dg.stringify(t)})`; + continue; + } + e += t; + } + return e; + }, + }; + hg.exports = dg; + }); + var vg = v((UD, bg) => { + l(); + var CA = cg(), + { feature: AA } = (Gn(), Wn), + { parse: _A } = ge(), + OA = dt(), + al = mg(), + EA = ke(), + TA = le(), + gg = AA(CA), + yg = []; + for (let r in gg.stats) { + let e = gg.stats[r]; + for (let t in e) { + let i = e[t]; + /y/.test(i) && yg.push(r + " " + t); + } + } + var wg = class { + constructor(e, t) { + ((this.Prefixes = e), (this.all = t)); + } + prefixer() { + if (this.prefixerCache) return this.prefixerCache; + let e = this.all.browsers.selected.filter((i) => yg.includes(i)), + t = new OA(this.all.browsers.data, e, this.all.options); + return ( + (this.prefixerCache = new this.Prefixes(this.all.data, t, this.all.options)), + this.prefixerCache + ); + } + parse(e) { + let t = e.split(":"), + i = t[0], + n = t[1]; + return (n || (n = ""), [i.trim(), n.trim()]); + } + virtual(e) { + let [t, i] = this.parse(e), + n = _A("a{}").first; + return (n.append({ prop: t, value: i, raws: { before: "" } }), n); + } + prefixed(e) { + let t = this.virtual(e); + if (this.disabled(t.first)) return t.nodes; + let i = { warn: () => null }, + n = this.prefixer().add[t.first.prop]; + n && n.process && n.process(t.first, i); + for (let a of t.nodes) { + for (let s of this.prefixer().values("add", t.first.prop)) s.process(a); + EA.save(this.all, a); + } + return t.nodes; + } + isNot(e) { + return typeof e == "string" && /not\s*/i.test(e); + } + isOr(e) { + return typeof e == "string" && /\s*or\s*/i.test(e); + } + isProp(e) { + return typeof e == "object" && e.length === 1 && typeof e[0] == "string"; + } + isHack(e, t) { + return !new RegExp(`(\\(|\\s)${TA.escapeRegexp(t)}:`).test(e); + } + toRemove(e, t) { + let [i, n] = this.parse(e), + a = this.all.unprefixed(i), + s = this.all.cleaner(); + if (s.remove[i] && s.remove[i].remove && !this.isHack(t, a)) return !0; + for (let o of s.values("remove", a)) if (o.check(n)) return !0; + return !1; + } + remove(e, t) { + let i = 0; + for (; i < e.length; ) { + if (!this.isNot(e[i - 1]) && this.isProp(e[i]) && this.isOr(e[i + 1])) { + if (this.toRemove(e[i][0], t)) { + e.splice(i, 2); + continue; + } + i += 2; + continue; + } + (typeof e[i] == "object" && (e[i] = this.remove(e[i], t)), (i += 1)); + } + return e; + } + cleanBrackets(e) { + return e.map((t) => + typeof t != "object" + ? t + : t.length === 1 && typeof t[0] == "object" + ? this.cleanBrackets(t[0]) + : this.cleanBrackets(t) + ); + } + convert(e) { + let t = [""]; + for (let i of e) (t.push([`${i.prop}: ${i.value}`]), t.push(" or ")); + return ((t[t.length - 1] = ""), t); + } + normalize(e) { + if (typeof e != "object") return e; + if (((e = e.filter((t) => t !== "")), typeof e[0] == "string")) { + let t = e[0].trim(); + if (t.includes(":") || t === "selector" || t === "not selector") return [al.stringify(e)]; + } + return e.map((t) => this.normalize(t)); + } + add(e, t) { + return e.map((i) => { + if (this.isProp(i)) { + let n = this.prefixed(i[0]); + return n.length > 1 ? this.convert(n) : i; + } + return typeof i == "object" ? this.add(i, t) : i; + }); + } + process(e) { + let t = al.parse(e.params); + ((t = this.normalize(t)), + (t = this.remove(t, e.params)), + (t = this.add(t, e.params)), + (t = this.cleanBrackets(t)), + (e.params = al.stringify(t))); + } + disabled(e) { + if ( + !this.all.options.grid && + ((e.prop === "display" && e.value.includes("grid")) || + e.prop.includes("grid") || + e.prop === "justify-items") + ) + return !0; + if (this.all.options.flexbox === !1) { + if (e.prop === "display" && e.value.includes("flex")) return !0; + let t = ["order", "justify-content", "align-items", "align-content"]; + if (e.prop.includes("flex") || t.includes(e.prop)) return !0; + } + return !1; + } + }; + bg.exports = wg; + }); + var Sg = v((WD, kg) => { + l(); + var xg = class { + constructor(e, t) { + ((this.prefix = t), + (this.prefixed = e.prefixed(this.prefix)), + (this.regexp = e.regexp(this.prefix)), + (this.prefixeds = e.possible().map((i) => [e.prefixed(i), e.regexp(i)])), + (this.unprefixed = e.name), + (this.nameRegexp = e.regexp())); + } + isHack(e) { + let t = e.parent.index(e) + 1, + i = e.parent.nodes; + for (; t < i.length; ) { + let n = i[t].selector; + if (!n) return !0; + if (n.includes(this.unprefixed) && n.match(this.nameRegexp)) return !1; + let a = !1; + for (let [s, o] of this.prefixeds) + if (n.includes(s) && n.match(o)) { + a = !0; + break; + } + if (!a) return !0; + t += 1; + } + return !0; + } + check(e) { + return !(!e.selector.includes(this.prefixed) || !e.selector.match(this.regexp) || this.isHack(e)); + } + }; + kg.exports = xg; + }); + var Jt = v((GD, Ag) => { + l(); + var { list: PA } = ge(), + DA = Sg(), + IA = Ht(), + qA = dt(), + RA = le(), + Cg = class extends IA { + constructor(e, t, i) { + super(e, t, i); + this.regexpCache = new Map(); + } + check(e) { + return e.selector.includes(this.name) ? !!e.selector.match(this.regexp()) : !1; + } + prefixed(e) { + return this.name.replace(/^(\W*)/, `$1${e}`); + } + regexp(e) { + if (!this.regexpCache.has(e)) { + let t = e ? this.prefixed(e) : this.name; + this.regexpCache.set(e, new RegExp(`(^|[^:"'=])${RA.escapeRegexp(t)}`, "gi")); + } + return this.regexpCache.get(e); + } + possible() { + return qA.prefixes(); + } + prefixeds(e) { + if (e._autoprefixerPrefixeds) { + if (e._autoprefixerPrefixeds[this.name]) return e._autoprefixerPrefixeds; + } else e._autoprefixerPrefixeds = {}; + let t = {}; + if (e.selector.includes(",")) { + let n = PA.comma(e.selector).filter((a) => a.includes(this.name)); + for (let a of this.possible()) t[a] = n.map((s) => this.replace(s, a)).join(", "); + } else for (let i of this.possible()) t[i] = this.replace(e.selector, i); + return ((e._autoprefixerPrefixeds[this.name] = t), e._autoprefixerPrefixeds); + } + already(e, t, i) { + let n = e.parent.index(e) - 1; + for (; n >= 0; ) { + let a = e.parent.nodes[n]; + if (a.type !== "rule") return !1; + let s = !1; + for (let o in t[this.name]) { + let u = t[this.name][o]; + if (a.selector === u) { + if (i === o) return !0; + s = !0; + break; + } + } + if (!s) return !1; + n -= 1; + } + return !1; + } + replace(e, t) { + return e.replace(this.regexp(), `$1${this.prefixed(t)}`); + } + add(e, t) { + let i = this.prefixeds(e); + if (this.already(e, i, t)) return; + let n = this.clone(e, { selector: i[this.name][t] }); + e.parent.insertBefore(e, n); + } + old(e) { + return new DA(this, e); + } + }; + Ag.exports = Cg; + }); + var Eg = v((HD, Og) => { + l(); + var MA = Ht(), + _g = class extends MA { + add(e, t) { + let i = t + e.name; + if (e.parent.some((s) => s.name === i && s.params === e.params)) return; + let a = this.clone(e, { name: i }); + return e.parent.insertBefore(e, a); + } + process(e) { + let t = this.parentPrefix(e); + for (let i of this.prefixes) (!t || t === i) && this.add(e, i); + } + }; + Og.exports = _g; + }); + var Pg = v((YD, Tg) => { + l(); + var BA = Jt(), + ol = class extends BA { + prefixed(e) { + return e === "-webkit-" + ? ":-webkit-full-screen" + : e === "-moz-" + ? ":-moz-full-screen" + : `:${e}fullscreen`; + } + }; + ol.names = [":fullscreen"]; + Tg.exports = ol; + }); + var Ig = v((QD, Dg) => { + l(); + var FA = Jt(), + ll = class extends FA { + possible() { + return super.possible().concat(["-moz- old", "-ms- old"]); + } + prefixed(e) { + return e === "-webkit-" + ? "::-webkit-input-placeholder" + : e === "-ms-" + ? "::-ms-input-placeholder" + : e === "-ms- old" + ? ":-ms-input-placeholder" + : e === "-moz- old" + ? ":-moz-placeholder" + : `::${e}placeholder`; + } + }; + ll.names = ["::placeholder"]; + Dg.exports = ll; + }); + var Rg = v((JD, qg) => { + l(); + var LA = Jt(), + ul = class extends LA { + prefixed(e) { + return e === "-ms-" ? ":-ms-input-placeholder" : `:${e}placeholder-shown`; + } + }; + ul.names = [":placeholder-shown"]; + qg.exports = ul; + }); + var Bg = v((XD, Mg) => { + l(); + var NA = Jt(), + $A = le(), + fl = class extends NA { + constructor(e, t, i) { + super(e, t, i); + this.prefixes && (this.prefixes = $A.uniq(this.prefixes.map((n) => "-webkit-"))); + } + prefixed(e) { + return e === "-webkit-" ? "::-webkit-file-upload-button" : `::${e}file-selector-button`; + } + }; + fl.names = ["::file-selector-button"]; + Mg.exports = fl; + }); + var pe = v((KD, Fg) => { + l(); + Fg.exports = function (r) { + let e; + return ( + r === "-webkit- 2009" || r === "-moz-" + ? (e = 2009) + : r === "-ms-" + ? (e = 2012) + : r === "-webkit-" && (e = "final"), + r === "-webkit- 2009" && (r = "-webkit-"), + [e, r] + ); + }; + }); + var zg = v((ZD, $g) => { + l(); + var Lg = ge().list, + Ng = pe(), + zA = M(), + Xt = class extends zA { + prefixed(e, t) { + let i; + return (([i, t] = Ng(t)), i === 2009 ? t + "box-flex" : super.prefixed(e, t)); + } + normalize() { + return "flex"; + } + set(e, t) { + let i = Ng(t)[0]; + if (i === 2009) + return ( + (e.value = Lg.space(e.value)[0]), + (e.value = Xt.oldValues[e.value] || e.value), + super.set(e, t) + ); + if (i === 2012) { + let n = Lg.space(e.value); + n.length === 3 && n[2] === "0" && (e.value = n.slice(0, 2).concat("0px").join(" ")); + } + return super.set(e, t); + } + }; + Xt.names = ["flex", "box-flex"]; + Xt.oldValues = { auto: "1", none: "0" }; + $g.exports = Xt; + }); + var Ug = v((eI, Vg) => { + l(); + var jg = pe(), + jA = M(), + cl = class extends jA { + prefixed(e, t) { + let i; + return ( + ([i, t] = jg(t)), + i === 2009 ? t + "box-ordinal-group" : i === 2012 ? t + "flex-order" : super.prefixed(e, t) + ); + } + normalize() { + return "order"; + } + set(e, t) { + return jg(t)[0] === 2009 && /\d/.test(e.value) + ? ((e.value = (parseInt(e.value) + 1).toString()), super.set(e, t)) + : super.set(e, t); + } + }; + cl.names = ["order", "flex-order", "box-ordinal-group"]; + Vg.exports = cl; + }); + var Gg = v((tI, Wg) => { + l(); + var VA = M(), + pl = class extends VA { + check(e) { + let t = e.value; + return ( + !t.toLowerCase().includes("alpha(") && + !t.includes("DXImageTransform.Microsoft") && + !t.includes("data:image/svg+xml") + ); + } + }; + pl.names = ["filter"]; + Wg.exports = pl; + }); + var Yg = v((rI, Hg) => { + l(); + var UA = M(), + dl = class extends UA { + insert(e, t, i, n) { + if (t !== "-ms-") return super.insert(e, t, i); + let a = this.clone(e), + s = e.prop.replace(/end$/, "start"), + o = t + e.prop.replace(/end$/, "span"); + if (!e.parent.some((u) => u.prop === o)) { + if (((a.prop = o), e.value.includes("span"))) a.value = e.value.replace(/span\s/i, ""); + else { + let u; + if ( + (e.parent.walkDecls(s, (c) => { + u = c; + }), + u) + ) { + let c = Number(e.value) - Number(u.value) + ""; + a.value = c; + } else e.warn(n, `Can not prefix ${e.prop} (${s} is not found)`); + } + e.cloneBefore(a); + } + } + }; + dl.names = ["grid-row-end", "grid-column-end"]; + Hg.exports = dl; + }); + var Jg = v((iI, Qg) => { + l(); + var WA = M(), + hl = class extends WA { + check(e) { + return !e.value.split(/\s+/).some((t) => { + let i = t.toLowerCase(); + return i === "reverse" || i === "alternate-reverse"; + }); + } + }; + hl.names = ["animation", "animation-direction"]; + Qg.exports = hl; + }); + var Kg = v((nI, Xg) => { + l(); + var GA = pe(), + HA = M(), + ml = class extends HA { + insert(e, t, i) { + let n; + if ((([n, t] = GA(t)), n !== 2009)) return super.insert(e, t, i); + let a = e.value.split(/\s+/).filter((d) => d !== "wrap" && d !== "nowrap" && "wrap-reverse"); + if ( + a.length === 0 || + e.parent.some((d) => d.prop === t + "box-orient" || d.prop === t + "box-direction") + ) + return; + let o = a[0], + u = o.includes("row") ? "horizontal" : "vertical", + c = o.includes("reverse") ? "reverse" : "normal", + f = this.clone(e); + return ( + (f.prop = t + "box-orient"), + (f.value = u), + this.needCascade(e) && (f.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, f), + (f = this.clone(e)), + (f.prop = t + "box-direction"), + (f.value = c), + this.needCascade(e) && (f.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, f) + ); + } + }; + ml.names = ["flex-flow", "box-direction", "box-orient"]; + Xg.exports = ml; + }); + var ey = v((sI, Zg) => { + l(); + var YA = pe(), + QA = M(), + gl = class extends QA { + normalize() { + return "flex"; + } + prefixed(e, t) { + let i; + return ( + ([i, t] = YA(t)), + i === 2009 ? t + "box-flex" : i === 2012 ? t + "flex-positive" : super.prefixed(e, t) + ); + } + }; + gl.names = ["flex-grow", "flex-positive"]; + Zg.exports = gl; + }); + var ry = v((aI, ty) => { + l(); + var JA = pe(), + XA = M(), + yl = class extends XA { + set(e, t) { + if (JA(t)[0] !== 2009) return super.set(e, t); + } + }; + yl.names = ["flex-wrap"]; + ty.exports = yl; + }); + var ny = v((oI, iy) => { + l(); + var KA = M(), + Kt = mt(), + wl = class extends KA { + insert(e, t, i, n) { + if (t !== "-ms-") return super.insert(e, t, i); + let a = Kt.parse(e), + [s, o] = Kt.translate(a, 0, 2), + [u, c] = Kt.translate(a, 1, 3); + ([ + ["grid-row", s], + ["grid-row-span", o], + ["grid-column", u], + ["grid-column-span", c], + ].forEach(([f, d]) => { + Kt.insertDecl(e, f, d); + }), + Kt.warnTemplateSelectorNotFound(e, n), + Kt.warnIfGridRowColumnExists(e, n)); + } + }; + wl.names = ["grid-area"]; + iy.exports = wl; + }); + var ay = v((lI, sy) => { + l(); + var ZA = M(), + oi = mt(), + bl = class extends ZA { + insert(e, t, i) { + if (t !== "-ms-") return super.insert(e, t, i); + if (e.parent.some((s) => s.prop === "-ms-grid-row-align")) return; + let [[n, a]] = oi.parse(e); + a + ? (oi.insertDecl(e, "grid-row-align", n), oi.insertDecl(e, "grid-column-align", a)) + : (oi.insertDecl(e, "grid-row-align", n), oi.insertDecl(e, "grid-column-align", n)); + } + }; + bl.names = ["place-self"]; + sy.exports = bl; + }); + var ly = v((uI, oy) => { + l(); + var e5 = M(), + vl = class extends e5 { + check(e) { + let t = e.value; + return !t.includes("/") || t.includes("span"); + } + normalize(e) { + return e.replace("-start", ""); + } + prefixed(e, t) { + let i = super.prefixed(e, t); + return (t === "-ms-" && (i = i.replace("-start", "")), i); + } + }; + vl.names = ["grid-row-start", "grid-column-start"]; + oy.exports = vl; + }); + var cy = v((fI, fy) => { + l(); + var uy = pe(), + t5 = M(), + Zt = class extends t5 { + check(e) { + return e.parent && !e.parent.some((t) => t.prop && t.prop.startsWith("grid-")); + } + prefixed(e, t) { + let i; + return (([i, t] = uy(t)), i === 2012 ? t + "flex-item-align" : super.prefixed(e, t)); + } + normalize() { + return "align-self"; + } + set(e, t) { + let i = uy(t)[0]; + if (i === 2012) return ((e.value = Zt.oldValues[e.value] || e.value), super.set(e, t)); + if (i === "final") return super.set(e, t); + } + }; + Zt.names = ["align-self", "flex-item-align"]; + Zt.oldValues = { "flex-end": "end", "flex-start": "start" }; + fy.exports = Zt; + }); + var dy = v((cI, py) => { + l(); + var r5 = M(), + i5 = le(), + xl = class extends r5 { + constructor(e, t, i) { + super(e, t, i); + this.prefixes && + (this.prefixes = i5.uniq(this.prefixes.map((n) => (n === "-ms-" ? "-webkit-" : n)))); + } + }; + xl.names = ["appearance"]; + py.exports = xl; + }); + var gy = v((pI, my) => { + l(); + var hy = pe(), + n5 = M(), + kl = class extends n5 { + normalize() { + return "flex-basis"; + } + prefixed(e, t) { + let i; + return (([i, t] = hy(t)), i === 2012 ? t + "flex-preferred-size" : super.prefixed(e, t)); + } + set(e, t) { + let i; + if ((([i, t] = hy(t)), i === 2012 || i === "final")) return super.set(e, t); + } + }; + kl.names = ["flex-basis", "flex-preferred-size"]; + my.exports = kl; + }); + var wy = v((dI, yy) => { + l(); + var s5 = M(), + Sl = class extends s5 { + normalize() { + return this.name.replace("box-image", "border"); + } + prefixed(e, t) { + let i = super.prefixed(e, t); + return (t === "-webkit-" && (i = i.replace("border", "box-image")), i); + } + }; + Sl.names = [ + "mask-border", + "mask-border-source", + "mask-border-slice", + "mask-border-width", + "mask-border-outset", + "mask-border-repeat", + "mask-box-image", + "mask-box-image-source", + "mask-box-image-slice", + "mask-box-image-width", + "mask-box-image-outset", + "mask-box-image-repeat", + ]; + yy.exports = Sl; + }); + var vy = v((hI, by) => { + l(); + var a5 = M(), + Ne = class extends a5 { + insert(e, t, i) { + let n = e.prop === "mask-composite", + a; + (n ? (a = e.value.split(",")) : (a = e.value.match(Ne.regexp) || []), + (a = a.map((c) => c.trim()).filter((c) => c))); + let s = a.length, + o; + if ( + (s && + ((o = this.clone(e)), + (o.value = a.map((c) => Ne.oldValues[c] || c).join(", ")), + a.includes("intersect") && (o.value += ", xor"), + (o.prop = t + "mask-composite")), + n) + ) + return s + ? (this.needCascade(e) && (o.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, o)) + : void 0; + let u = this.clone(e); + return ( + (u.prop = t + u.prop), + s && (u.value = u.value.replace(Ne.regexp, "")), + this.needCascade(e) && (u.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, u), + s + ? (this.needCascade(e) && (o.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, o)) + : e + ); + } + }; + Ne.names = ["mask", "mask-composite"]; + Ne.oldValues = { add: "source-over", subtract: "source-out", intersect: "source-in", exclude: "xor" }; + Ne.regexp = new RegExp(`\\s+(${Object.keys(Ne.oldValues).join("|")})\\b(?!\\))\\s*(?=[,])`, "ig"); + by.exports = Ne; + }); + var Sy = v((mI, ky) => { + l(); + var xy = pe(), + o5 = M(), + er = class extends o5 { + prefixed(e, t) { + let i; + return ( + ([i, t] = xy(t)), + i === 2009 ? t + "box-align" : i === 2012 ? t + "flex-align" : super.prefixed(e, t) + ); + } + normalize() { + return "align-items"; + } + set(e, t) { + let i = xy(t)[0]; + return ( + (i === 2009 || i === 2012) && (e.value = er.oldValues[e.value] || e.value), + super.set(e, t) + ); + } + }; + er.names = ["align-items", "flex-align", "box-align"]; + er.oldValues = { "flex-end": "end", "flex-start": "start" }; + ky.exports = er; + }); + var Ay = v((gI, Cy) => { + l(); + var l5 = M(), + Cl = class extends l5 { + set(e, t) { + return (t === "-ms-" && e.value === "contain" && (e.value = "element"), super.set(e, t)); + } + insert(e, t, i) { + if (!(e.value === "all" && t === "-ms-")) return super.insert(e, t, i); + } + }; + Cl.names = ["user-select"]; + Cy.exports = Cl; + }); + var Ey = v((yI, Oy) => { + l(); + var _y = pe(), + u5 = M(), + Al = class extends u5 { + normalize() { + return "flex-shrink"; + } + prefixed(e, t) { + let i; + return (([i, t] = _y(t)), i === 2012 ? t + "flex-negative" : super.prefixed(e, t)); + } + set(e, t) { + let i; + if ((([i, t] = _y(t)), i === 2012 || i === "final")) return super.set(e, t); + } + }; + Al.names = ["flex-shrink", "flex-negative"]; + Oy.exports = Al; + }); + var Py = v((wI, Ty) => { + l(); + var f5 = M(), + _l = class extends f5 { + prefixed(e, t) { + return `${t}column-${e}`; + } + normalize(e) { + return e.includes("inside") + ? "break-inside" + : e.includes("before") + ? "break-before" + : "break-after"; + } + set(e, t) { + return ( + ((e.prop === "break-inside" && e.value === "avoid-column") || e.value === "avoid-page") && + (e.value = "avoid"), + super.set(e, t) + ); + } + insert(e, t, i) { + if (e.prop !== "break-inside") return super.insert(e, t, i); + if (!(/region/i.test(e.value) || /page/i.test(e.value))) return super.insert(e, t, i); + } + }; + _l.names = [ + "break-inside", + "page-break-inside", + "column-break-inside", + "break-before", + "page-break-before", + "column-break-before", + "break-after", + "page-break-after", + "column-break-after", + ]; + Ty.exports = _l; + }); + var Iy = v((bI, Dy) => { + l(); + var c5 = M(), + Ol = class extends c5 { + prefixed(e, t) { + return t + "print-color-adjust"; + } + normalize() { + return "color-adjust"; + } + }; + Ol.names = ["color-adjust", "print-color-adjust"]; + Dy.exports = Ol; + }); + var Ry = v((vI, qy) => { + l(); + var p5 = M(), + tr = class extends p5 { + insert(e, t, i) { + if (t === "-ms-") { + let n = this.set(this.clone(e), t); + this.needCascade(e) && (n.raws.before = this.calcBefore(i, e, t)); + let a = "ltr"; + return ( + e.parent.nodes.forEach((s) => { + s.prop === "direction" && (s.value === "rtl" || s.value === "ltr") && (a = s.value); + }), + (n.value = tr.msValues[a][e.value] || e.value), + e.parent.insertBefore(e, n) + ); + } + return super.insert(e, t, i); + } + }; + tr.names = ["writing-mode"]; + tr.msValues = { + ltr: { "horizontal-tb": "lr-tb", "vertical-rl": "tb-rl", "vertical-lr": "tb-lr" }, + rtl: { "horizontal-tb": "rl-tb", "vertical-rl": "bt-rl", "vertical-lr": "bt-lr" }, + }; + qy.exports = tr; + }); + var By = v((xI, My) => { + l(); + var d5 = M(), + El = class extends d5 { + set(e, t) { + return ((e.value = e.value.replace(/\s+fill(\s)/, "$1")), super.set(e, t)); + } + }; + El.names = ["border-image"]; + My.exports = El; + }); + var Ny = v((kI, Ly) => { + l(); + var Fy = pe(), + h5 = M(), + rr = class extends h5 { + prefixed(e, t) { + let i; + return (([i, t] = Fy(t)), i === 2012 ? t + "flex-line-pack" : super.prefixed(e, t)); + } + normalize() { + return "align-content"; + } + set(e, t) { + let i = Fy(t)[0]; + if (i === 2012) return ((e.value = rr.oldValues[e.value] || e.value), super.set(e, t)); + if (i === "final") return super.set(e, t); + } + }; + rr.names = ["align-content", "flex-line-pack"]; + rr.oldValues = { + "flex-end": "end", + "flex-start": "start", + "space-between": "justify", + "space-around": "distribute", + }; + Ly.exports = rr; + }); + var zy = v((SI, $y) => { + l(); + var m5 = M(), + Se = class extends m5 { + prefixed(e, t) { + return t === "-moz-" ? t + (Se.toMozilla[e] || e) : super.prefixed(e, t); + } + normalize(e) { + return Se.toNormal[e] || e; + } + }; + Se.names = ["border-radius"]; + Se.toMozilla = {}; + Se.toNormal = {}; + for (let r of ["top", "bottom"]) + for (let e of ["left", "right"]) { + let t = `border-${r}-${e}-radius`, + i = `border-radius-${r}${e}`; + (Se.names.push(t), Se.names.push(i), (Se.toMozilla[t] = i), (Se.toNormal[i] = t)); + } + $y.exports = Se; + }); + var Vy = v((CI, jy) => { + l(); + var g5 = M(), + Tl = class extends g5 { + prefixed(e, t) { + return e.includes("-start") + ? t + e.replace("-block-start", "-before") + : t + e.replace("-block-end", "-after"); + } + normalize(e) { + return e.includes("-before") + ? e.replace("-before", "-block-start") + : e.replace("-after", "-block-end"); + } + }; + Tl.names = [ + "border-block-start", + "border-block-end", + "margin-block-start", + "margin-block-end", + "padding-block-start", + "padding-block-end", + "border-before", + "border-after", + "margin-before", + "margin-after", + "padding-before", + "padding-after", + ]; + jy.exports = Tl; + }); + var Wy = v((AI, Uy) => { + l(); + var y5 = M(), + { parseTemplate: w5, warnMissedAreas: b5, getGridGap: v5, warnGridGap: x5, inheritGridGap: k5 } = mt(), + Pl = class extends y5 { + insert(e, t, i, n) { + if (t !== "-ms-") return super.insert(e, t, i); + if (e.parent.some((m) => m.prop === "-ms-grid-rows")) return; + let a = v5(e), + s = k5(e, a), + { rows: o, columns: u, areas: c } = w5({ decl: e, gap: s || a }), + f = Object.keys(c).length > 0, + d = Boolean(o), + p = Boolean(u); + return ( + x5({ gap: a, hasColumns: p, decl: e, result: n }), + b5(c, e, n), + ((d && p) || f) && e.cloneBefore({ prop: "-ms-grid-rows", value: o, raws: {} }), + p && e.cloneBefore({ prop: "-ms-grid-columns", value: u, raws: {} }), + e + ); + } + }; + Pl.names = ["grid-template"]; + Uy.exports = Pl; + }); + var Hy = v((_I, Gy) => { + l(); + var S5 = M(), + Dl = class extends S5 { + prefixed(e, t) { + return t + e.replace("-inline", ""); + } + normalize(e) { + return e.replace(/(margin|padding|border)-(start|end)/, "$1-inline-$2"); + } + }; + Dl.names = [ + "border-inline-start", + "border-inline-end", + "margin-inline-start", + "margin-inline-end", + "padding-inline-start", + "padding-inline-end", + "border-start", + "border-end", + "margin-start", + "margin-end", + "padding-start", + "padding-end", + ]; + Gy.exports = Dl; + }); + var Qy = v((OI, Yy) => { + l(); + var C5 = M(), + Il = class extends C5 { + check(e) { + return !e.value.includes("flex-") && e.value !== "baseline"; + } + prefixed(e, t) { + return t + "grid-row-align"; + } + normalize() { + return "align-self"; + } + }; + Il.names = ["grid-row-align"]; + Yy.exports = Il; + }); + var Xy = v((EI, Jy) => { + l(); + var A5 = M(), + ir = class extends A5 { + keyframeParents(e) { + let { parent: t } = e; + for (; t; ) { + if (t.type === "atrule" && t.name === "keyframes") return !0; + ({ parent: t } = t); + } + return !1; + } + contain3d(e) { + if (e.prop === "transform-origin") return !1; + for (let t of ir.functions3d) if (e.value.includes(`${t}(`)) return !0; + return !1; + } + set(e, t) { + return ( + (e = super.set(e, t)), + t === "-ms-" && (e.value = e.value.replace(/rotatez/gi, "rotate")), + e + ); + } + insert(e, t, i) { + if (t === "-ms-") { + if (!this.contain3d(e) && !this.keyframeParents(e)) return super.insert(e, t, i); + } else if (t === "-o-") { + if (!this.contain3d(e)) return super.insert(e, t, i); + } else return super.insert(e, t, i); + } + }; + ir.names = ["transform", "transform-origin"]; + ir.functions3d = [ + "matrix3d", + "translate3d", + "translateZ", + "scale3d", + "scaleZ", + "rotate3d", + "rotateX", + "rotateY", + "perspective", + ]; + Jy.exports = ir; + }); + var ew = v((TI, Zy) => { + l(); + var Ky = pe(), + _5 = M(), + ql = class extends _5 { + normalize() { + return "flex-direction"; + } + insert(e, t, i) { + let n; + if ((([n, t] = Ky(t)), n !== 2009)) return super.insert(e, t, i); + if (e.parent.some((f) => f.prop === t + "box-orient" || f.prop === t + "box-direction")) return; + let s = e.value, + o, + u; + s === "inherit" || s === "initial" || s === "unset" + ? ((o = s), (u = s)) + : ((o = s.includes("row") ? "horizontal" : "vertical"), + (u = s.includes("reverse") ? "reverse" : "normal")); + let c = this.clone(e); + return ( + (c.prop = t + "box-orient"), + (c.value = o), + this.needCascade(e) && (c.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, c), + (c = this.clone(e)), + (c.prop = t + "box-direction"), + (c.value = u), + this.needCascade(e) && (c.raws.before = this.calcBefore(i, e, t)), + e.parent.insertBefore(e, c) + ); + } + old(e, t) { + let i; + return (([i, t] = Ky(t)), i === 2009 ? [t + "box-orient", t + "box-direction"] : super.old(e, t)); + } + }; + ql.names = ["flex-direction", "box-direction", "box-orient"]; + Zy.exports = ql; + }); + var rw = v((PI, tw) => { + l(); + var O5 = M(), + Rl = class extends O5 { + check(e) { + return e.value === "pixelated"; + } + prefixed(e, t) { + return t === "-ms-" ? "-ms-interpolation-mode" : super.prefixed(e, t); + } + set(e, t) { + return t !== "-ms-" + ? super.set(e, t) + : ((e.prop = "-ms-interpolation-mode"), (e.value = "nearest-neighbor"), e); + } + normalize() { + return "image-rendering"; + } + process(e, t) { + return super.process(e, t); + } + }; + Rl.names = ["image-rendering", "interpolation-mode"]; + tw.exports = Rl; + }); + var nw = v((DI, iw) => { + l(); + var E5 = M(), + T5 = le(), + Ml = class extends E5 { + constructor(e, t, i) { + super(e, t, i); + this.prefixes && + (this.prefixes = T5.uniq(this.prefixes.map((n) => (n === "-ms-" ? "-webkit-" : n)))); + } + }; + Ml.names = ["backdrop-filter"]; + iw.exports = Ml; + }); + var aw = v((II, sw) => { + l(); + var P5 = M(), + D5 = le(), + Bl = class extends P5 { + constructor(e, t, i) { + super(e, t, i); + this.prefixes && + (this.prefixes = D5.uniq(this.prefixes.map((n) => (n === "-ms-" ? "-webkit-" : n)))); + } + check(e) { + return e.value.toLowerCase() === "text"; + } + }; + Bl.names = ["background-clip"]; + sw.exports = Bl; + }); + var lw = v((qI, ow) => { + l(); + var I5 = M(), + q5 = ["none", "underline", "overline", "line-through", "blink", "inherit", "initial", "unset"], + Fl = class extends I5 { + check(e) { + return e.value.split(/\s+/).some((t) => !q5.includes(t)); + } + }; + Fl.names = ["text-decoration"]; + ow.exports = Fl; + }); + var cw = v((RI, fw) => { + l(); + var uw = pe(), + R5 = M(), + nr = class extends R5 { + prefixed(e, t) { + let i; + return ( + ([i, t] = uw(t)), + i === 2009 ? t + "box-pack" : i === 2012 ? t + "flex-pack" : super.prefixed(e, t) + ); + } + normalize() { + return "justify-content"; + } + set(e, t) { + let i = uw(t)[0]; + if (i === 2009 || i === 2012) { + let n = nr.oldValues[e.value] || e.value; + if (((e.value = n), i !== 2009 || n !== "distribute")) return super.set(e, t); + } else if (i === "final") return super.set(e, t); + } + }; + nr.names = ["justify-content", "flex-pack", "box-pack"]; + nr.oldValues = { + "flex-end": "end", + "flex-start": "start", + "space-between": "justify", + "space-around": "distribute", + }; + fw.exports = nr; + }); + var dw = v((MI, pw) => { + l(); + var M5 = M(), + Ll = class extends M5 { + set(e, t) { + let i = e.value.toLowerCase(); + return ( + t === "-webkit-" && + !i.includes(" ") && + i !== "contain" && + i !== "cover" && + (e.value = e.value + " " + e.value), + super.set(e, t) + ); + } + }; + Ll.names = ["background-size"]; + pw.exports = Ll; + }); + var mw = v((BI, hw) => { + l(); + var B5 = M(), + Nl = mt(), + $l = class extends B5 { + insert(e, t, i) { + if (t !== "-ms-") return super.insert(e, t, i); + let n = Nl.parse(e), + [a, s] = Nl.translate(n, 0, 1); + (n[0] && n[0].includes("span") && (s = n[0].join("").replace(/\D/g, "")), + [ + [e.prop, a], + [`${e.prop}-span`, s], + ].forEach(([u, c]) => { + Nl.insertDecl(e, u, c); + })); + } + }; + $l.names = ["grid-row", "grid-column"]; + hw.exports = $l; + }); + var ww = v((FI, yw) => { + l(); + var F5 = M(), + { + prefixTrackProp: gw, + prefixTrackValue: L5, + autoplaceGridItems: N5, + getGridGap: $5, + inheritGridGap: z5, + } = mt(), + j5 = sl(), + zl = class extends F5 { + prefixed(e, t) { + return t === "-ms-" ? gw({ prop: e, prefix: t }) : super.prefixed(e, t); + } + normalize(e) { + return e.replace(/^grid-(rows|columns)/, "grid-template-$1"); + } + insert(e, t, i, n) { + if (t !== "-ms-") return super.insert(e, t, i); + let { parent: a, prop: s, value: o } = e, + u = s.includes("rows"), + c = s.includes("columns"), + f = a.some((k) => k.prop === "grid-template" || k.prop === "grid-template-areas"); + if (f && u) return !1; + let d = new j5({ options: {} }), + p = d.gridStatus(a, n), + m = $5(e); + m = z5(e, m) || m; + let b = u ? m.row : m.column; + (p === "no-autoplace" || p === !0) && !f && (b = null); + let x = L5({ value: o, gap: b }); + e.cloneBefore({ prop: gw({ prop: s, prefix: t }), value: x }); + let y = a.nodes.find((k) => k.prop === "grid-auto-flow"), + w = "row"; + if ((y && !d.disabled(y, n) && (w = y.value.trim()), p === "autoplace")) { + let k = a.nodes.find((_) => _.prop === "grid-template-rows"); + if (!k && f) return; + if (!k && !f) { + e.warn(n, "Autoplacement does not work without grid-template-rows property"); + return; + } + (!a.nodes.find((_) => _.prop === "grid-template-columns") && + !f && + e.warn(n, "Autoplacement does not work without grid-template-columns property"), + c && !f && N5(e, n, m, w)); + } + } + }; + zl.names = ["grid-template-rows", "grid-template-columns", "grid-rows", "grid-columns"]; + yw.exports = zl; + }); + var vw = v((LI, bw) => { + l(); + var V5 = M(), + jl = class extends V5 { + check(e) { + return !e.value.includes("flex-") && e.value !== "baseline"; + } + prefixed(e, t) { + return t + "grid-column-align"; + } + normalize() { + return "justify-self"; + } + }; + jl.names = ["grid-column-align"]; + bw.exports = jl; + }); + var kw = v((NI, xw) => { + l(); + var U5 = M(), + Vl = class extends U5 { + prefixed(e, t) { + return t + "scroll-chaining"; + } + normalize() { + return "overscroll-behavior"; + } + set(e, t) { + return ( + e.value === "auto" + ? (e.value = "chained") + : (e.value === "none" || e.value === "contain") && (e.value = "none"), + super.set(e, t) + ); + } + }; + Vl.names = ["overscroll-behavior", "scroll-chaining"]; + xw.exports = Vl; + }); + var Aw = v(($I, Cw) => { + l(); + var W5 = M(), + { + parseGridAreas: G5, + warnMissedAreas: H5, + prefixTrackProp: Y5, + prefixTrackValue: Sw, + getGridGap: Q5, + warnGridGap: J5, + inheritGridGap: X5, + } = mt(); + function K5(r) { + return r + .trim() + .slice(1, -1) + .split(/["']\s*["']?/g); + } + var Ul = class extends W5 { + insert(e, t, i, n) { + if (t !== "-ms-") return super.insert(e, t, i); + let a = !1, + s = !1, + o = e.parent, + u = Q5(e); + ((u = X5(e, u) || u), + o.walkDecls(/-ms-grid-rows/, (d) => d.remove()), + o.walkDecls(/grid-template-(rows|columns)/, (d) => { + if (d.prop === "grid-template-rows") { + s = !0; + let { prop: p, value: m } = d; + d.cloneBefore({ prop: Y5({ prop: p, prefix: t }), value: Sw({ value: m, gap: u.row }) }); + } else a = !0; + })); + let c = K5(e.value); + (a && + !s && + u.row && + c.length > 1 && + e.cloneBefore({ + prop: "-ms-grid-rows", + value: Sw({ value: `repeat(${c.length}, auto)`, gap: u.row }), + raws: {}, + }), + J5({ gap: u, hasColumns: a, decl: e, result: n })); + let f = G5({ rows: c, gap: u }); + return (H5(f, e, n), e); + } + }; + Ul.names = ["grid-template-areas"]; + Cw.exports = Ul; + }); + var Ow = v((zI, _w) => { + l(); + var Z5 = M(), + Wl = class extends Z5 { + set(e, t) { + return ( + t === "-webkit-" && (e.value = e.value.replace(/\s*(right|left)\s*/i, "")), + super.set(e, t) + ); + } + }; + Wl.names = ["text-emphasis-position"]; + _w.exports = Wl; + }); + var Tw = v((jI, Ew) => { + l(); + var e_ = M(), + Gl = class extends e_ { + set(e, t) { + return e.prop === "text-decoration-skip-ink" && e.value === "auto" + ? ((e.prop = t + "text-decoration-skip"), (e.value = "ink"), e) + : super.set(e, t); + } + }; + Gl.names = ["text-decoration-skip-ink", "text-decoration-skip"]; + Ew.exports = Gl; + }); + var Mw = v((VI, Rw) => { + l(); + ("use strict"); + Rw.exports = { wrap: Pw, limit: Dw, validate: Iw, test: Hl, curry: t_, name: qw }; + function Pw(r, e, t) { + var i = e - r; + return ((((t - r) % i) + i) % i) + r; + } + function Dw(r, e, t) { + return Math.max(r, Math.min(e, t)); + } + function Iw(r, e, t, i, n) { + if (!Hl(r, e, t, i, n)) throw new Error(t + " is outside of range [" + r + "," + e + ")"); + return t; + } + function Hl(r, e, t, i, n) { + return !(t < r || t > e || (n && t === e) || (i && t === r)); + } + function qw(r, e, t, i) { + return (t ? "(" : "[") + r + "," + e + (i ? ")" : "]"); + } + function t_(r, e, t, i) { + var n = qw.bind(null, r, e, t, i); + return { + wrap: Pw.bind(null, r, e), + limit: Dw.bind(null, r, e), + validate: function (a) { + return Iw(r, e, a, t, i); + }, + test: function (a) { + return Hl(r, e, a, t, i); + }, + toString: n, + name: n, + }; + } + }); + var Lw = v((UI, Fw) => { + l(); + var Yl = Kn(), + r_ = Mw(), + i_ = Qt(), + n_ = ke(), + s_ = le(), + Bw = /top|left|right|bottom/gi, + Qe = class extends n_ { + replace(e, t) { + let i = Yl(e); + for (let n of i.nodes) + if (n.type === "function" && n.value === this.name) + if ( + ((n.nodes = this.newDirection(n.nodes)), + (n.nodes = this.normalize(n.nodes)), + t === "-webkit- old") + ) { + if (!this.oldWebkit(n)) return !1; + } else ((n.nodes = this.convertDirection(n.nodes)), (n.value = t + n.value)); + return i.toString(); + } + replaceFirst(e, ...t) { + return t + .map((n) => (n === " " ? { type: "space", value: n } : { type: "word", value: n })) + .concat(e.slice(1)); + } + normalizeUnit(e, t) { + return `${(parseFloat(e) / t) * 360}deg`; + } + normalize(e) { + if (!e[0]) return e; + if (/-?\d+(.\d+)?grad/.test(e[0].value)) e[0].value = this.normalizeUnit(e[0].value, 400); + else if (/-?\d+(.\d+)?rad/.test(e[0].value)) + e[0].value = this.normalizeUnit(e[0].value, 2 * Math.PI); + else if (/-?\d+(.\d+)?turn/.test(e[0].value)) e[0].value = this.normalizeUnit(e[0].value, 1); + else if (e[0].value.includes("deg")) { + let t = parseFloat(e[0].value); + ((t = r_.wrap(0, 360, t)), (e[0].value = `${t}deg`)); + } + return ( + e[0].value === "0deg" + ? (e = this.replaceFirst(e, "to", " ", "top")) + : e[0].value === "90deg" + ? (e = this.replaceFirst(e, "to", " ", "right")) + : e[0].value === "180deg" + ? (e = this.replaceFirst(e, "to", " ", "bottom")) + : e[0].value === "270deg" && (e = this.replaceFirst(e, "to", " ", "left")), + e + ); + } + newDirection(e) { + if (e[0].value === "to" || ((Bw.lastIndex = 0), !Bw.test(e[0].value))) return e; + e.unshift({ type: "word", value: "to" }, { type: "space", value: " " }); + for (let t = 2; t < e.length && e[t].type !== "div"; t++) + e[t].type === "word" && (e[t].value = this.revertDirection(e[t].value)); + return e; + } + isRadial(e) { + let t = "before"; + for (let i of e) + if (t === "before" && i.type === "space") t = "at"; + else if (t === "at" && i.value === "at") t = "after"; + else { + if (t === "after" && i.type === "space") return !0; + if (i.type === "div") break; + t = "before"; + } + return !1; + } + convertDirection(e) { + return ( + e.length > 0 && + (e[0].value === "to" + ? this.fixDirection(e) + : e[0].value.includes("deg") + ? this.fixAngle(e) + : this.isRadial(e) && this.fixRadial(e)), + e + ); + } + fixDirection(e) { + e.splice(0, 2); + for (let t of e) { + if (t.type === "div") break; + t.type === "word" && (t.value = this.revertDirection(t.value)); + } + } + fixAngle(e) { + let t = e[0].value; + ((t = parseFloat(t)), + (t = Math.abs(450 - t) % 360), + (t = this.roundFloat(t, 3)), + (e[0].value = `${t}deg`)); + } + fixRadial(e) { + let t = [], + i = [], + n, + a, + s, + o, + u; + for (o = 0; o < e.length - 2; o++) + if ( + ((n = e[o]), + (a = e[o + 1]), + (s = e[o + 2]), + n.type === "space" && a.value === "at" && s.type === "space") + ) { + u = o + 3; + break; + } else t.push(n); + let c; + for (o = u; o < e.length; o++) + if (e[o].type === "div") { + c = e[o]; + break; + } else i.push(e[o]); + e.splice(0, o, ...i, c, ...t); + } + revertDirection(e) { + return Qe.directions[e.toLowerCase()] || e; + } + roundFloat(e, t) { + return parseFloat(e.toFixed(t)); + } + oldWebkit(e) { + let { nodes: t } = e, + i = Yl.stringify(e.nodes); + if ( + this.name !== "linear-gradient" || + (t[0] && t[0].value.includes("deg")) || + i.includes("px") || + i.includes("-corner") || + i.includes("-side") + ) + return !1; + let n = [[]]; + for (let a of t) (n[n.length - 1].push(a), a.type === "div" && a.value === "," && n.push([])); + (this.oldDirection(n), this.colorStops(n), (e.nodes = [])); + for (let a of n) e.nodes = e.nodes.concat(a); + return ( + e.nodes.unshift({ type: "word", value: "linear" }, this.cloneDiv(e.nodes)), + (e.value = "-webkit-gradient"), + !0 + ); + } + oldDirection(e) { + let t = this.cloneDiv(e[0]); + if (e[0][0].value !== "to") return e.unshift([{ type: "word", value: Qe.oldDirections.bottom }, t]); + { + let i = []; + for (let a of e[0].slice(2)) a.type === "word" && i.push(a.value.toLowerCase()); + i = i.join(" "); + let n = Qe.oldDirections[i] || i; + return ((e[0] = [{ type: "word", value: n }, t]), e[0]); + } + } + cloneDiv(e) { + for (let t of e) if (t.type === "div" && t.value === ",") return t; + return { type: "div", value: ",", after: " " }; + } + colorStops(e) { + let t = []; + for (let i = 0; i < e.length; i++) { + let n, + a = e[i], + s; + if (i === 0) continue; + let o = Yl.stringify(a[0]); + a[1] && a[1].type === "word" + ? (n = a[1].value) + : a[2] && a[2].type === "word" && (n = a[2].value); + let u; + i === 1 && (!n || n === "0%") + ? (u = `from(${o})`) + : i === e.length - 1 && (!n || n === "100%") + ? (u = `to(${o})`) + : n + ? (u = `color-stop(${n}, ${o})`) + : (u = `color-stop(${o})`); + let c = a[a.length - 1]; + ((e[i] = [{ type: "word", value: u }]), + c.type === "div" && c.value === "," && (s = e[i].push(c)), + t.push(s)); + } + return t; + } + old(e) { + if (e === "-webkit-") { + let t = this.name === "linear-gradient" ? "linear" : "radial", + i = "-gradient", + n = s_.regexp(`-webkit-(${t}-gradient|gradient\\(\\s*${t})`, !1); + return new i_(this.name, e + this.name, i, n); + } else return super.old(e); + } + add(e, t) { + let i = e.prop; + if (i.includes("mask")) { + if (t === "-webkit-" || t === "-webkit- old") return super.add(e, t); + } else if (i === "list-style" || i === "list-style-image" || i === "content") { + if (t === "-webkit-" || t === "-webkit- old") return super.add(e, t); + } else return super.add(e, t); + } + }; + Qe.names = ["linear-gradient", "repeating-linear-gradient", "radial-gradient", "repeating-radial-gradient"]; + Qe.directions = { top: "bottom", left: "right", bottom: "top", right: "left" }; + Qe.oldDirections = { + top: "left bottom, left top", + left: "right top, left top", + bottom: "left top, left bottom", + right: "left top, right top", + "top right": "left bottom, right top", + "top left": "right bottom, left top", + "right top": "left bottom, right top", + "right bottom": "left top, right bottom", + "bottom right": "left top, right bottom", + "bottom left": "right top, left bottom", + "left top": "right bottom, left top", + "left bottom": "right top, left bottom", + }; + Fw.exports = Qe; + }); + var zw = v((WI, $w) => { + l(); + var a_ = Qt(), + o_ = ke(); + function Nw(r) { + return new RegExp(`(^|[\\s,(])(${r}($|[\\s),]))`, "gi"); + } + var Ql = class extends o_ { + regexp() { + return (this.regexpCache || (this.regexpCache = Nw(this.name)), this.regexpCache); + } + isStretch() { + return this.name === "stretch" || this.name === "fill" || this.name === "fill-available"; + } + replace(e, t) { + return t === "-moz-" && this.isStretch() + ? e.replace(this.regexp(), "$1-moz-available$3") + : t === "-webkit-" && this.isStretch() + ? e.replace(this.regexp(), "$1-webkit-fill-available$3") + : super.replace(e, t); + } + old(e) { + let t = e + this.name; + return ( + this.isStretch() && + (e === "-moz-" ? (t = "-moz-available") : e === "-webkit-" && (t = "-webkit-fill-available")), + new a_(this.name, t, t, Nw(t)) + ); + } + add(e, t) { + if (!(e.prop.includes("grid") && t !== "-webkit-")) return super.add(e, t); + } + }; + Ql.names = ["max-content", "min-content", "fit-content", "fill", "fill-available", "stretch"]; + $w.exports = Ql; + }); + var Uw = v((GI, Vw) => { + l(); + var jw = Qt(), + l_ = ke(), + Jl = class extends l_ { + replace(e, t) { + return t === "-webkit-" + ? e.replace(this.regexp(), "$1-webkit-optimize-contrast") + : t === "-moz-" + ? e.replace(this.regexp(), "$1-moz-crisp-edges") + : super.replace(e, t); + } + old(e) { + return e === "-webkit-" + ? new jw(this.name, "-webkit-optimize-contrast") + : e === "-moz-" + ? new jw(this.name, "-moz-crisp-edges") + : super.old(e); + } + }; + Jl.names = ["pixelated"]; + Vw.exports = Jl; + }); + var Gw = v((HI, Ww) => { + l(); + var u_ = ke(), + Xl = class extends u_ { + replace(e, t) { + let i = super.replace(e, t); + return (t === "-webkit-" && (i = i.replace(/("[^"]+"|'[^']+')(\s+\d+\w)/gi, "url($1)$2")), i); + } + }; + Xl.names = ["image-set"]; + Ww.exports = Xl; + }); + var Yw = v((YI, Hw) => { + l(); + var f_ = ge().list, + c_ = ke(), + Kl = class extends c_ { + replace(e, t) { + return f_ + .space(e) + .map((i) => { + if (i.slice(0, +this.name.length + 1) !== this.name + "(") return i; + let n = i.lastIndexOf(")"), + a = i.slice(n + 1), + s = i.slice(this.name.length + 1, n); + if (t === "-webkit-") { + let o = s.match(/\d*.?\d+%?/); + o ? ((s = s.slice(o[0].length).trim()), (s += `, ${o[0]}`)) : (s += ", 0.5"); + } + return t + this.name + "(" + s + ")" + a; + }) + .join(" "); + } + }; + Kl.names = ["cross-fade"]; + Hw.exports = Kl; + }); + var Jw = v((QI, Qw) => { + l(); + var p_ = pe(), + d_ = Qt(), + h_ = ke(), + Zl = class extends h_ { + constructor(e, t) { + super(e, t); + e === "display-flex" && (this.name = "flex"); + } + check(e) { + return e.prop === "display" && e.value === this.name; + } + prefixed(e) { + let t, i; + return ( + ([t, e] = p_(e)), + t === 2009 + ? this.name === "flex" + ? (i = "box") + : (i = "inline-box") + : t === 2012 + ? this.name === "flex" + ? (i = "flexbox") + : (i = "inline-flexbox") + : t === "final" && (i = this.name), + e + i + ); + } + replace(e, t) { + return this.prefixed(t); + } + old(e) { + let t = this.prefixed(e); + if (!!t) return new d_(this.name, t); + } + }; + Zl.names = ["display-flex", "inline-flex"]; + Qw.exports = Zl; + }); + var Kw = v((JI, Xw) => { + l(); + var m_ = ke(), + eu = class extends m_ { + constructor(e, t) { + super(e, t); + e === "display-grid" && (this.name = "grid"); + } + check(e) { + return e.prop === "display" && e.value === this.name; + } + }; + eu.names = ["display-grid", "inline-grid"]; + Xw.exports = eu; + }); + var eb = v((XI, Zw) => { + l(); + var g_ = ke(), + tu = class extends g_ { + constructor(e, t) { + super(e, t); + e === "filter-function" && (this.name = "filter"); + } + }; + tu.names = ["filter", "filter-function"]; + Zw.exports = tu; + }); + var nb = v((KI, ib) => { + l(); + var tb = ai(), + B = M(), + rb = Fm(), + y_ = tg(), + w_ = sl(), + b_ = vg(), + ru = dt(), + sr = Jt(), + v_ = Eg(), + $e = ke(), + ar = le(), + x_ = Pg(), + k_ = Ig(), + S_ = Rg(), + C_ = Bg(), + A_ = zg(), + __ = Ug(), + O_ = Gg(), + E_ = Yg(), + T_ = Jg(), + P_ = Kg(), + D_ = ey(), + I_ = ry(), + q_ = ny(), + R_ = ay(), + M_ = ly(), + B_ = cy(), + F_ = dy(), + L_ = gy(), + N_ = wy(), + $_ = vy(), + z_ = Sy(), + j_ = Ay(), + V_ = Ey(), + U_ = Py(), + W_ = Iy(), + G_ = Ry(), + H_ = By(), + Y_ = Ny(), + Q_ = zy(), + J_ = Vy(), + X_ = Wy(), + K_ = Hy(), + Z_ = Qy(), + eO = Xy(), + tO = ew(), + rO = rw(), + iO = nw(), + nO = aw(), + sO = lw(), + aO = cw(), + oO = dw(), + lO = mw(), + uO = ww(), + fO = vw(), + cO = kw(), + pO = Aw(), + dO = Ow(), + hO = Tw(), + mO = Lw(), + gO = zw(), + yO = Uw(), + wO = Gw(), + bO = Yw(), + vO = Jw(), + xO = Kw(), + kO = eb(); + sr.hack(x_); + sr.hack(k_); + sr.hack(S_); + sr.hack(C_); + B.hack(A_); + B.hack(__); + B.hack(O_); + B.hack(E_); + B.hack(T_); + B.hack(P_); + B.hack(D_); + B.hack(I_); + B.hack(q_); + B.hack(R_); + B.hack(M_); + B.hack(B_); + B.hack(F_); + B.hack(L_); + B.hack(N_); + B.hack($_); + B.hack(z_); + B.hack(j_); + B.hack(V_); + B.hack(U_); + B.hack(W_); + B.hack(G_); + B.hack(H_); + B.hack(Y_); + B.hack(Q_); + B.hack(J_); + B.hack(X_); + B.hack(K_); + B.hack(Z_); + B.hack(eO); + B.hack(tO); + B.hack(rO); + B.hack(iO); + B.hack(nO); + B.hack(sO); + B.hack(aO); + B.hack(oO); + B.hack(lO); + B.hack(uO); + B.hack(fO); + B.hack(cO); + B.hack(pO); + B.hack(dO); + B.hack(hO); + $e.hack(mO); + $e.hack(gO); + $e.hack(yO); + $e.hack(wO); + $e.hack(bO); + $e.hack(vO); + $e.hack(xO); + $e.hack(kO); + var iu = new Map(), + li = class { + constructor(e, t, i = {}) { + ((this.data = e), + (this.browsers = t), + (this.options = i), + ([this.add, this.remove] = this.preprocess(this.select(this.data))), + (this.transition = new y_(this)), + (this.processor = new w_(this))); + } + cleaner() { + if (this.cleanerCache) return this.cleanerCache; + if (this.browsers.selected.length) { + let e = new ru(this.browsers.data, []); + this.cleanerCache = new li(this.data, e, this.options); + } else return this; + return this.cleanerCache; + } + select(e) { + let t = { add: {}, remove: {} }; + for (let i in e) { + let n = e[i], + a = n.browsers.map((u) => { + let c = u.split(" "); + return { browser: `${c[0]} ${c[1]}`, note: c[2] }; + }), + s = a.filter((u) => u.note).map((u) => `${this.browsers.prefix(u.browser)} ${u.note}`); + ((s = ar.uniq(s)), + (a = a + .filter((u) => this.browsers.isSelected(u.browser)) + .map((u) => { + let c = this.browsers.prefix(u.browser); + return u.note ? `${c} ${u.note}` : c; + })), + (a = this.sort(ar.uniq(a))), + this.options.flexbox === "no-2009" && (a = a.filter((u) => !u.includes("2009")))); + let o = n.browsers.map((u) => this.browsers.prefix(u)); + (n.mistakes && (o = o.concat(n.mistakes)), + (o = o.concat(s)), + (o = ar.uniq(o)), + a.length + ? ((t.add[i] = a), + a.length < o.length && (t.remove[i] = o.filter((u) => !a.includes(u)))) + : (t.remove[i] = o)); + } + return t; + } + sort(e) { + return e.sort((t, i) => { + let n = ar.removeNote(t).length, + a = ar.removeNote(i).length; + return n === a ? i.length - t.length : a - n; + }); + } + preprocess(e) { + let t = { selectors: [], "@supports": new b_(li, this) }; + for (let n in e.add) { + let a = e.add[n]; + if (n === "@keyframes" || n === "@viewport") t[n] = new v_(n, a, this); + else if (n === "@resolution") t[n] = new rb(n, a, this); + else if (this.data[n].selector) t.selectors.push(sr.load(n, a, this)); + else { + let s = this.data[n].props; + if (s) { + let o = $e.load(n, a, this); + for (let u of s) (t[u] || (t[u] = { values: [] }), t[u].values.push(o)); + } else { + let o = (t[n] && t[n].values) || []; + ((t[n] = B.load(n, a, this)), (t[n].values = o)); + } + } + } + let i = { selectors: [] }; + for (let n in e.remove) { + let a = e.remove[n]; + if (this.data[n].selector) { + let s = sr.load(n, a); + for (let o of a) i.selectors.push(s.old(o)); + } else if (n === "@keyframes" || n === "@viewport") + for (let s of a) { + let o = `@${s}${n.slice(1)}`; + i[o] = { remove: !0 }; + } + else if (n === "@resolution") i[n] = new rb(n, a, this); + else { + let s = this.data[n].props; + if (s) { + let o = $e.load(n, [], this); + for (let u of a) { + let c = o.old(u); + if (c) + for (let f of s) + (i[f] || (i[f] = {}), + i[f].values || (i[f].values = []), + i[f].values.push(c)); + } + } else + for (let o of a) { + let u = this.decl(n).old(n, o); + if (n === "align-self") { + let c = t[n] && t[n].prefixes; + if (c) { + if (o === "-webkit- 2009" && c.includes("-webkit-")) continue; + if (o === "-webkit-" && c.includes("-webkit- 2009")) continue; + } + } + for (let c of u) (i[c] || (i[c] = {}), (i[c].remove = !0)); + } + } + } + return [t, i]; + } + decl(e) { + return (iu.has(e) || iu.set(e, B.load(e)), iu.get(e)); + } + unprefixed(e) { + let t = this.normalize(tb.unprefixed(e)); + return (t === "flex-direction" && (t = "flex-flow"), t); + } + normalize(e) { + return this.decl(e).normalize(e); + } + prefixed(e, t) { + return ((e = tb.unprefixed(e)), this.decl(e).prefixed(e, t)); + } + values(e, t) { + let i = this[e], + n = i["*"] && i["*"].values, + a = i[t] && i[t].values; + return n && a ? ar.uniq(n.concat(a)) : n || a || []; + } + group(e) { + let t = e.parent, + i = t.index(e), + { length: n } = t.nodes, + a = this.unprefixed(e.prop), + s = (o, u) => { + for (i += o; i >= 0 && i < n; ) { + let c = t.nodes[i]; + if (c.type === "decl") { + if ( + (o === -1 && c.prop === a && !ru.withPrefix(c.value)) || + this.unprefixed(c.prop) !== a + ) + break; + if (u(c) === !0) return !0; + if (o === 1 && c.prop === a && !ru.withPrefix(c.value)) break; + } + i += o; + } + return !1; + }; + return { + up(o) { + return s(-1, o); + }, + down(o) { + return s(1, o); + }, + }; + } + }; + ib.exports = li; + }); + var ab = v((ZI, sb) => { + l(); + sb.exports = { + "backdrop-filter": { + feature: "css-backdrop-filter", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5", "safari 16.5"], + }, + element: { + props: [ + "background", + "background-image", + "border-image", + "mask", + "list-style", + "list-style-image", + "content", + "mask-image", + ], + feature: "css-element-function", + browsers: ["firefox 114"], + }, + "user-select": { + mistakes: ["-khtml-"], + feature: "user-select-none", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5", "safari 16.5"], + }, + "background-clip": { + feature: "background-clip-text", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + hyphens: { + feature: "css-hyphens", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5", "safari 16.5"], + }, + fill: { + props: [ + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "inline-size", + "min-inline-size", + "max-inline-size", + "block-size", + "min-block-size", + "max-block-size", + "grid", + "grid-template", + "grid-template-rows", + "grid-template-columns", + "grid-auto-columns", + "grid-auto-rows", + ], + feature: "intrinsic-width", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "fill-available": { + props: [ + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "inline-size", + "min-inline-size", + "max-inline-size", + "block-size", + "min-block-size", + "max-block-size", + "grid", + "grid-template", + "grid-template-rows", + "grid-template-columns", + "grid-auto-columns", + "grid-auto-rows", + ], + feature: "intrinsic-width", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + stretch: { + props: [ + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "inline-size", + "min-inline-size", + "max-inline-size", + "block-size", + "min-block-size", + "max-block-size", + "grid", + "grid-template", + "grid-template-rows", + "grid-template-columns", + "grid-auto-columns", + "grid-auto-rows", + ], + feature: "intrinsic-width", + browsers: ["firefox 114"], + }, + "fit-content": { + props: [ + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "inline-size", + "min-inline-size", + "max-inline-size", + "block-size", + "min-block-size", + "max-block-size", + "grid", + "grid-template", + "grid-template-rows", + "grid-template-columns", + "grid-auto-columns", + "grid-auto-rows", + ], + feature: "intrinsic-width", + browsers: ["firefox 114"], + }, + "text-decoration-style": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-decoration-color": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-decoration-line": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-decoration": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-decoration-skip": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-decoration-skip-ink": { + feature: "text-decoration", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "text-size-adjust": { + feature: "text-size-adjust", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5"], + }, + "mask-clip": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-composite": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-image": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-origin": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-repeat": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border-repeat": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border-source": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + mask: { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-position": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-size": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border-outset": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border-width": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "mask-border-slice": { + feature: "css-masks", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + "clip-path": { feature: "css-clip-path", browsers: ["samsung 21"] }, + "box-decoration-break": { + feature: "css-boxdecorationbreak", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "ios_saf 16.1", + "ios_saf 16.3", + "ios_saf 16.4", + "ios_saf 16.5", + "opera 99", + "safari 16.5", + "samsung 21", + ], + }, + appearance: { feature: "css-appearance", browsers: ["samsung 21"] }, + "image-set": { + props: [ + "background", + "background-image", + "border-image", + "cursor", + "mask", + "mask-image", + "list-style", + "list-style-image", + "content", + ], + feature: "css-image-set", + browsers: ["and_uc 15.5", "chrome 109", "samsung 21"], + }, + "cross-fade": { + props: [ + "background", + "background-image", + "border-image", + "mask", + "list-style", + "list-style-image", + "content", + "mask-image", + ], + feature: "css-cross-fade", + browsers: [ + "and_chr 114", + "and_uc 15.5", + "chrome 109", + "chrome 113", + "chrome 114", + "edge 114", + "opera 99", + "samsung 21", + ], + }, + isolate: { + props: ["unicode-bidi"], + feature: "css-unicode-bidi", + browsers: ["ios_saf 16.1", "ios_saf 16.3", "ios_saf 16.4", "ios_saf 16.5", "safari 16.5"], + }, + "color-adjust": { + feature: "css-color-adjust", + browsers: ["chrome 109", "chrome 113", "chrome 114", "edge 114", "opera 99"], + }, + }; + }); + var lb = v((eq, ob) => { + l(); + ob.exports = {}; + }); + var pb = v((tq, cb) => { + l(); + var SO = Ho(), + { agents: CO } = (Gn(), Wn), + nu = Sm(), + AO = dt(), + _O = nb(), + OO = ab(), + EO = lb(), + ub = { browsers: CO, prefixes: OO }, + fb = ` Replace Autoprefixer \`browsers\` option to Browserslist config. Use \`browserslist\` key in \`package.json\` or \`.browserslistrc\` file. @@ -51,12 +18914,564 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho https://github.com/browserslist/browserslist#readme https://twitter.com/browserslist -`;function TO(r){return Object.prototype.toString.apply(r)==="[object Object]"}var su=new Map;function PO(r,e){e.browsers.selected.length!==0&&(e.add.selectors.length>0||Object.keys(e.add).length>2||r.warn(`Autoprefixer target browsers do not need any prefixes.You do not need Autoprefixer anymore. +`; + function TO(r) { + return Object.prototype.toString.apply(r) === "[object Object]"; + } + var su = new Map(); + function PO(r, e) { + e.browsers.selected.length !== 0 && + (e.add.selectors.length > 0 || + Object.keys(e.add).length > 2 || + r.warn(`Autoprefixer target browsers do not need any prefixes.You do not need Autoprefixer anymore. Check your Browserslist config to be sure that your targets are set up correctly. Learn more at: https://github.com/postcss/autoprefixer#readme https://github.com/browserslist/browserslist#readme -`))}cb.exports=or;function or(...r){let e;if(r.length===1&&TO(r[0])?(e=r[0],r=void 0):r.length===0||r.length===1&&!r[0]?r=void 0:r.length<=2&&(Array.isArray(r[0])||!r[0])?(e=r[1],r=r[0]):typeof r[r.length-1]=="object"&&(e=r.pop()),e||(e={}),e.browser)throw new Error("Change `browser` option to `overrideBrowserslist` in Autoprefixer");if(e.browserslist)throw new Error("Change `browserslist` option to `overrideBrowserslist` in Autoprefixer");e.overrideBrowserslist?r=e.overrideBrowserslist:e.browsers&&(typeof console!="undefined"&&console.warn&&(nu.red?console.warn(nu.red(fb.replace(/`[^`]+`/g,n=>nu.yellow(n.slice(1,-1))))):console.warn(fb)),r=e.browsers);let t={ignoreUnknownVersions:e.ignoreUnknownVersions,stats:e.stats,env:e.env};function i(n){let a=ub,s=new AO(a.browsers,r,n,t),o=s.selected.join(", ")+JSON.stringify(e);return su.has(o)||su.set(o,new _O(a.prefixes,s,e)),su.get(o)}return{postcssPlugin:"autoprefixer",prepare(n){let a=i({from:n.opts.from,env:e.env});return{OnceExit(s){PO(n,a),e.remove!==!1&&a.processor.remove(s,n),e.add!==!1&&a.processor.add(s,n)}}},info(n){return n=n||{},n.from=n.from||h.cwd(),EO(i(n))},options:e,browsers:r}}or.postcss=!0;or.data=ub;or.defaults=SO.defaults;or.info=()=>or().info()});var hb=v((rq,db)=>{l();db.exports={aqua:/#00ffff(ff)?(?!\w)|#0ff(f)?(?!\w)/gi,azure:/#f0ffff(ff)?(?!\w)/gi,beige:/#f5f5dc(ff)?(?!\w)/gi,bisque:/#ffe4c4(ff)?(?!\w)/gi,black:/#000000(ff)?(?!\w)|#000(f)?(?!\w)/gi,blue:/#0000ff(ff)?(?!\w)|#00f(f)?(?!\w)/gi,brown:/#a52a2a(ff)?(?!\w)/gi,coral:/#ff7f50(ff)?(?!\w)/gi,cornsilk:/#fff8dc(ff)?(?!\w)/gi,crimson:/#dc143c(ff)?(?!\w)/gi,cyan:/#00ffff(ff)?(?!\w)|#0ff(f)?(?!\w)/gi,darkblue:/#00008b(ff)?(?!\w)/gi,darkcyan:/#008b8b(ff)?(?!\w)/gi,darkgrey:/#a9a9a9(ff)?(?!\w)/gi,darkred:/#8b0000(ff)?(?!\w)/gi,deeppink:/#ff1493(ff)?(?!\w)/gi,dimgrey:/#696969(ff)?(?!\w)/gi,gold:/#ffd700(ff)?(?!\w)/gi,green:/#008000(ff)?(?!\w)/gi,grey:/#808080(ff)?(?!\w)/gi,honeydew:/#f0fff0(ff)?(?!\w)/gi,hotpink:/#ff69b4(ff)?(?!\w)/gi,indigo:/#4b0082(ff)?(?!\w)/gi,ivory:/#fffff0(ff)?(?!\w)/gi,khaki:/#f0e68c(ff)?(?!\w)/gi,lavender:/#e6e6fa(ff)?(?!\w)/gi,lime:/#00ff00(ff)?(?!\w)|#0f0(f)?(?!\w)/gi,linen:/#faf0e6(ff)?(?!\w)/gi,maroon:/#800000(ff)?(?!\w)/gi,moccasin:/#ffe4b5(ff)?(?!\w)/gi,navy:/#000080(ff)?(?!\w)/gi,oldlace:/#fdf5e6(ff)?(?!\w)/gi,olive:/#808000(ff)?(?!\w)/gi,orange:/#ffa500(ff)?(?!\w)/gi,orchid:/#da70d6(ff)?(?!\w)/gi,peru:/#cd853f(ff)?(?!\w)/gi,pink:/#ffc0cb(ff)?(?!\w)/gi,plum:/#dda0dd(ff)?(?!\w)/gi,purple:/#800080(ff)?(?!\w)/gi,red:/#ff0000(ff)?(?!\w)|#f00(f)?(?!\w)/gi,salmon:/#fa8072(ff)?(?!\w)/gi,seagreen:/#2e8b57(ff)?(?!\w)/gi,seashell:/#fff5ee(ff)?(?!\w)/gi,sienna:/#a0522d(ff)?(?!\w)/gi,silver:/#c0c0c0(ff)?(?!\w)/gi,skyblue:/#87ceeb(ff)?(?!\w)/gi,snow:/#fffafa(ff)?(?!\w)/gi,tan:/#d2b48c(ff)?(?!\w)/gi,teal:/#008080(ff)?(?!\w)/gi,thistle:/#d8bfd8(ff)?(?!\w)/gi,tomato:/#ff6347(ff)?(?!\w)/gi,violet:/#ee82ee(ff)?(?!\w)/gi,wheat:/#f5deb3(ff)?(?!\w)/gi,white:/#ffffff(ff)?(?!\w)|#fff(f)?(?!\w)/gi}});var gb=v((iq,mb)=>{l();var au=hb(),ou={whitespace:/\s+/g,urlHexPairs:/%[\dA-F]{2}/g,quotes:/"/g};function DO(r){return r.trim().replace(ou.whitespace," ")}function IO(r){return encodeURIComponent(r).replace(ou.urlHexPairs,RO)}function qO(r){return Object.keys(au).forEach(function(e){au[e].test(r)&&(r=r.replace(au[e],e))}),r}function RO(r){switch(r){case"%20":return" ";case"%3D":return"=";case"%3A":return":";case"%2F":return"/";default:return r.toLowerCase()}}function lu(r){if(typeof r!="string")throw new TypeError("Expected a string, but received "+typeof r);r.charCodeAt(0)===65279&&(r=r.slice(1));var e=qO(DO(r)).replace(ou.quotes,"'");return"data:image/svg+xml,"+IO(e)}lu.toSrcset=function(e){return lu(e).replace(/ /g,"%20")};mb.exports=lu});var uu={};Ae(uu,{default:()=>MO});var yb,MO,fu=C(()=>{l();wi();yb=X(Si()),MO=et(yb.default.theme)});var kb=v((sq,xb)=>{l();var Zn=gb(),BO=(qn(),In).default,wb=(fu(),uu).default,gt=(mi(),as).default,[FO,{lineHeight:LO}]=wb.fontSize.base,{spacing:Je,borderWidth:bb,borderRadius:vb}=wb;function yt(r,e){return r.replace("",`var(${e}, 1)`)}var NO=BO.withOptions(function(r={strategy:void 0}){return function({addBase:e,addComponents:t,theme:i}){let n=r.strategy===void 0?["base","class"]:[r.strategy],a=[{base:["[type='text']","input:where(:not([type]))","[type='email']","[type='url']","[type='password']","[type='number']","[type='date']","[type='datetime-local']","[type='month']","[type='search']","[type='tel']","[type='time']","[type='week']","[multiple]","textarea","select"],class:[".form-input",".form-textarea",".form-select",".form-multiselect"],styles:{appearance:"none","background-color":"#fff","border-color":yt(i("colors.gray.500",gt.gray[500]),"--tw-border-opacity"),"border-width":bb.DEFAULT,"border-radius":vb.none,"padding-top":Je[2],"padding-right":Je[3],"padding-bottom":Je[2],"padding-left":Je[3],"font-size":FO,"line-height":LO,"--tw-shadow":"0 0 #0000","&:focus":{outline:"2px solid transparent","outline-offset":"2px","--tw-ring-inset":"var(--tw-empty,/*!*/ /*!*/)","--tw-ring-offset-width":"0px","--tw-ring-offset-color":"#fff","--tw-ring-color":yt(i("colors.blue.600",gt.blue[600]),"--tw-ring-opacity"),"--tw-ring-offset-shadow":"var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)","--tw-ring-shadow":"var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)","box-shadow":"var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)","border-color":yt(i("colors.blue.600",gt.blue[600]),"--tw-border-opacity")}}},{base:["input::placeholder","textarea::placeholder"],class:[".form-input::placeholder",".form-textarea::placeholder"],styles:{color:yt(i("colors.gray.500",gt.gray[500]),"--tw-text-opacity"),opacity:"1"}},{base:["::-webkit-datetime-edit-fields-wrapper"],class:[".form-input::-webkit-datetime-edit-fields-wrapper"],styles:{padding:"0"}},{base:["::-webkit-date-and-time-value"],class:[".form-input::-webkit-date-and-time-value"],styles:{"min-height":"1.5em"}},{base:["::-webkit-date-and-time-value"],class:[".form-input::-webkit-date-and-time-value"],styles:{"text-align":"inherit"}},{base:["::-webkit-datetime-edit"],class:[".form-input::-webkit-datetime-edit"],styles:{display:"inline-flex"}},{base:["::-webkit-datetime-edit","::-webkit-datetime-edit-year-field","::-webkit-datetime-edit-month-field","::-webkit-datetime-edit-day-field","::-webkit-datetime-edit-hour-field","::-webkit-datetime-edit-minute-field","::-webkit-datetime-edit-second-field","::-webkit-datetime-edit-millisecond-field","::-webkit-datetime-edit-meridiem-field"],class:[".form-input::-webkit-datetime-edit",".form-input::-webkit-datetime-edit-year-field",".form-input::-webkit-datetime-edit-month-field",".form-input::-webkit-datetime-edit-day-field",".form-input::-webkit-datetime-edit-hour-field",".form-input::-webkit-datetime-edit-minute-field",".form-input::-webkit-datetime-edit-second-field",".form-input::-webkit-datetime-edit-millisecond-field",".form-input::-webkit-datetime-edit-meridiem-field"],styles:{"padding-top":0,"padding-bottom":0}},{base:["select"],class:[".form-select"],styles:{"background-image":`url("${Zn(``)}")`,"background-position":`right ${Je[2]} center`,"background-repeat":"no-repeat","background-size":"1.5em 1.5em","padding-right":Je[10],"print-color-adjust":"exact"}},{base:["[multiple]",'[size]:where(select:not([size="1"]))'],class:['.form-select:where([size]:not([size="1"]))'],styles:{"background-image":"initial","background-position":"initial","background-repeat":"unset","background-size":"initial","padding-right":Je[3],"print-color-adjust":"unset"}},{base:["[type='checkbox']","[type='radio']"],class:[".form-checkbox",".form-radio"],styles:{appearance:"none",padding:"0","print-color-adjust":"exact",display:"inline-block","vertical-align":"middle","background-origin":"border-box","user-select":"none","flex-shrink":"0",height:Je[4],width:Je[4],color:yt(i("colors.blue.600",gt.blue[600]),"--tw-text-opacity"),"background-color":"#fff","border-color":yt(i("colors.gray.500",gt.gray[500]),"--tw-border-opacity"),"border-width":bb.DEFAULT,"--tw-shadow":"0 0 #0000"}},{base:["[type='checkbox']"],class:[".form-checkbox"],styles:{"border-radius":vb.none}},{base:["[type='radio']"],class:[".form-radio"],styles:{"border-radius":"100%"}},{base:["[type='checkbox']:focus","[type='radio']:focus"],class:[".form-checkbox:focus",".form-radio:focus"],styles:{outline:"2px solid transparent","outline-offset":"2px","--tw-ring-inset":"var(--tw-empty,/*!*/ /*!*/)","--tw-ring-offset-width":"2px","--tw-ring-offset-color":"#fff","--tw-ring-color":yt(i("colors.blue.600",gt.blue[600]),"--tw-ring-opacity"),"--tw-ring-offset-shadow":"var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)","--tw-ring-shadow":"var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)","box-shadow":"var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)"}},{base:["[type='checkbox']:checked","[type='radio']:checked"],class:[".form-checkbox:checked",".form-radio:checked"],styles:{"border-color":"transparent","background-color":"currentColor","background-size":"100% 100%","background-position":"center","background-repeat":"no-repeat"}},{base:["[type='checkbox']:checked"],class:[".form-checkbox:checked"],styles:{"background-image":`url("${Zn('')}")`,"@media (forced-colors: active) ":{appearance:"auto"}}},{base:["[type='radio']:checked"],class:[".form-radio:checked"],styles:{"background-image":`url("${Zn('')}")`,"@media (forced-colors: active) ":{appearance:"auto"}}},{base:["[type='checkbox']:checked:hover","[type='checkbox']:checked:focus","[type='radio']:checked:hover","[type='radio']:checked:focus"],class:[".form-checkbox:checked:hover",".form-checkbox:checked:focus",".form-radio:checked:hover",".form-radio:checked:focus"],styles:{"border-color":"transparent","background-color":"currentColor"}},{base:["[type='checkbox']:indeterminate"],class:[".form-checkbox:indeterminate"],styles:{"background-image":`url("${Zn('')}")`,"border-color":"transparent","background-color":"currentColor","background-size":"100% 100%","background-position":"center","background-repeat":"no-repeat","@media (forced-colors: active) ":{appearance:"auto"}}},{base:["[type='checkbox']:indeterminate:hover","[type='checkbox']:indeterminate:focus"],class:[".form-checkbox:indeterminate:hover",".form-checkbox:indeterminate:focus"],styles:{"border-color":"transparent","background-color":"currentColor"}},{base:["[type='file']"],class:null,styles:{background:"unset","border-color":"inherit","border-width":"0","border-radius":"0",padding:"0","font-size":"unset","line-height":"inherit"}},{base:["[type='file']:focus"],class:null,styles:{outline:["1px solid ButtonText","1px auto -webkit-focus-ring-color"]}}],s=o=>a.map(u=>u[o]===null?null:{[u[o]]:u.styles}).filter(Boolean);n.includes("base")&&e(s("base")),n.includes("class")&&t(s("class"))}});xb.exports=NO});var Sb={};Ae(Sb,{default:()=>$O});var $O,Cb=C(()=>{l();$O=[kb()]});var _b={};Ae(_b,{default:()=>zO});var Ab,zO,Ob=C(()=>{l();wi();Ab=X(Si()),zO=et(Ab.default)});l();"use strict";var jO=Xe(xm()),VO=Xe(ge()),UO=Xe(pb()),WO=Xe((Cb(),Sb)),GO=Xe((fu(),uu)),HO=Xe((Ob(),_b)),YO=Xe((mi(),as)),QO=Xe((qn(),In)),JO=Xe((xs(),lf));function Xe(r){return r&&r.__esModule?r:{default:r}}console.warn("cdn.tailwindcss.com should not be used in production. To use Tailwind CSS in production, install it as a PostCSS plugin or use the Tailwind CLI: https://tailwindcss.com/docs/installation");var es="tailwind",cu="text/tailwindcss",Eb="/template.html",Ct,Tb=!0,Pb=0,pu=new Set,du,Db="",Ib=(r=!1)=>({get(e,t){return(!r||t==="config")&&typeof e[t]=="object"&&e[t]!==null?new Proxy(e[t],Ib()):e[t]},set(e,t,i){return e[t]=i,(!r||t==="config")&&hu(!0),!0}});window[es]=new Proxy({config:{},defaultTheme:GO.default,defaultConfig:HO.default,colors:YO.default,plugin:QO.default,resolveConfig:JO.default},Ib(!0));function qb(r){du.observe(r,{attributes:!0,attributeFilter:["type"],characterData:!0,subtree:!0,childList:!0})}new MutationObserver(async r=>{let e=!1;if(!du){du=new MutationObserver(async()=>await hu(!0));for(let t of document.querySelectorAll(`style[type="${cu}"]`))qb(t)}for(let t of r)for(let i of t.addedNodes)i.nodeType===1&&i.tagName==="STYLE"&&i.getAttribute("type")===cu&&(qb(i),e=!0);await hu(e)}).observe(document.documentElement,{attributes:!0,attributeFilter:["class"],childList:!0,subtree:!0});async function hu(r=!1){r&&(Pb++,pu.clear());let e="";for(let i of document.querySelectorAll(`style[type="${cu}"]`))e+=i.textContent;let t=new Set;for(let i of document.querySelectorAll("[class]"))for(let n of i.classList)pu.has(n)||t.add(n);if(document.body&&(Tb||t.size>0||e!==Db||!Ct||!Ct.isConnected)){for(let n of t)pu.add(n);Tb=!1,Db=e,self[Eb]=Array.from(t).join(" ");let{css:i}=await(0,VO.default)([(0,jO.default)({...window[es].config,_hash:Pb,content:[Eb],plugins:[...WO.default,...Array.isArray(window[es].config.plugins)?window[es].config.plugins:[]]}),(0,UO.default)({remove:!1})]).process(`@tailwind base;@tailwind components;@tailwind utilities;${e}`);(!Ct||!Ct.isConnected)&&(Ct=document.createElement("style"),document.head.append(Ct)),Ct.textContent=i}}})(); +`)); + } + cb.exports = or; + function or(...r) { + let e; + if ( + (r.length === 1 && TO(r[0]) + ? ((e = r[0]), (r = void 0)) + : r.length === 0 || (r.length === 1 && !r[0]) + ? (r = void 0) + : r.length <= 2 && (Array.isArray(r[0]) || !r[0]) + ? ((e = r[1]), (r = r[0])) + : typeof r[r.length - 1] == "object" && (e = r.pop()), + e || (e = {}), + e.browser) + ) + throw new Error("Change `browser` option to `overrideBrowserslist` in Autoprefixer"); + if (e.browserslist) + throw new Error("Change `browserslist` option to `overrideBrowserslist` in Autoprefixer"); + e.overrideBrowserslist + ? (r = e.overrideBrowserslist) + : e.browsers && + (typeof console != "undefined" && + console.warn && + (nu.red + ? console.warn(nu.red(fb.replace(/`[^`]+`/g, (n) => nu.yellow(n.slice(1, -1))))) + : console.warn(fb)), + (r = e.browsers)); + let t = { ignoreUnknownVersions: e.ignoreUnknownVersions, stats: e.stats, env: e.env }; + function i(n) { + let a = ub, + s = new AO(a.browsers, r, n, t), + o = s.selected.join(", ") + JSON.stringify(e); + return (su.has(o) || su.set(o, new _O(a.prefixes, s, e)), su.get(o)); + } + return { + postcssPlugin: "autoprefixer", + prepare(n) { + let a = i({ from: n.opts.from, env: e.env }); + return { + OnceExit(s) { + (PO(n, a), + e.remove !== !1 && a.processor.remove(s, n), + e.add !== !1 && a.processor.add(s, n)); + }, + }; + }, + info(n) { + return ((n = n || {}), (n.from = n.from || h.cwd()), EO(i(n))); + }, + options: e, + browsers: r, + }; + } + or.postcss = !0; + or.data = ub; + or.defaults = SO.defaults; + or.info = () => or().info(); + }); + var hb = v((rq, db) => { + l(); + db.exports = { + aqua: /#00ffff(ff)?(?!\w)|#0ff(f)?(?!\w)/gi, + azure: /#f0ffff(ff)?(?!\w)/gi, + beige: /#f5f5dc(ff)?(?!\w)/gi, + bisque: /#ffe4c4(ff)?(?!\w)/gi, + black: /#000000(ff)?(?!\w)|#000(f)?(?!\w)/gi, + blue: /#0000ff(ff)?(?!\w)|#00f(f)?(?!\w)/gi, + brown: /#a52a2a(ff)?(?!\w)/gi, + coral: /#ff7f50(ff)?(?!\w)/gi, + cornsilk: /#fff8dc(ff)?(?!\w)/gi, + crimson: /#dc143c(ff)?(?!\w)/gi, + cyan: /#00ffff(ff)?(?!\w)|#0ff(f)?(?!\w)/gi, + darkblue: /#00008b(ff)?(?!\w)/gi, + darkcyan: /#008b8b(ff)?(?!\w)/gi, + darkgrey: /#a9a9a9(ff)?(?!\w)/gi, + darkred: /#8b0000(ff)?(?!\w)/gi, + deeppink: /#ff1493(ff)?(?!\w)/gi, + dimgrey: /#696969(ff)?(?!\w)/gi, + gold: /#ffd700(ff)?(?!\w)/gi, + green: /#008000(ff)?(?!\w)/gi, + grey: /#808080(ff)?(?!\w)/gi, + honeydew: /#f0fff0(ff)?(?!\w)/gi, + hotpink: /#ff69b4(ff)?(?!\w)/gi, + indigo: /#4b0082(ff)?(?!\w)/gi, + ivory: /#fffff0(ff)?(?!\w)/gi, + khaki: /#f0e68c(ff)?(?!\w)/gi, + lavender: /#e6e6fa(ff)?(?!\w)/gi, + lime: /#00ff00(ff)?(?!\w)|#0f0(f)?(?!\w)/gi, + linen: /#faf0e6(ff)?(?!\w)/gi, + maroon: /#800000(ff)?(?!\w)/gi, + moccasin: /#ffe4b5(ff)?(?!\w)/gi, + navy: /#000080(ff)?(?!\w)/gi, + oldlace: /#fdf5e6(ff)?(?!\w)/gi, + olive: /#808000(ff)?(?!\w)/gi, + orange: /#ffa500(ff)?(?!\w)/gi, + orchid: /#da70d6(ff)?(?!\w)/gi, + peru: /#cd853f(ff)?(?!\w)/gi, + pink: /#ffc0cb(ff)?(?!\w)/gi, + plum: /#dda0dd(ff)?(?!\w)/gi, + purple: /#800080(ff)?(?!\w)/gi, + red: /#ff0000(ff)?(?!\w)|#f00(f)?(?!\w)/gi, + salmon: /#fa8072(ff)?(?!\w)/gi, + seagreen: /#2e8b57(ff)?(?!\w)/gi, + seashell: /#fff5ee(ff)?(?!\w)/gi, + sienna: /#a0522d(ff)?(?!\w)/gi, + silver: /#c0c0c0(ff)?(?!\w)/gi, + skyblue: /#87ceeb(ff)?(?!\w)/gi, + snow: /#fffafa(ff)?(?!\w)/gi, + tan: /#d2b48c(ff)?(?!\w)/gi, + teal: /#008080(ff)?(?!\w)/gi, + thistle: /#d8bfd8(ff)?(?!\w)/gi, + tomato: /#ff6347(ff)?(?!\w)/gi, + violet: /#ee82ee(ff)?(?!\w)/gi, + wheat: /#f5deb3(ff)?(?!\w)/gi, + white: /#ffffff(ff)?(?!\w)|#fff(f)?(?!\w)/gi, + }; + }); + var gb = v((iq, mb) => { + l(); + var au = hb(), + ou = { whitespace: /\s+/g, urlHexPairs: /%[\dA-F]{2}/g, quotes: /"/g }; + function DO(r) { + return r.trim().replace(ou.whitespace, " "); + } + function IO(r) { + return encodeURIComponent(r).replace(ou.urlHexPairs, RO); + } + function qO(r) { + return ( + Object.keys(au).forEach(function (e) { + au[e].test(r) && (r = r.replace(au[e], e)); + }), + r + ); + } + function RO(r) { + switch (r) { + case "%20": + return " "; + case "%3D": + return "="; + case "%3A": + return ":"; + case "%2F": + return "/"; + default: + return r.toLowerCase(); + } + } + function lu(r) { + if (typeof r != "string") throw new TypeError("Expected a string, but received " + typeof r); + r.charCodeAt(0) === 65279 && (r = r.slice(1)); + var e = qO(DO(r)).replace(ou.quotes, "'"); + return "data:image/svg+xml," + IO(e); + } + lu.toSrcset = function (e) { + return lu(e).replace(/ /g, "%20"); + }; + mb.exports = lu; + }); + var uu = {}; + Ae(uu, { default: () => MO }); + var yb, + MO, + fu = C(() => { + l(); + wi(); + ((yb = X(Si())), (MO = et(yb.default.theme))); + }); + var kb = v((sq, xb) => { + l(); + var Zn = gb(), + BO = (qn(), In).default, + wb = (fu(), uu).default, + gt = (mi(), as).default, + [FO, { lineHeight: LO }] = wb.fontSize.base, + { spacing: Je, borderWidth: bb, borderRadius: vb } = wb; + function yt(r, e) { + return r.replace("", `var(${e}, 1)`); + } + var NO = BO.withOptions(function (r = { strategy: void 0 }) { + return function ({ addBase: e, addComponents: t, theme: i }) { + let n = r.strategy === void 0 ? ["base", "class"] : [r.strategy], + a = [ + { + base: [ + "[type='text']", + "input:where(:not([type]))", + "[type='email']", + "[type='url']", + "[type='password']", + "[type='number']", + "[type='date']", + "[type='datetime-local']", + "[type='month']", + "[type='search']", + "[type='tel']", + "[type='time']", + "[type='week']", + "[multiple]", + "textarea", + "select", + ], + class: [".form-input", ".form-textarea", ".form-select", ".form-multiselect"], + styles: { + appearance: "none", + "background-color": "#fff", + "border-color": yt(i("colors.gray.500", gt.gray[500]), "--tw-border-opacity"), + "border-width": bb.DEFAULT, + "border-radius": vb.none, + "padding-top": Je[2], + "padding-right": Je[3], + "padding-bottom": Je[2], + "padding-left": Je[3], + "font-size": FO, + "line-height": LO, + "--tw-shadow": "0 0 #0000", + "&:focus": { + outline: "2px solid transparent", + "outline-offset": "2px", + "--tw-ring-inset": "var(--tw-empty,/*!*/ /*!*/)", + "--tw-ring-offset-width": "0px", + "--tw-ring-offset-color": "#fff", + "--tw-ring-color": yt(i("colors.blue.600", gt.blue[600]), "--tw-ring-opacity"), + "--tw-ring-offset-shadow": + "var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)", + "--tw-ring-shadow": + "var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)", + "box-shadow": + "var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)", + "border-color": yt(i("colors.blue.600", gt.blue[600]), "--tw-border-opacity"), + }, + }, + }, + { + base: ["input::placeholder", "textarea::placeholder"], + class: [".form-input::placeholder", ".form-textarea::placeholder"], + styles: { + color: yt(i("colors.gray.500", gt.gray[500]), "--tw-text-opacity"), + opacity: "1", + }, + }, + { + base: ["::-webkit-datetime-edit-fields-wrapper"], + class: [".form-input::-webkit-datetime-edit-fields-wrapper"], + styles: { padding: "0" }, + }, + { + base: ["::-webkit-date-and-time-value"], + class: [".form-input::-webkit-date-and-time-value"], + styles: { "min-height": "1.5em" }, + }, + { + base: ["::-webkit-date-and-time-value"], + class: [".form-input::-webkit-date-and-time-value"], + styles: { "text-align": "inherit" }, + }, + { + base: ["::-webkit-datetime-edit"], + class: [".form-input::-webkit-datetime-edit"], + styles: { display: "inline-flex" }, + }, + { + base: [ + "::-webkit-datetime-edit", + "::-webkit-datetime-edit-year-field", + "::-webkit-datetime-edit-month-field", + "::-webkit-datetime-edit-day-field", + "::-webkit-datetime-edit-hour-field", + "::-webkit-datetime-edit-minute-field", + "::-webkit-datetime-edit-second-field", + "::-webkit-datetime-edit-millisecond-field", + "::-webkit-datetime-edit-meridiem-field", + ], + class: [ + ".form-input::-webkit-datetime-edit", + ".form-input::-webkit-datetime-edit-year-field", + ".form-input::-webkit-datetime-edit-month-field", + ".form-input::-webkit-datetime-edit-day-field", + ".form-input::-webkit-datetime-edit-hour-field", + ".form-input::-webkit-datetime-edit-minute-field", + ".form-input::-webkit-datetime-edit-second-field", + ".form-input::-webkit-datetime-edit-millisecond-field", + ".form-input::-webkit-datetime-edit-meridiem-field", + ], + styles: { "padding-top": 0, "padding-bottom": 0 }, + }, + { + base: ["select"], + class: [".form-select"], + styles: { + "background-image": `url("${Zn(``)}")`, + "background-position": `right ${Je[2]} center`, + "background-repeat": "no-repeat", + "background-size": "1.5em 1.5em", + "padding-right": Je[10], + "print-color-adjust": "exact", + }, + }, + { + base: ["[multiple]", '[size]:where(select:not([size="1"]))'], + class: ['.form-select:where([size]:not([size="1"]))'], + styles: { + "background-image": "initial", + "background-position": "initial", + "background-repeat": "unset", + "background-size": "initial", + "padding-right": Je[3], + "print-color-adjust": "unset", + }, + }, + { + base: ["[type='checkbox']", "[type='radio']"], + class: [".form-checkbox", ".form-radio"], + styles: { + appearance: "none", + padding: "0", + "print-color-adjust": "exact", + display: "inline-block", + "vertical-align": "middle", + "background-origin": "border-box", + "user-select": "none", + "flex-shrink": "0", + height: Je[4], + width: Je[4], + color: yt(i("colors.blue.600", gt.blue[600]), "--tw-text-opacity"), + "background-color": "#fff", + "border-color": yt(i("colors.gray.500", gt.gray[500]), "--tw-border-opacity"), + "border-width": bb.DEFAULT, + "--tw-shadow": "0 0 #0000", + }, + }, + { + base: ["[type='checkbox']"], + class: [".form-checkbox"], + styles: { "border-radius": vb.none }, + }, + { base: ["[type='radio']"], class: [".form-radio"], styles: { "border-radius": "100%" } }, + { + base: ["[type='checkbox']:focus", "[type='radio']:focus"], + class: [".form-checkbox:focus", ".form-radio:focus"], + styles: { + outline: "2px solid transparent", + "outline-offset": "2px", + "--tw-ring-inset": "var(--tw-empty,/*!*/ /*!*/)", + "--tw-ring-offset-width": "2px", + "--tw-ring-offset-color": "#fff", + "--tw-ring-color": yt(i("colors.blue.600", gt.blue[600]), "--tw-ring-opacity"), + "--tw-ring-offset-shadow": + "var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)", + "--tw-ring-shadow": + "var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)", + "box-shadow": "var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)", + }, + }, + { + base: ["[type='checkbox']:checked", "[type='radio']:checked"], + class: [".form-checkbox:checked", ".form-radio:checked"], + styles: { + "border-color": "transparent", + "background-color": "currentColor", + "background-size": "100% 100%", + "background-position": "center", + "background-repeat": "no-repeat", + }, + }, + { + base: ["[type='checkbox']:checked"], + class: [".form-checkbox:checked"], + styles: { + "background-image": `url("${Zn('')}")`, + "@media (forced-colors: active) ": { appearance: "auto" }, + }, + }, + { + base: ["[type='radio']:checked"], + class: [".form-radio:checked"], + styles: { + "background-image": `url("${Zn('')}")`, + "@media (forced-colors: active) ": { appearance: "auto" }, + }, + }, + { + base: [ + "[type='checkbox']:checked:hover", + "[type='checkbox']:checked:focus", + "[type='radio']:checked:hover", + "[type='radio']:checked:focus", + ], + class: [ + ".form-checkbox:checked:hover", + ".form-checkbox:checked:focus", + ".form-radio:checked:hover", + ".form-radio:checked:focus", + ], + styles: { "border-color": "transparent", "background-color": "currentColor" }, + }, + { + base: ["[type='checkbox']:indeterminate"], + class: [".form-checkbox:indeterminate"], + styles: { + "background-image": `url("${Zn('')}")`, + "border-color": "transparent", + "background-color": "currentColor", + "background-size": "100% 100%", + "background-position": "center", + "background-repeat": "no-repeat", + "@media (forced-colors: active) ": { appearance: "auto" }, + }, + }, + { + base: ["[type='checkbox']:indeterminate:hover", "[type='checkbox']:indeterminate:focus"], + class: [".form-checkbox:indeterminate:hover", ".form-checkbox:indeterminate:focus"], + styles: { "border-color": "transparent", "background-color": "currentColor" }, + }, + { + base: ["[type='file']"], + class: null, + styles: { + background: "unset", + "border-color": "inherit", + "border-width": "0", + "border-radius": "0", + padding: "0", + "font-size": "unset", + "line-height": "inherit", + }, + }, + { + base: ["[type='file']:focus"], + class: null, + styles: { outline: ["1px solid ButtonText", "1px auto -webkit-focus-ring-color"] }, + }, + ], + s = (o) => a.map((u) => (u[o] === null ? null : { [u[o]]: u.styles })).filter(Boolean); + (n.includes("base") && e(s("base")), n.includes("class") && t(s("class"))); + }; + }); + xb.exports = NO; + }); + var Sb = {}; + Ae(Sb, { default: () => $O }); + var $O, + Cb = C(() => { + l(); + $O = [kb()]; + }); + var _b = {}; + Ae(_b, { default: () => zO }); + var Ab, + zO, + Ob = C(() => { + l(); + wi(); + ((Ab = X(Si())), (zO = et(Ab.default))); + }); + l(); + ("use strict"); + var jO = Xe(xm()), + VO = Xe(ge()), + UO = Xe(pb()), + WO = Xe((Cb(), Sb)), + GO = Xe((fu(), uu)), + HO = Xe((Ob(), _b)), + YO = Xe((mi(), as)), + QO = Xe((qn(), In)), + JO = Xe((xs(), lf)); + function Xe(r) { + return r && r.__esModule ? r : { default: r }; + } + console.warn( + "cdn.tailwindcss.com should not be used in production. To use Tailwind CSS in production, install it as a PostCSS plugin or use the Tailwind CLI: https://tailwindcss.com/docs/installation" + ); + var es = "tailwind", + cu = "text/tailwindcss", + Eb = "/template.html", + Ct, + Tb = !0, + Pb = 0, + pu = new Set(), + du, + Db = "", + Ib = (r = !1) => ({ + get(e, t) { + return (!r || t === "config") && typeof e[t] == "object" && e[t] !== null + ? new Proxy(e[t], Ib()) + : e[t]; + }, + set(e, t, i) { + return ((e[t] = i), (!r || t === "config") && hu(!0), !0); + }, + }); + window[es] = new Proxy( + { + config: {}, + defaultTheme: GO.default, + defaultConfig: HO.default, + colors: YO.default, + plugin: QO.default, + resolveConfig: JO.default, + }, + Ib(!0) + ); + function qb(r) { + du.observe(r, { attributes: !0, attributeFilter: ["type"], characterData: !0, subtree: !0, childList: !0 }); + } + new MutationObserver(async (r) => { + let e = !1; + if (!du) { + du = new MutationObserver(async () => await hu(!0)); + for (let t of document.querySelectorAll(`style[type="${cu}"]`)) qb(t); + } + for (let t of r) + for (let i of t.addedNodes) + i.nodeType === 1 && i.tagName === "STYLE" && i.getAttribute("type") === cu && (qb(i), (e = !0)); + await hu(e); + }).observe(document.documentElement, { attributes: !0, attributeFilter: ["class"], childList: !0, subtree: !0 }); + async function hu(r = !1) { + r && (Pb++, pu.clear()); + let e = ""; + for (let i of document.querySelectorAll(`style[type="${cu}"]`)) e += i.textContent; + let t = new Set(); + for (let i of document.querySelectorAll("[class]")) for (let n of i.classList) pu.has(n) || t.add(n); + if (document.body && (Tb || t.size > 0 || e !== Db || !Ct || !Ct.isConnected)) { + for (let n of t) pu.add(n); + ((Tb = !1), (Db = e), (self[Eb] = Array.from(t).join(" "))); + let { css: i } = await (0, VO.default)([ + (0, jO.default)({ + ...window[es].config, + _hash: Pb, + content: [Eb], + plugins: [ + ...WO.default, + ...(Array.isArray(window[es].config.plugins) ? window[es].config.plugins : []), + ], + }), + (0, UO.default)({ remove: !1 }), + ]).process(`@tailwind base;@tailwind components;@tailwind utilities;${e}`); + ((!Ct || !Ct.isConnected) && ((Ct = document.createElement("style")), document.head.append(Ct)), + (Ct.textContent = i)); + } + } +})(); /*! https://mths.be/cssesc v3.0.0 by @mathias */ diff --git a/electron/build/icon.png b/electron/build/icon.png index aea1c67..05ae152 100644 Binary files a/electron/build/icon.png and b/electron/build/icon.png differ diff --git a/electron/crash.html b/electron/crash.html new file mode 100644 index 0000000..159c9cb --- /dev/null +++ b/electron/crash.html @@ -0,0 +1,216 @@ + + + + + + + MeshChatX - Crash Report + + + +
+
+
+
+ +
+
+
+
+
+
+ + + +
+
+
+ MeshChatX Crashed +
+
+ Critical error detected in backend service. +
+
+
+ +
+
+
+ Exit Code +
+
+ -- +
+
+
+
+ Status +
+
Offline
+
+
+ +
+
+

+ Diagnostic Logs +

+ +
+ +
+
+ Standard Output (stdout) +
+
+

+                                
+
+ +
+
+ Standard Error (stderr) +
+
+

+                                
+
+
+ +
+ + + +
+
+
+
+
+ + + + diff --git a/electron/loading.html b/electron/loading.html index 693df9b..619ebd3 100644 --- a/electron/loading.html +++ b/electron/loading.html @@ -1,6 +1,10 @@ + @@ -19,15 +23,17 @@ > -
+
-
-
+
+
-

- MeshChatX -

MeshChatX
@@ -47,11 +50,11 @@
- Preparing your node + Preparing your app
-
-
+
+
@@ -79,7 +84,7 @@
-
+
diff --git a/electron/main-legacy.js b/electron/main-legacy.js new file mode 100644 index 0000000..9679e03 --- /dev/null +++ b/electron/main-legacy.js @@ -0,0 +1,366 @@ +const { app, BrowserWindow, dialog, ipcMain, shell, systemPreferences } = require("electron"); +const electronPrompt = require("electron-prompt"); +const { spawn } = require("child_process"); +const fs = require("fs"); +const path = require("node:path"); + +// remember main window +var mainWindow = null; + +// remember child process for exe so we can kill it when app exits +var exeChildProcess = null; + +// allow fetching app version via ipc +ipcMain.handle("app-version", () => { + return app.getVersion(); +}); + +// allow fetching hardware acceleration status via ipc +ipcMain.handle("is-hardware-acceleration-enabled", () => { + // New in Electron 39, fallback for legacy + if (typeof app.isHardwareAccelerationEnabled === "function") { + return app.isHardwareAccelerationEnabled(); + } + return true; // Assume true for older versions +}); + +// allow fetching integrity status (Stub for legacy) +ipcMain.handle("get-integrity-status", () => { + return { + backend: { ok: true, issues: ["Not supported in legacy mode"] }, + data: { ok: true, issues: ["Not supported in legacy mode"] }, + }; +}); + +// ignore ssl errors +app.commandLine.appendSwitch("ignore-certificate-errors"); + +// add support for showing an alert window via ipc +ipcMain.handle("alert", async (event, message) => { + return await dialog.showMessageBox(mainWindow, { + message: message, + }); +}); + +// add support for showing a confirm window via ipc +ipcMain.handle("confirm", async (event, message) => { + // show confirm dialog + const result = await dialog.showMessageBox(mainWindow, { + type: "question", + title: "Confirm", + message: message, + cancelId: 0, // esc key should press cancel button + defaultId: 1, // enter key should press ok button + buttons: [ + "Cancel", // 0 + "OK", // 1 + ], + }); + + // check if user clicked OK + return result.response === 1; +}); + +// add support for showing a prompt window via ipc +ipcMain.handle("prompt", async (event, message) => { + return await electronPrompt({ + title: message, + label: "", + value: "", + type: "input", + inputAttrs: { + type: "text", + }, + }); +}); + +// allow relaunching app via ipc +ipcMain.handle("relaunch", () => { + app.relaunch(); + app.exit(); +}); + +// allow showing a file path in os file manager +ipcMain.handle("showPathInFolder", (event, path) => { + shell.showItemInFolder(path); +}); + +function log(message) { + // log to stdout of this process + console.log(message); + + // make sure main window exists + if (!mainWindow) { + return; + } + + // make sure window is not destroyed + if (mainWindow.isDestroyed()) { + return; + } + + // log to web console + mainWindow.webContents.send("log", message); +} + +function getDefaultStorageDir() { + // if we are running a windows portable exe, we want to use .reticulum-meshchat in the portable exe dir + // e.g if we launch "E:\Some\Path\MeshChat.exe" we want to use "E:\Some\Path\.reticulum-meshchat" + const portableExecutableDir = process.env.PORTABLE_EXECUTABLE_DIR; + if (process.platform === "win32" && portableExecutableDir != null) { + return path.join(portableExecutableDir, ".reticulum-meshchat"); + } + + // otherwise, we will fall back to putting the storage dir in the users home directory + // e.g: ~/.reticulum-meshchat + return path.join(app.getPath("home"), ".reticulum-meshchat"); +} + +function getDefaultReticulumConfigDir() { + // if we are running a windows portable exe, we want to use .reticulum in the portable exe dir + // e.g if we launch "E:\Some\Path\MeshChat.exe" we want to use "E:\Some\Path\.reticulum" + const portableExecutableDir = process.env.PORTABLE_EXECUTABLE_DIR; + if (process.platform === "win32" && portableExecutableDir != null) { + return path.join(portableExecutableDir, ".reticulum"); + } + + // otherwise, we will fall back to using the .reticulum folder in the users home directory + // e.g: ~/.reticulum + return path.join(app.getPath("home"), ".reticulum"); +} + +app.whenReady().then(async () => { + // get arguments passed to application, and remove the provided application path + const ignoredArguments = ["--no-sandbox", "--ozone-platform-hint=auto"]; + const userProvidedArguments = process.argv.slice(1).filter((arg) => !ignoredArguments.includes(arg)); + const shouldLaunchHeadless = userProvidedArguments.includes("--headless"); + + if (!shouldLaunchHeadless) { + // create browser window + mainWindow = new BrowserWindow({ + width: 1500, + height: 800, + webPreferences: { + // used to inject logging over ipc + preload: path.join(__dirname, "preload.js"), + // Security: disable node integration in renderer + nodeIntegration: false, + // Security: enable context isolation (default in Electron 12+) + contextIsolation: true, + // Security: enable sandbox for additional protection + sandbox: true, + // Security: disable remote module (deprecated but explicit) + enableRemoteModule: false, + }, + }); + + // open external links in default web browser instead of electron + mainWindow.webContents.setWindowOpenHandler(({ url }) => { + var shouldShowInNewElectronWindow = false; + + // we want to open call.html in a new electron window + // but all other target="_blank" links should open in the system web browser + // we don't want /rnode-flasher/index.html to open in electron, otherwise user can't select usb devices... + if ( + (url.startsWith("http://localhost") || url.startsWith("https://localhost")) && + url.includes("/call.html") + ) { + shouldShowInNewElectronWindow = true; + } + + // we want to open blob urls in a new electron window + else if (url.startsWith("blob:")) { + shouldShowInNewElectronWindow = true; + } + + // open in new electron window + if (shouldShowInNewElectronWindow) { + return { + action: "allow", + }; + } + + // fallback to opening any other url in external browser + shell.openExternal(url); + return { + action: "deny", + }; + }); + + // navigate to loading page + await mainWindow.loadFile(path.join(__dirname, "loading.html")); + + // ask mac users for microphone access for audio calls to work + if (process.platform === "darwin") { + await systemPreferences.askForMediaAccess("microphone"); + } + } + + // find path to python/cxfreeze reticulum meshchatx executable + // Note: setup.py creates ReticulumMeshChatX (with X), not ReticulumMeshChat + const exeName = process.platform === "win32" ? "ReticulumMeshChatX.exe" : "ReticulumMeshChatX"; + + // get app path (handles both development and packaged app) + const appPath = app.getAppPath(); + // get resources path (where extraFiles are placed) + const resourcesPath = process.resourcesPath || path.join(appPath, "..", ".."); + var exe = null; + + // when packaged, extraFiles are placed at resources/app/electron/build/exe + // when packaged with asar, unpacked files are in app.asar.unpacked/ directory + // app.getAppPath() returns the path to app.asar, so unpacked is at the same level + const possiblePaths = [ + // packaged app - extraFiles location (resources/app/electron/build/exe) + path.join(resourcesPath, "app", "electron", "build", "exe", exeName), + // packaged app with asar (unpacked files from asarUnpack) + path.join(appPath, "..", "app.asar.unpacked", "build", "exe", exeName), + // packaged app without asar (relative to app path) + path.join(appPath, "build", "exe", exeName), + // development mode (relative to electron directory) + path.join(__dirname, "build", "exe", exeName), + // development mode (relative to project root) + path.join(__dirname, "..", "build", "exe", exeName), + ]; + + // find the first path that exists + for (const possibleExe of possiblePaths) { + if (fs.existsSync(possibleExe)) { + exe = possibleExe; + break; + } + } + + // verify executable exists + if (!exe || !fs.existsSync(exe)) { + const errorMsg = `Could not find executable: ${exeName}\nChecked paths:\n${possiblePaths.join("\n")}\n\nApp path: ${appPath}\nResources path: ${resourcesPath}`; + log(errorMsg); + if (mainWindow) { + await dialog.showMessageBox(mainWindow, { + message: errorMsg, + }); + } + app.quit(); + return; + } + + log(`Found executable at: ${exe}`); + + try { + // arguments we always want to pass in + const requiredArguments = [ + "--headless", // reticulum meshchatx usually launches default web browser, we don't want this when using electron + "--port", + "9337", // FIXME: let system pick a random unused port? + // '--test-exception-message', 'Test Exception Message', // uncomment to test the crash dialog + ]; + + // if user didn't provide reticulum config dir, we should provide it + if (!userProvidedArguments.includes("--reticulum-config-dir")) { + requiredArguments.push("--reticulum-config-dir", getDefaultReticulumConfigDir()); + } + + // if user didn't provide storage dir, we should provide it + if (!userProvidedArguments.includes("--storage-dir")) { + requiredArguments.push("--storage-dir", getDefaultStorageDir()); + } + + // spawn executable + exeChildProcess = await spawn(exe, [ + ...requiredArguments, // always provide required arguments + ...userProvidedArguments, // also include any user provided arguments + ]); + + // log stdout + var stdoutLines = []; + exeChildProcess.stdout.setEncoding("utf8"); + exeChildProcess.stdout.on("data", function (data) { + // log + log(data.toString()); + + // keep track of last 10 stdout lines + stdoutLines.push(data.toString()); + if (stdoutLines.length > 10) { + stdoutLines.shift(); + } + }); + + // log stderr + var stderrLines = []; + exeChildProcess.stderr.setEncoding("utf8"); + exeChildProcess.stderr.on("data", function (data) { + // log + log(data.toString()); + + // keep track of last 10 stderr lines + stderrLines.push(data.toString()); + if (stderrLines.length > 10) { + stderrLines.shift(); + } + }); + + // log errors + exeChildProcess.on("error", function (error) { + log(error); + }); + + // quit electron app if exe dies + exeChildProcess.on("exit", async function (code) { + // if no exit code provided, we wanted exit to happen, so do nothing + if (code == null) { + return; + } + + // tell user that Visual C++ redistributable needs to be installed on Windows + if (code === 3221225781 && process.platform === "win32") { + await dialog.showMessageBox(mainWindow, { + message: "Microsoft Visual C++ redistributable must be installed to run this application.", + }); + app.quit(); + return; + } + + // show crash log + const stdout = stdoutLines.join(""); + const stderr = stderrLines.join(""); + await dialog.showMessageBox(mainWindow, { + message: [ + "MeshChat Crashed!", + "", + `Exit Code: ${code}`, + "", + `----- stdout -----`, + "", + stdout, + `----- stderr -----`, + "", + stderr, + ].join("\n"), + }); + + // quit after dismissing error dialog + app.quit(); + }); + } catch (e) { + log(e); + } +}); + +function quit() { + // kill python process + if (exeChildProcess) { + exeChildProcess.kill("SIGKILL"); + } + + // quit electron app + app.quit(); +} + +// quit electron if all windows are closed +app.on("window-all-closed", () => { + quit(); +}); + +// make sure child process is killed if app is quiting +app.on("quit", () => { + quit(); +}); diff --git a/electron/main.js b/electron/main.js index b83619a..aec565e 100644 --- a/electron/main.js +++ b/electron/main.js @@ -1,20 +1,195 @@ -const { app, BrowserWindow, dialog, ipcMain, shell, systemPreferences } = require("electron"); +const { + app, + BrowserWindow, + dialog, + ipcMain, + shell, + systemPreferences, + Tray, + Menu, + Notification, + powerSaveBlocker, + session, +} = require("electron"); const electronPrompt = require("electron-prompt"); const { spawn } = require("child_process"); const fs = require("fs"); const path = require("node:path"); +const crypto = require("crypto"); + // remember main window var mainWindow = null; +// tray instance +var tray = null; + +// power save blocker id +var activePowerSaveBlockerId = null; + +// track if we are actually quiting +var isQuiting = false; + // remember child process for exe so we can kill it when app exits var exeChildProcess = null; +// store integrity status +var integrityStatus = { + backend: { ok: true, issues: [] }, + data: { ok: true, issues: [] }, +}; + +// Check for hardware acceleration preference in storage dir +try { + const storageDir = getDefaultStorageDir(); + const disableGpuFile = path.join(storageDir, "disable-gpu"); + if (fs.existsSync(disableGpuFile)) { + app.disableHardwareAcceleration(); + console.log("Hardware acceleration disabled via storage flag."); + } +} catch { + // ignore errors reading storage dir this early +} + +// Handle hardware acceleration disabling via CLI +if (process.argv.includes("--disable-gpu") || process.argv.includes("--disable-software-rasterizer")) { + app.disableHardwareAcceleration(); +} + +// Protocol registration +if (process.defaultApp) { + if (process.argv.length >= 2) { + app.setAsDefaultProtocolClient("lxmf", process.execPath, [path.resolve(process.argv[1])]); + app.setAsDefaultProtocolClient("rns", process.execPath, [path.resolve(process.argv[1])]); + } +} else { + app.setAsDefaultProtocolClient("lxmf"); + app.setAsDefaultProtocolClient("rns"); +} + +// Single instance lock +const gotTheLock = app.requestSingleInstanceLock(); +if (!gotTheLock) { + app.quit(); +} else { + app.on("second-instance", (event, commandLine) => { + // Someone tried to run a second instance, we should focus our window. + if (mainWindow) { + if (mainWindow.isMinimized()) mainWindow.restore(); + mainWindow.show(); + mainWindow.focus(); + + // Handle protocol links from second instance + const url = commandLine.pop(); + if (url && (url.startsWith("lxmf://") || url.startsWith("rns://"))) { + mainWindow.webContents.send("open-protocol-link", url); + } + } + }); +} + +// Handle protocol links on macOS +app.on("open-url", (event, url) => { + event.preventDefault(); + if (mainWindow) { + mainWindow.show(); + mainWindow.webContents.send("open-protocol-link", url); + } +}); + +function verifyBackendIntegrity(exeDir) { + const manifestPath = path.join(exeDir, "backend-manifest.json"); + if (!fs.existsSync(manifestPath)) { + log("Backend integrity manifest missing, skipping check."); + return { ok: true, issues: ["Manifest missing"] }; + } + + try { + const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8")); + const issues = []; + + const filesToVerify = manifest.files || manifest; + const metadata = manifest._metadata || {}; + + // The exeDir is build/exe when running or unpacked + // we only care about files in the manifest + for (const [relPath, expectedHash] of Object.entries(filesToVerify)) { + const fullPath = path.join(exeDir, relPath); + if (!fs.existsSync(fullPath)) { + issues.push(`Missing: ${relPath}`); + continue; + } + + const fileBuffer = fs.readFileSync(fullPath); + const actualHash = crypto.createHash("sha256").update(fileBuffer).digest("hex"); + if (actualHash !== expectedHash) { + issues.push(`Modified: ${relPath}`); + } + } + + if (issues.length > 0 && metadata.date && metadata.time) { + issues.unshift(`Backend build timestamp: ${metadata.date} ${metadata.time}`); + } + + return { + ok: issues.length === 0, + issues: issues, + }; + } catch (error) { + log(`Backend integrity check failed: ${error.message}`); + return { ok: false, issues: [error.message] }; + } +} + // allow fetching app version via ipc ipcMain.handle("app-version", () => { return app.getVersion(); }); +// allow fetching hardware acceleration status via ipc +ipcMain.handle("is-hardware-acceleration-enabled", () => { + return app.isHardwareAccelerationEnabled(); +}); + +// allow fetching integrity status +ipcMain.handle("get-integrity-status", () => { + return integrityStatus; +}); + +// Native Notification IPC +ipcMain.handle("show-notification", (event, { title, body, silent }) => { + const notification = new Notification({ + title: title, + body: body, + silent: silent, + }); + notification.show(); + + notification.on("click", () => { + if (mainWindow) { + mainWindow.show(); + mainWindow.focus(); + } + }); +}); + +// Power Management IPC +ipcMain.handle("set-power-save-blocker", (event, enabled) => { + if (enabled) { + if (activePowerSaveBlockerId === null) { + activePowerSaveBlockerId = powerSaveBlocker.start("prevent-app-suspension"); + log("Power save blocker started."); + } + } else { + if (activePowerSaveBlockerId !== null) { + powerSaveBlocker.stop(activePowerSaveBlockerId); + activePowerSaveBlockerId = null; + log("Power save blocker stopped."); + } + } + return activePowerSaveBlockerId !== null; +}); + // ignore ssl errors app.commandLine.appendSwitch("ignore-certificate-errors"); @@ -63,6 +238,19 @@ ipcMain.handle("relaunch", () => { app.exit(); }); +ipcMain.handle("relaunch-emergency", () => { + app.relaunch({ args: process.argv.slice(1).concat(["--emergency"]) }); + app.exit(); +}); + +ipcMain.handle("shutdown", () => { + quit(); +}); + +ipcMain.handle("get-memory-usage", async () => { + return process.getProcessMemoryInfo(); +}); + // allow showing a file path in os file manager ipcMain.handle("showPathInFolder", (event, path) => { shell.showItemInFolder(path); @@ -112,7 +300,79 @@ function getDefaultReticulumConfigDir() { return path.join(app.getPath("home"), ".reticulum"); } +function createTray() { + const iconPath = path.join(__dirname, "build", "icon.png"); + const fallbackIconPath = path.join(__dirname, "assets", "images", "logo.png"); + const trayIcon = fs.existsSync(iconPath) ? iconPath : fallbackIconPath; + + tray = new Tray(trayIcon); + const contextMenu = Menu.buildFromTemplate([ + { + label: "Show App", + click: function () { + if (mainWindow) { + mainWindow.show(); + } + }, + }, + { + label: "Quit", + click: function () { + isQuiting = true; + quit(); + }, + }, + ]); + + tray.setToolTip("Reticulum MeshChatX"); + tray.setContextMenu(contextMenu); + + tray.on("click", () => { + if (mainWindow) { + if (mainWindow.isVisible()) { + mainWindow.hide(); + } else { + mainWindow.show(); + } + } + }); +} + app.whenReady().then(async () => { + // Security: Enforce CSP for all requests as a shell-level fallback + session.defaultSession.webRequest.onHeadersReceived((details, callback) => { + const responseHeaders = { ...details.responseHeaders }; + + // Define a robust fallback CSP that matches our backend's policy + const fallbackCsp = [ + "default-src 'self'", + "script-src 'self' 'unsafe-inline' 'unsafe-eval'", + "style-src 'self' 'unsafe-inline'", + "img-src 'self' data: blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://*.cartocdn.com", + "font-src 'self' data:", + "connect-src 'self' http://localhost:9337 https://localhost:9337 ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org https://git.quad4.io https://*.cartocdn.com", + "media-src 'self' blob:", + "worker-src 'self' blob:", + "frame-src 'self'", + "object-src 'none'", + "base-uri 'self'", + ].join("; "); + + // If the response doesn't already have a CSP, apply our fallback + if (!responseHeaders["Content-Security-Policy"] && !responseHeaders["content-security-policy"]) { + responseHeaders["Content-Security-Policy"] = [fallbackCsp]; + } + + callback({ responseHeaders }); + }); + + // Log Hardware Acceleration status (New in Electron 39) + const isHardwareAccelerationEnabled = app.isHardwareAccelerationEnabled(); + log(`Hardware Acceleration Enabled: ${isHardwareAccelerationEnabled}`); + + // Create system tray + createTray(); + // get arguments passed to application, and remove the provided application path const ignoredArguments = ["--no-sandbox", "--ozone-platform-hint=auto"]; const userProvidedArguments = process.argv.slice(1).filter((arg) => !ignoredArguments.includes(arg)); @@ -137,6 +397,15 @@ app.whenReady().then(async () => { }, }); + // minimize to tray behavior + mainWindow.on("close", (event) => { + if (!isQuiting) { + event.preventDefault(); + mainWindow.hide(); + return false; + } + }); + // open external links in default web browser instead of electron mainWindow.webContents.setWindowOpenHandler(({ url }) => { var shouldShowInNewElectronWindow = false; @@ -160,6 +429,16 @@ app.whenReady().then(async () => { if (shouldShowInNewElectronWindow) { return { action: "allow", + overrideBrowserWindowOptions: { + autoHideMenuBar: true, + webPreferences: { + preload: path.join(__dirname, "preload.js"), + nodeIntegration: false, + contextIsolation: true, + sandbox: true, + enableRemoteModule: false, + }, + }, }; } @@ -179,7 +458,7 @@ app.whenReady().then(async () => { } } - // find path to python/cxfreeze reticulum meshchat executable + // find path to python/cxfreeze reticulum meshchatx executable // Note: setup.py creates ReticulumMeshChatX (with X), not ReticulumMeshChat const exeName = process.platform === "win32" ? "ReticulumMeshChatX.exe" : "ReticulumMeshChatX"; @@ -189,11 +468,16 @@ app.whenReady().then(async () => { const resourcesPath = process.resourcesPath || path.join(appPath, "..", ".."); var exe = null; - // when packaged, extraFiles are placed at resources/app/electron/build/exe + // when packaged, extraResources are placed at resources/backend + // when packaged with extraFiles, they were at resources/app/electron/build/exe // when packaged with asar, unpacked files are in app.asar.unpacked/ directory // app.getAppPath() returns the path to app.asar, so unpacked is at the same level const possiblePaths = [ - // packaged app - extraFiles location (resources/app/electron/build/exe) + // packaged app - extraResources location (resources/backend) + path.join(resourcesPath, "backend", exeName), + // electron-forge extraResource location (resources/exe) + path.join(resourcesPath, "exe", exeName), + // legacy packaged app - extraFiles location (resources/app/electron/build/exe) path.join(resourcesPath, "app", "electron", "build", "exe", exeName), // packaged app with asar (unpacked files from asarUnpack) path.join(appPath, "..", "app.asar.unpacked", "build", "exe", exeName), @@ -228,10 +512,17 @@ app.whenReady().then(async () => { log(`Found executable at: ${exe}`); + // Verify backend integrity before spawning + const exeDir = path.dirname(exe); + integrityStatus.backend = verifyBackendIntegrity(exeDir); + if (!integrityStatus.backend.ok) { + log(`INTEGRITY WARNING: Backend tampering detected! Issues: ${integrityStatus.backend.issues.join(", ")}`); + } + try { // arguments we always want to pass in const requiredArguments = [ - "--headless", // reticulum meshchat usually launches default web browser, we don't want this when using electron + "--headless", // reticulum meshchatx usually launches default web browser, we don't want this when using electron "--port", "9337", // FIXME: let system pick a random unused port? // '--test-exception-message', 'Test Exception Message', // uncomment to test the crash dialog @@ -260,9 +551,9 @@ app.whenReady().then(async () => { // log log(data.toString()); - // keep track of last 10 stdout lines + // keep track of last 100 stdout lines stdoutLines.push(data.toString()); - if (stdoutLines.length > 10) { + if (stdoutLines.length > 100) { stdoutLines.shift(); } }); @@ -274,9 +565,9 @@ app.whenReady().then(async () => { // log log(data.toString()); - // keep track of last 10 stderr lines + // keep track of last 100 stderr lines stderrLines.push(data.toString()); - if (stderrLines.length > 10) { + if (stderrLines.length > 100) { stderrLines.shift(); } }); @@ -293,35 +584,34 @@ app.whenReady().then(async () => { return; } - // tell user that Visual C++ redistributable needs to be installed on Windows - if (code === 3221225781 && process.platform === "win32") { - await dialog.showMessageBox(mainWindow, { - message: "Microsoft Visual C++ redistributable must be installed to run this application.", - }); - app.quit(); - return; - } - // show crash log const stdout = stdoutLines.join(""); const stderr = stderrLines.join(""); - await dialog.showMessageBox(mainWindow, { - message: [ - "MeshChat Crashed!", - "", - `Exit Code: ${code}`, - "", - `----- stdout -----`, - "", - stdout, - `----- stderr -----`, - "", - stderr, - ].join("\n"), - }); - // quit after dismissing error dialog - app.quit(); + // Base64 encode for safe URL passing + const stdoutBase64 = Buffer.from(stdout).toString("base64"); + const stderrBase64 = Buffer.from(stderr).toString("base64"); + + // Load crash page if main window exists + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.show(); // Ensure visible + mainWindow.focus(); + await mainWindow.loadFile(path.join(__dirname, "crash.html"), { + query: { + code: code.toString(), + stdout: stdoutBase64, + stderr: stderrBase64, + }, + }); + } else { + // Fallback for cases where window is gone + await dialog.showMessageBox({ + type: "error", + title: "MeshChatX Crashed", + message: `Backend exited with code: ${code}\n\nSTDOUT: ${stdout.slice(-500)}\n\nSTDERR: ${stderr.slice(-500)}`, + }); + app.quit(); + } }); } catch (e) { log(e); diff --git a/electron/preload.js b/electron/preload.js index d677747..5b2ec3d 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -9,6 +9,21 @@ contextBridge.exposeInMainWorld("electron", { return await ipcRenderer.invoke("app-version"); }, + // allow fetching electron version + electronVersion: function () { + return process.versions.electron; + }, + + // allow fetching chrome version + chromeVersion: function () { + return process.versions.chrome; + }, + + // allow fetching node version + nodeVersion: function () { + return process.versions.node; + }, + // show an alert dialog in electron browser window, this fixes a bug where alert breaks input fields on windows alert: async function (message) { return await ipcRenderer.invoke("alert", message); @@ -29,8 +44,43 @@ contextBridge.exposeInMainWorld("electron", { return await ipcRenderer.invoke("relaunch"); }, + // allow relaunching app in emergency mode + relaunchEmergency: async function () { + return await ipcRenderer.invoke("relaunch-emergency"); + }, + + // allow shutting down app in electron browser window + shutdown: async function () { + return await ipcRenderer.invoke("shutdown"); + }, + + // allow getting memory usage in electron browser window + getMemoryUsage: async function () { + return await ipcRenderer.invoke("get-memory-usage"); + }, + // allow showing a file path in os file manager showPathInFolder: async function (path) { return await ipcRenderer.invoke("showPathInFolder", path); }, + // allow checking hardware acceleration status + isHardwareAccelerationEnabled: async function () { + return await ipcRenderer.invoke("is-hardware-acceleration-enabled"); + }, + // allow checking integrity status + getIntegrityStatus: async function () { + return await ipcRenderer.invoke("get-integrity-status"); + }, + // allow showing a native notification + showNotification: function (title, body, silent = false) { + ipcRenderer.invoke("show-notification", { title, body, silent }); + }, + // allow controlling power save blocker + setPowerSaveBlocker: async function (enabled) { + return await ipcRenderer.invoke("set-power-save-blocker", enabled); + }, + // listen for protocol links + onProtocolLink: function (callback) { + ipcRenderer.on("open-protocol-link", (event, url) => callback(url)); + }, }); diff --git a/eslint.config.mjs b/eslint.config.mjs index 58003ea..7e3bf46 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -9,6 +9,12 @@ export default [ "**/node_modules/**", "**/dist/**", "**/build/**", + "**/out/**", + "**/android/**", + "**/MagicMock/**", + "**/reticulum_meshchatx.egg-info/**", + "**/meshchat-config/**", + "**/screenshots/**", "**/electron/assets/**", "**/meshchatx/public/**", "**/meshchatx/src/frontend/public/**", @@ -26,7 +32,7 @@ export default [ "**/*.wasm", "**/*.proto", "**/tests/**", - "**/tests/frontend/**", + "**/.pnpm-store/**", ], }, { diff --git a/flake.nix b/flake.nix index 4b1f605..97b3207 100644 --- a/flake.nix +++ b/flake.nix @@ -53,9 +53,6 @@ gradle openjdk17 - # Flatpak Packaging - flatpak-builder - # Containerization docker docker-compose @@ -77,7 +74,7 @@ # Simple package definition for the backend packages.default = pkgs.python312Packages.buildPythonPackage { pname = "reticulum-meshchatx"; - version = "3.3.2"; + version = "4.0.0"; src = ./.; format = "pyproject"; diff --git a/flatpak-build.sh b/flatpak-build.sh deleted file mode 100755 index 35b704c..0000000 --- a/flatpak-build.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash -set -e - -export HOME=/tmp/build -export XDG_CONFIG_HOME=/tmp/build/.config -export XDG_DATA_HOME=/tmp/build/.local/share -mkdir -p /tmp/build/.config /tmp/build/.local/share - -NODE_PATHS=( - "/usr/lib/sdk/node20/bin" - "/usr/lib/sdk/node20/root/usr/bin" - "/usr/lib/sdk/node/bin" - "/usr/lib/sdk/node/root/usr/bin" -) - -NODE_BIN="" -NPM_BIN="" - -for path in "${NODE_PATHS[@]}"; do - if [ -f "$path/node" ] && [ -f "$path/npm" ]; then - NODE_BIN="$path/node" - NPM_BIN="$path/npm" - export PATH="$path:$PATH" - break - fi -done - -if [ -z "$NODE_BIN" ] || [ -z "$NPM_BIN" ]; then - if command -v node >/dev/null 2>&1 && command -v npm >/dev/null 2>&1; then - NODE_BIN=$(command -v node) - NPM_BIN=$(command -v npm) - else - echo "Error: Node.js binaries not found. Checking common locations..." - find /usr/lib/sdk -name node -type f 2>/dev/null | head -1 - find /usr/lib/sdk -name npm -type f 2>/dev/null | head -1 - exit 1 - fi -fi - -echo "Using Node.js: $NODE_BIN" -echo "Using npm: $NPM_BIN" - -PNPM_VERSION="10.0.0" -NPM_PREFIX="$HOME/.local" -mkdir -p "$NPM_PREFIX" - -export npm_config_prefix="$NPM_PREFIX" -$NPM_BIN config set prefix "$NPM_PREFIX" - -echo "Installing pnpm via npm to $NPM_PREFIX..." -$NPM_BIN install -g pnpm@${PNPM_VERSION} || exit 1 - -export PATH="$NPM_PREFIX/bin:$PATH" - -python3 scripts/sync_version.py - -pnpm install --frozen-lockfile -pnpm run build - -mkdir -p /tmp/electron-install -cd /tmp/electron-install -pnpm init -pnpm add electron@39.2.7 -cd - - -pip3 install poetry -poetry install --no-dev -poetry run python cx_setup.py build - -mkdir -p /app/bin /app/lib/reticulum-meshchatx /app/share/applications /app/share/icons/hicolor/512x512/apps - -cp -r electron /app/lib/reticulum-meshchatx/ -cp -r build/exe /app/lib/reticulum-meshchatx/ -mkdir -p /app/lib/reticulum-meshchatx/electron-bin -cp -r /tmp/electron-install/node_modules/electron/* /app/lib/reticulum-meshchatx/electron-bin/ -cp logo/logo.png /app/share/icons/hicolor/512x512/apps/com.sudoivan.reticulummeshchat.png - -cat > /app/share/applications/com.sudoivan.reticulummeshchat.desktop <<'EOF' -[Desktop Entry] -Type=Application -Name=Reticulum MeshChatX -Comment=A simple mesh network communications app powered by the Reticulum Network Stack -Exec=reticulum-meshchatx -Icon=com.sudoivan.reticulummeshchat -Categories=Network;InstantMessaging; -StartupNotify=true -EOF - -cat > /app/bin/reticulum-meshchatx <<'EOF' -#!/bin/sh -export ELECTRON_IS_DEV=0 -export APP_PATH=/app/lib/reticulum-meshchatx/electron -export EXE_PATH=/app/lib/reticulum-meshchatx/build/exe/ReticulumMeshChatX -ELECTRON_BIN=/app/lib/reticulum-meshchatx/electron-bin/dist/electron -if [ ! -f "$ELECTRON_BIN" ]; then - ELECTRON_BIN=$(find /app/lib/reticulum-meshchatx/electron-bin -name electron -type f 2>/dev/null | head -1) -fi -cd /app/lib/reticulum-meshchatx/electron -exec "$ELECTRON_BIN" . "$@" -EOF - -chmod +x /app/bin/reticulum-meshchatx - diff --git a/flatpak.json b/flatpak.json deleted file mode 100644 index 29e19fd..0000000 --- a/flatpak.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "app-id": "com.sudoivan.reticulummeshchatx", - "runtime": "org.freedesktop.Platform", - "runtime-version": "24.08", - "sdk": "org.freedesktop.Sdk", - "sdk-extensions": ["org.freedesktop.Sdk.Extension.node20"], - "build-options": { - "env": { - "PYTHON": "/usr/bin/python3" - } - }, - "command": "reticulum-meshchatx", - "finish-args": [ - "--share=network", - "--socket=wayland", - "--socket=x11", - "--socket=pulseaudio", - "--device=all", - "--filesystem=home", - "--filesystem=host", - "--talk-name=org.freedesktop.NetworkManager", - "--talk-name=org.freedesktop.secrets" - ], - "modules": [ - { - "name": "reticulum-meshchatx", - "buildsystem": "simple", - "build-commands": ["bash flatpak-build.sh"], - "sources": [ - { - "type": "dir", - "path": "." - } - ] - } - ] -} diff --git a/forge.config.js b/forge.config.js new file mode 100644 index 0000000..2969b81 --- /dev/null +++ b/forge.config.js @@ -0,0 +1,74 @@ +const { FusesPlugin } = require("@electron-forge/plugin-fuses"); +const { FuseV1Options, FuseVersion } = require("@electron/fuses"); + +const platform = process.env.PLATFORM || process.platform; +const extraResourceDir = platform === "win32" || platform === "win" ? "build/exe/win32" : "build/exe/linux"; + +module.exports = { + packagerConfig: { + asar: true, + extraResource: [extraResourceDir], + executableName: "reticulum-meshchatx", + name: "Reticulum MeshChatX", + appBundleId: "com.sudoivan.reticulummeshchatx", + icon: "electron/build/icon", + // osxSign: {}, // Uncomment and configure for macOS signing + // osxNotarize: { ... }, // Uncomment and configure for macOS notarization + }, + rebuildConfig: {}, + makers: [ + { + name: "@electron-forge/maker-squirrel", + config: { + name: "reticulum_meshchatx", + }, + }, + { + name: "@electron-forge/maker-zip", + }, + { + name: "@electron-forge/maker-deb", + config: { + options: { + maintainer: "Sudo-Ivan", + homepage: "https://git.quad4.io/RNS-Things/MeshChatX", + categories: ["Network"], + }, + }, + }, + { + name: "@electron-forge/maker-rpm", + config: {}, + }, + { + name: "@electron-forge/maker-flatpak", + config: { + options: { + categories: ["Network"], + runtime: "org.freedesktop.Platform", + runtimeVersion: "24.08", + sdk: "org.freedesktop.Sdk", + base: "org.electronjs.Electron2.BaseApp", + baseVersion: "24.08", + }, + }, + }, + ], + plugins: [ + { + name: "@electron-forge/plugin-auto-unpack-natives", + config: {}, + }, + // Fuses are used to enable/disable various Electron functionality + // at package time, before code signing the application + new FusesPlugin({ + version: FuseVersion.V1, + [FuseV1Options.RunAsNode]: false, + [FuseV1Options.EnableCookieEncryption]: true, + [FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false, + [FuseV1Options.EnableNodeCliInspectArguments]: false, + [FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true, + [FuseV1Options.OnlyLoadAppFromAsar]: true, + }), + ], +}; diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py index 190932e..ab5b792 100644 --- a/meshchatx/meshchat.py +++ b/meshchatx/meshchat.py @@ -8,9 +8,10 @@ import configparser import copy import gc import hashlib -import io +import importlib.metadata import ipaddress import json +import logging import os import platform import secrets @@ -23,33 +24,16 @@ import threading import time import traceback import webbrowser -import zipfile -from collections.abc import Callable from datetime import UTC, datetime, timedelta +from logging.handlers import RotatingFileHandler +from urllib.parse import urlparse +import aiohttp import bcrypt import LXMF import LXST import psutil import RNS - -# Patch LXST LinkSource to have a samplerate attribute if missing -# This avoids AttributeError in sinks that expect it -try: - import LXST.Network - - if hasattr(LXST.Network, "LinkSource"): - original_init = LXST.Network.LinkSource.__init__ - - def patched_init(self, *args, **kwargs): - self.samplerate = 48000 # Default fallback - original_init(self, *args, **kwargs) - - LXST.Network.LinkSource.__init__ = patched_init -except Exception as e: - print(f"Failed to patch LXST LinkSource: {e}") - -import RNS.vendor.umsgpack as msgpack from aiohttp import WSCloseCode, WSMessage, WSMsgType, web from aiohttp_session import get_session from aiohttp_session import setup as setup_session @@ -59,17 +43,13 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.x509.oid import NameOID -from LXMF import LXMRouter +from RNS.Discovery import InterfaceDiscovery from serial.tools import list_ports -from meshchatx.src.backend.announce_handler import AnnounceHandler -from meshchatx.src.backend.announce_manager import AnnounceManager -from meshchatx.src.backend.archiver_manager import ArchiverManager from meshchatx.src.backend.async_utils import AsyncUtils from meshchatx.src.backend.colour_utils import ColourUtils -from meshchatx.src.backend.config_manager import ConfigManager -from meshchatx.src.backend.database import Database -from meshchatx.src.backend.forwarding_manager import ForwardingManager +from meshchatx.src.backend.identity_context import IdentityContext +from meshchatx.src.backend.identity_manager import IdentityManager from meshchatx.src.backend.interface_config_parser import InterfaceConfigParser from meshchatx.src.backend.interface_editor import InterfaceEditor from meshchatx.src.backend.lxmf_message_fields import ( @@ -78,20 +58,94 @@ from meshchatx.src.backend.lxmf_message_fields import ( LxmfFileAttachmentsField, LxmfImageField, ) -from meshchatx.src.backend.map_manager import MapManager -from meshchatx.src.backend.message_handler import MessageHandler -from meshchatx.src.backend.ringtone_manager import RingtoneManager -from meshchatx.src.backend.rncp_handler import RNCPHandler +from meshchatx.src.backend.lxmf_utils import ( + convert_db_lxmf_message_to_dict, + convert_lxmf_message_to_dict, +) +from meshchatx.src.backend.map_manager import TRANSPARENT_TILE +from meshchatx.src.backend.markdown_renderer import MarkdownRenderer +from meshchatx.src.backend.meshchat_utils import ( + convert_db_favourite_to_dict, + convert_propagation_node_state_to_string, + has_attachments, + message_fields_have_attachments, + parse_bool_query_param, + parse_lxmf_display_name, + parse_lxmf_propagation_node_app_data, + parse_lxmf_stamp_cost, + parse_nomadnetwork_node_display_name, +) +from meshchatx.src.backend.nomadnet_downloader import ( + NomadnetFileDownloader, + NomadnetPageDownloader, + nomadnet_cached_links, +) +from meshchatx.src.backend.nomadnet_utils import ( + convert_nomadnet_field_data_to_map, + convert_nomadnet_string_data_to_map, +) +from meshchatx.src.backend.persistent_log_handler import PersistentLogHandler +from meshchatx.src.backend.recovery import CrashRecovery from meshchatx.src.backend.rnprobe_handler import RNProbeHandler -from meshchatx.src.backend.rnstatus_handler import RNStatusHandler from meshchatx.src.backend.sideband_commands import SidebandCommands from meshchatx.src.backend.telemetry_utils import Telemeter -from meshchatx.src.backend.telephone_manager import TelephoneManager -from meshchatx.src.backend.translator_handler import TranslatorHandler -from meshchatx.src.backend.voicemail_manager import VoicemailManager +from meshchatx.src.backend.web_audio_bridge import WebAudioBridge from meshchatx.src.version import __version__ as app_version +def resolve_log_dir(): + """Choose a writable log directory across container, desktop, and Windows.""" + env_dir = os.environ.get("MESHCHAT_LOG_DIR") + candidates = [] + if env_dir: + candidates.append(env_dir) + + candidates.append("/config/logs") + + if os.name == "nt": + appdata = os.environ.get("LOCALAPPDATA") or os.environ.get("APPDATA") + if appdata: + candidates.append(os.path.join(appdata, "MeshChatX", "logs")) + + home_dir = os.path.expanduser("~") + candidates.append(os.path.join(home_dir, ".reticulum-meshchatx", "logs")) + candidates.append(os.path.join(tempfile.gettempdir(), "meshchatx", "logs")) + + for path in candidates: + if not path: + continue + try: + os.makedirs(path, exist_ok=True) + return path + except PermissionError: + continue + except OSError: + continue + + return None + + +# Global log handler +memory_log_handler = PersistentLogHandler() +log_dir = resolve_log_dir() +handlers = [memory_log_handler] + +if log_dir: + file_handler = RotatingFileHandler( + os.path.join(log_dir, "meshchatx.log"), + maxBytes=5 * 1024 * 1024, + backupCount=3, + encoding="utf-8", + ) + handlers.append(file_handler) +else: + handlers.append(logging.StreamHandler(sys.stdout)) + +logging.basicConfig(level=logging.INFO, handlers=handlers) +logging.getLogger("aiohttp.access").setLevel(logging.WARNING) +logger = logging.getLogger("meshchatx") + + # NOTE: this is required to be able to pack our app with cxfreeze as an exe, otherwise it can't access bundled assets # this returns a file path based on if we are running meshchat.py directly, or if we have packed it as an exe with cxfreeze # https://cx-freeze.readthedocs.io/en/latest/faq.html#using-data-files @@ -193,24 +247,21 @@ class ReticulumMeshChat: auto_recover: bool = False, identity_file_path: str | None = None, auth_enabled: bool = False, + public_dir: str | None = None, + emergency: bool = False, + gitea_base_url: str | None = None, + docs_download_urls: str | None = None, ): - self.running = True - self.reticulum_config_dir = reticulum_config_dir - # when providing a custom storage_dir, files will be saved as - # /identities// - # /identities//database.db - - # if storage_dir is not provided, we will use ./storage instead - # ./storage/identities// - # ./storage/identities//database.db - - # ensure a storage path exists for the loaded identity self.running = True self.reticulum_config_dir = reticulum_config_dir self.storage_dir = storage_dir or os.path.join("storage") self.identity_file_path = identity_file_path self.auto_recover = auto_recover + self.emergency = emergency self.auth_enabled_initial = auth_enabled + self.public_dir_override = public_dir + self.gitea_base_url_override = gitea_base_url + self.docs_download_urls_override = docs_download_urls self.websocket_clients: list[web.WebSocketResponse] = [] # track announce timestamps for rate calculation @@ -223,422 +274,327 @@ class ReticulumMeshChat: self.active_downloads = {} self.download_id_counter = 0 + self.identity_manager = IdentityManager(self.storage_dir, identity_file_path) + + # Multi-identity support + self.contexts: dict[str, IdentityContext] = {} + self.current_context: IdentityContext | None = None + self.setup_identity(identity) + self.web_audio_bridge = WebAudioBridge(None, None) + + # Proxy properties for backward compatibility + @property + def identity(self): + return self.current_context.identity if self.current_context else None + + @identity.setter + def identity(self, value): + if self.current_context: + self.current_context.identity = value + + @property + def database(self): + return self.current_context.database if self.current_context else None + + @database.setter + def database(self, value): + if self.current_context: + self.current_context.database = value + + @property + def db(self): + return self.database + + @db.setter + def db(self, value): + self.database = value + + @property + def config(self): + return self.current_context.config if self.current_context else None + + @config.setter + def config(self, value): + if self.current_context: + self.current_context.config = value + + @property + def message_handler(self): + return self.current_context.message_handler if self.current_context else None + + @message_handler.setter + def message_handler(self, value): + if self.current_context: + self.current_context.message_handler = value + + @property + def announce_manager(self): + return self.current_context.announce_manager if self.current_context else None + + @announce_manager.setter + def announce_manager(self, value): + if self.current_context: + self.current_context.announce_manager = value + + @property + def archiver_manager(self): + return self.current_context.archiver_manager if self.current_context else None + + @archiver_manager.setter + def archiver_manager(self, value): + if self.current_context: + self.current_context.archiver_manager = value + + @property + def map_manager(self): + return self.current_context.map_manager if self.current_context else None + + @map_manager.setter + def map_manager(self, value): + if self.current_context: + self.current_context.map_manager = value + + @property + def docs_manager(self): + return self.current_context.docs_manager if self.current_context else None + + @docs_manager.setter + def docs_manager(self, value): + if self.current_context: + self.current_context.docs_manager = value + + @property + def nomadnet_manager(self): + return self.current_context.nomadnet_manager if self.current_context else None + + @nomadnet_manager.setter + def nomadnet_manager(self, value): + if self.current_context: + self.current_context.nomadnet_manager = value + + @property + def message_router(self): + return self.current_context.message_router if self.current_context else None + + @message_router.setter + def message_router(self, value): + if self.current_context: + self.current_context.message_router = value + + @property + def telephone_manager(self): + return self.current_context.telephone_manager if self.current_context else None + + @telephone_manager.setter + def telephone_manager(self, value): + if self.current_context: + self.current_context.telephone_manager = value + + @property + def voicemail_manager(self): + return self.current_context.voicemail_manager if self.current_context else None + + @voicemail_manager.setter + def voicemail_manager(self, value): + if self.current_context: + self.current_context.voicemail_manager = value + + @property + def ringtone_manager(self): + return self.current_context.ringtone_manager if self.current_context else None + + @ringtone_manager.setter + def ringtone_manager(self, value): + if self.current_context: + self.current_context.ringtone_manager = value + + @property + def rncp_handler(self): + return self.current_context.rncp_handler if self.current_context else None + + @rncp_handler.setter + def rncp_handler(self, value): + if self.current_context: + self.current_context.rncp_handler = value + + @property + def rnstatus_handler(self): + return self.current_context.rnstatus_handler if self.current_context else None + + @rnstatus_handler.setter + def rnstatus_handler(self, value): + if self.current_context: + self.current_context.rnstatus_handler = value + + @property + def rnpath_handler(self): + return self.current_context.rnpath_handler if self.current_context else None + + @rnpath_handler.setter + def rnpath_handler(self, value): + if self.current_context: + self.current_context.rnpath_handler = value + + @property + def rnpath_trace_handler(self): + return ( + self.current_context.rnpath_trace_handler if self.current_context else None + ) + + @rnpath_trace_handler.setter + def rnpath_trace_handler(self, value): + if self.current_context: + self.current_context.rnpath_trace_handler = value + + @property + def rnprobe_handler(self): + return self.current_context.rnprobe_handler if self.current_context else None + + @rnprobe_handler.setter + def rnprobe_handler(self, value): + if self.current_context: + self.current_context.rnprobe_handler = value + + @property + def translator_handler(self): + return self.current_context.translator_handler if self.current_context else None + + @translator_handler.setter + def translator_handler(self, value): + if self.current_context: + self.current_context.translator_handler = value + + @property + def bot_handler(self): + return self.current_context.bot_handler if self.current_context else None + + @bot_handler.setter + def bot_handler(self, value): + if self.current_context: + self.current_context.bot_handler = value + + @property + def forwarding_manager(self): + return self.current_context.forwarding_manager if self.current_context else None + + @forwarding_manager.setter + def forwarding_manager(self, value): + if self.current_context: + self.current_context.forwarding_manager = value + + @property + def community_interfaces_manager(self): + return ( + self.current_context.community_interfaces_manager + if self.current_context + else None + ) + + @community_interfaces_manager.setter + def community_interfaces_manager(self, value): + if self.current_context: + self.current_context.community_interfaces_manager = value + + @property + def local_lxmf_destination(self): + return ( + self.current_context.local_lxmf_destination + if self.current_context + else None + ) + + @local_lxmf_destination.setter + def local_lxmf_destination(self, value): + if self.current_context: + self.current_context.local_lxmf_destination = value + + @property + def auth_enabled(self): + if self.config: + return self.config.auth_enabled.get() + return self.auth_enabled_initial + + @property + def storage_path(self): + return ( + self.current_context.storage_path + if self.current_context + else self.storage_dir + ) + + @storage_path.setter + def storage_path(self, value): + if self.current_context: + self.current_context.storage_path = value + + @property + def database_path(self): + return self.current_context.database_path if self.current_context else None + + @property + def _identity_session_id(self): + return self.current_context.session_id if self.current_context else 0 + + @_identity_session_id.setter + def _identity_session_id(self, value): + if self.current_context: + self.current_context.session_id = value + + def get_public_path(self, filename=""): + if self.public_dir_override: + return os.path.join(self.public_dir_override, filename) + return get_file_path(os.path.join("public", filename)) + + def backup_database(self, backup_path=None): + if not self.database: + raise RuntimeError("Database not initialized") + return self.database.backup_database(self.storage_dir, backup_path) + + def restore_database(self, backup_path): + if not self.database: + raise RuntimeError("Database not initialized") + return self.database.restore_database(backup_path) def setup_identity(self, identity: RNS.Identity): - # assign a unique session ID to this identity instance to help background threads exit - if not hasattr(self, "_identity_session_id"): - self._identity_session_id = 0 - self._identity_session_id += 1 - session_id = self._identity_session_id + identity_hash = identity.hash.hex() - # ensure a storage path exists for the loaded identity - self.storage_path = os.path.join( - self.storage_dir, - "identities", - identity.hash.hex(), - ) - print(f"Using Storage Path: {self.storage_path}") - os.makedirs(self.storage_path, exist_ok=True) + self.running = True - # Safety: Before setting up a new identity, ensure no destinations for this identity - # are currently registered in Transport. This prevents the "Attempt to register - # an already registered destination" error during hotswap. - self.cleanup_rns_state_for_identity(identity.hash) - - # ensure identity is saved in its specific directory for multi-identity support - identity_backup_file = os.path.join(self.storage_path, "identity") - if not os.path.exists(identity_backup_file): - with open(identity_backup_file, "wb") as f: - f.write(identity.get_private_key()) - - # define path to files based on storage path - self.database_path = os.path.join(self.storage_path, "database.db") - lxmf_router_path = os.path.join(self.storage_path, "lxmf_router") - - # init database - self.database = Database(self.database_path) - self.db = ( - self.database - ) # keep for compatibility with parts I haven't changed yet - - try: - self.database.initialize() - # Try to auto-migrate from legacy database if this is a fresh start - self.database.migrate_from_legacy( - self.reticulum_config_dir, - identity.hash.hex(), + # Check if we already have a context for this identity + if identity_hash in self.contexts: + self.current_context = self.contexts[identity_hash] + if not self.current_context.running: + self.current_context.setup() + self.web_audio_bridge = WebAudioBridge( + self.current_context.telephone_manager, + self.current_context.config, ) - self._tune_sqlite_pragmas() - except Exception as exc: - if not self.auto_recover: - raise + return - print(f"Database initialization failed, attempting auto recovery: {exc}") - self._run_startup_auto_recovery() - # retry once after recovery - self.database.initialize() - self._tune_sqlite_pragmas() - - # init config - self.config = ConfigManager(self.database) - - # init managers - self.message_handler = MessageHandler(self.database) - self.announce_manager = AnnounceManager(self.database) - self.archiver_manager = ArchiverManager(self.database) - self.map_manager = MapManager(self.config, self.storage_dir) - self.forwarding_manager = None # will init after lxmf router - - # remember if authentication is enabled - self.auth_enabled = self.auth_enabled_initial or self.config.auth_enabled.get() - - # migrate database - # The new initialize() handles migrations automatically, but we still update the config if needed - self.config.database_version.set(self.database.schema.LATEST_VERSION) - - # vacuum database on start to shrink its file size - self.database.provider.vacuum() - - # lxmf messages in outbound or sending state should be marked as failed when app starts as they are no longer being processed - self.database.messages.mark_stuck_messages_as_failed() - - # init reticulum + # Initialize Reticulum if not already done if not hasattr(self, "reticulum"): self.reticulum = RNS.Reticulum(self.reticulum_config_dir) - self.identity = identity - # init lxmf router - # get propagation node stamp cost from config (only used if running a propagation node) - propagation_stamp_cost = self.config.lxmf_propagation_node_stamp_cost.get() - self.message_router = LXMF.LXMRouter( - identity=self.identity, - storagepath=lxmf_router_path, - propagation_cost=propagation_stamp_cost, - ) - self.message_router.PROCESSING_INTERVAL = 1 - - # increase limit for incoming lxmf messages (received over a resource), to allow receiving larger attachments - # the lxmf router expects delivery_per_transfer_limit to be provided in kilobytes, so we will do that... - self.message_router.delivery_per_transfer_limit = ( - self.config.lxmf_delivery_transfer_limit_in_bytes.get() / 1000 + # Create new context + context = IdentityContext(identity, self) + self.contexts[identity_hash] = context + self.current_context = context + context.setup() + self.web_audio_bridge = WebAudioBridge( + context.telephone_manager, + context.config, ) - # register lxmf identity - inbound_stamp_cost = self.config.lxmf_inbound_stamp_cost.get() - self.local_lxmf_destination = self.message_router.register_delivery_identity( - identity=self.identity, - display_name=self.config.display_name.get(), - stamp_cost=inbound_stamp_cost, - ) - - # load and register all forwarding alias identities - self.forwarding_manager = ForwardingManager( - self.database, - lxmf_router_path, - self.on_lxmf_delivery, - config=self.config, - ) - self.forwarding_manager.load_aliases() - - # set a callback for when an lxmf message is received - self.message_router.register_delivery_callback(self.on_lxmf_delivery) - - # update active propagation node - self.set_active_propagation_node( - self.config.lxmf_preferred_propagation_node_destination_hash.get(), - ) - - # enable propagation node (we don't call with false if disabled, as no need to announce disabled state every launch) - if self.config.lxmf_local_propagation_node_enabled.get(): - self.enable_local_propagation_node() - - # handle received announces based on aspect - RNS.Transport.register_announce_handler( - AnnounceHandler("lxst.telephony", self.on_telephone_announce_received), - ) - RNS.Transport.register_announce_handler( - AnnounceHandler("lxmf.delivery", self.on_lxmf_announce_received), - ) - RNS.Transport.register_announce_handler( - AnnounceHandler( - "lxmf.propagation", - self.on_lxmf_propagation_announce_received, - ), - ) - RNS.Transport.register_announce_handler( - AnnounceHandler( - "nomadnetwork.node", - self.on_nomadnet_node_announce_received, - ), - ) - - # register audio call identity - # init telephone manager - self.telephone_manager = TelephoneManager( - identity=self.identity, - config_manager=self.config, - ) - self.telephone_manager.register_ringing_callback( - self.on_incoming_telephone_call, - ) - self.telephone_manager.register_established_callback( - self.on_telephone_call_established, - ) - self.telephone_manager.register_ended_callback( - self.on_telephone_call_ended, - ) - self.telephone_manager.init_telephone() - - # init Voicemail Manager - self.voicemail_manager = VoicemailManager( - db=self.database, - config=self.config, - telephone_manager=self.telephone_manager, - storage_dir=self.storage_path, - ) - # Monkey patch VoicemailManager to use our get_name_for_identity_hash - self.voicemail_manager.get_name_for_identity_hash = ( - self.get_name_for_identity_hash - ) - self.voicemail_manager.on_new_voicemail_callback = ( - self.on_new_voicemail_received - ) - - # init Ringtone Manager - self.ringtone_manager = RingtoneManager( - config=self.config, - storage_dir=self.storage_path, - ) - - # init RNCP handler - self.rncp_handler = RNCPHandler( - reticulum_instance=getattr(self, "reticulum", None), - identity=self.identity, - storage_dir=self.storage_dir, - ) - - # init RNStatus handler - self.rnstatus_handler = RNStatusHandler( - reticulum_instance=getattr(self, "reticulum", None), - ) - - # init RNProbe handler - self.rnprobe_handler = RNProbeHandler( - reticulum_instance=getattr(self, "reticulum", None), - identity=self.identity, - ) - - # init Translator handler - libretranslate_url = self.config.get("libretranslate_url", None) - self.translator_handler = TranslatorHandler( - libretranslate_url=libretranslate_url, - ) - - # start background thread for auto announce loop - thread = threading.Thread( - target=asyncio.run, - args=(self.announce_loop(session_id),), - ) - thread.daemon = True - thread.start() - - # start background thread for auto syncing propagation nodes - thread = threading.Thread( - target=asyncio.run, - args=(self.announce_sync_propagation_nodes(session_id),), - ) - thread.daemon = True - thread.start() - - # start background thread for crawler loop - thread = threading.Thread( - target=asyncio.run, - args=(self.crawler_loop(session_id),), - ) - thread.daemon = True - thread.start() - - def _tune_sqlite_pragmas(self): - try: - self.db.execute_sql("PRAGMA wal_autocheckpoint=1000") - self.db.execute_sql("PRAGMA temp_store=MEMORY") - self.db.execute_sql("PRAGMA journal_mode=WAL") - except Exception as exc: - print(f"SQLite pragma setup failed: {exc}") - - def _get_pragma_value(self, pragma: str, default=None): - try: - cursor = self.db.execute_sql(f"PRAGMA {pragma}") - row = cursor.fetchone() - if row is None: - return default - return row[0] - except Exception: - return default - - def _get_database_file_stats(self): - def size_for(path): - try: - return os.path.getsize(path) - except OSError: - return 0 - - wal_path = f"{self.database_path}-wal" - shm_path = f"{self.database_path}-shm" - - main_bytes = size_for(self.database_path) - wal_bytes = size_for(wal_path) - shm_bytes = size_for(shm_path) - - return { - "main_bytes": main_bytes, - "wal_bytes": wal_bytes, - "shm_bytes": shm_bytes, - "total_bytes": main_bytes + wal_bytes + shm_bytes, - } - - def _database_paths(self): - return { - "main": self.database_path, - "wal": f"{self.database_path}-wal", - "shm": f"{self.database_path}-shm", - } - - def get_database_health_snapshot(self): - page_size = self._get_pragma_value("page_size", 0) or 0 - page_count = self._get_pragma_value("page_count", 0) or 0 - freelist_pages = self._get_pragma_value("freelist_count", 0) or 0 - free_bytes = ( - page_size * freelist_pages if page_size > 0 and freelist_pages > 0 else 0 - ) - - return { - "quick_check": self._get_pragma_value("quick_check", "unknown"), - "journal_mode": self._get_pragma_value("journal_mode", "unknown"), - "synchronous": self._get_pragma_value("synchronous", None), - "wal_autocheckpoint": self._get_pragma_value("wal_autocheckpoint", None), - "auto_vacuum": self._get_pragma_value("auto_vacuum", None), - "page_size": page_size, - "page_count": page_count, - "freelist_pages": freelist_pages, - "estimated_free_bytes": free_bytes, - "files": self._get_database_file_stats(), - } - - def _checkpoint_wal(self, mode: str = "TRUNCATE"): - return self.db.execute_sql(f"PRAGMA wal_checkpoint({mode})").fetchall() - - def run_database_vacuum(self): - checkpoint = self._checkpoint_wal() - self.db.execute_sql("VACUUM") - self._tune_sqlite_pragmas() - - return { - "checkpoint": checkpoint, - "health": self.get_database_health_snapshot(), - } - - def run_database_recovery(self): - actions = [] - - actions.append( - { - "step": "quick_check_before", - "result": self._get_pragma_value("quick_check", "unknown"), - }, - ) - - actions.append({"step": "wal_checkpoint", "result": self._checkpoint_wal()}) - - integrity_rows = self.database.provider.integrity_check() - integrity = [row[0] for row in integrity_rows] if integrity_rows else [] - actions.append({"step": "integrity_check", "result": integrity}) - - self.database.provider.vacuum() - self._tune_sqlite_pragmas() - - actions.append( - { - "step": "quick_check_after", - "result": self._get_pragma_value("quick_check", "unknown"), - }, - ) - - return { - "actions": actions, - "health": self.get_database_health_snapshot(), - } + # Link database to memory log handler + memory_log_handler.set_database(context.database) def _checkpoint_and_close(self): - try: - self._checkpoint_wal() - except Exception as e: - print(f"Failed to checkpoint WAL: {e}") - try: - self.database.close() - except Exception as e: - print(f"Failed to close database: {e}") - - def _backup_to_zip(self, backup_path: str): - paths = self._database_paths() - os.makedirs(os.path.dirname(backup_path), exist_ok=True) - # ensure WAL is checkpointed to get a consistent snapshot - self._checkpoint_wal() - - with zipfile.ZipFile(backup_path, "w", compression=zipfile.ZIP_DEFLATED) as zf: - zf.write(paths["main"], arcname="database.db") - if os.path.exists(paths["wal"]): - zf.write(paths["wal"], arcname="database.db-wal") - if os.path.exists(paths["shm"]): - zf.write(paths["shm"], arcname="database.db-shm") - - return { - "path": backup_path, - "size": os.path.getsize(backup_path), - } - - def backup_database(self, backup_path: str | None = None): - default_dir = os.path.join(self.storage_path, "database-backups") - os.makedirs(default_dir, exist_ok=True) - if backup_path is None: - timestamp = datetime.now(UTC).strftime("%Y%m%d-%H%M%S") - backup_path = os.path.join(default_dir, f"backup-{timestamp}.zip") - - return self._backup_to_zip(backup_path) - - def restore_database(self, backup_path: str): - if not os.path.exists(backup_path): - msg = f"Backup not found at {backup_path}" - raise FileNotFoundError(msg) - - paths = self._database_paths() - self._checkpoint_and_close() - - # clean existing files - for p in paths.values(): - if os.path.exists(p): - os.remove(p) - - if zipfile.is_zipfile(backup_path): - with zipfile.ZipFile(backup_path, "r") as zf: - zf.extractall(os.path.dirname(paths["main"])) - else: - shutil.copy2(backup_path, paths["main"]) - - # reopen and retune - self.database.initialize() - self._tune_sqlite_pragmas() - integrity = self.database.provider.integrity_check() - - return { - "restored_from": backup_path, - "integrity_check": integrity, - "health": self.get_database_health_snapshot(), - } + # delegated to database instance + self.database._checkpoint_and_close() def _get_identity_bytes(self) -> bytes: - return self.identity.get_private_key() + return self.identity_manager.get_identity_bytes(self.identity) def cleanup_rns_state_for_identity(self, identity_hash): if not identity_hash: @@ -688,124 +644,19 @@ class ReticulumMeshChat: print(f"Tearing down RNS link {link}") try: link.teardown() - except Exception: + except Exception: # noqa: S110 pass except Exception as e: print(f"Error while cleaning up RNS links: {e}") def teardown_identity(self): - print("Tearing down current identity instance...") - self.running = False - - # 1. Deregister destinations and links from RNS Transport - try: - # Get current identity hash for matching - current_identity_hash = ( - self.identity.hash - if hasattr(self, "identity") and self.identity - else None - ) - - # Explicitly deregister known destinations from managers first - if hasattr(self, "message_router") and self.message_router: - # Deregister delivery destinations - if hasattr(self.message_router, "delivery_destinations"): - for dest_hash in list( - self.message_router.delivery_destinations.keys(), - ): - dest = self.message_router.delivery_destinations[dest_hash] - RNS.Transport.deregister_destination(dest) - - # Deregister propagation destination - if ( - hasattr(self.message_router, "propagation_destination") - and self.message_router.propagation_destination - ): - RNS.Transport.deregister_destination( - self.message_router.propagation_destination, - ) - - if hasattr(self, "telephone_manager") and self.telephone_manager: - if ( - hasattr(self.telephone_manager, "telephone") - and self.telephone_manager.telephone - ): - if ( - hasattr(self.telephone_manager.telephone, "destination") - and self.telephone_manager.telephone.destination - ): - RNS.Transport.deregister_destination( - self.telephone_manager.telephone.destination, - ) - - # Use the global helper for thorough cleanup - if current_identity_hash: - self.cleanup_rns_state_for_identity(current_identity_hash) - - except Exception as e: - print(f"Error while deregistering destinations or links: {e}") - - # 2. Unregister all announce handlers from Transport - try: - for handler in list(RNS.Transport.announce_handlers): - should_deregister = False - - # check if it's one of our AnnounceHandler instances - if ( - ( - hasattr(handler, "aspect_filter") - and hasattr(handler, "received_announce_callback") - ) - or ( - hasattr(handler, "router") - and hasattr(self, "message_router") - and handler.router == self.message_router - ) - or "LXMFDeliveryAnnounceHandler" in str(type(handler)) - or "LXMFPropagationAnnounceHandler" in str(type(handler)) - ): - should_deregister = True - - if should_deregister: - RNS.Transport.deregister_announce_handler(handler) - except Exception as e: - print(f"Error while deregistering announce handlers: {e}") - - # 3. Stop the LXMRouter job loop (hacking it to stop) - if hasattr(self, "message_router") and self.message_router: - try: - # Replacing jobs with a no-op so the thread just sleeps - self.message_router.jobs = lambda: None - - # Try to call exit_handler to persist state - if hasattr(self.message_router, "exit_handler"): - self.message_router.exit_handler() - except Exception as e: - print(f"Error while tearing down LXMRouter: {e}") - - # 4. Stop telephone and voicemail - if hasattr(self, "telephone_manager") and self.telephone_manager: - try: - # use teardown instead of shutdown - if hasattr(self.telephone_manager, "teardown"): - self.telephone_manager.teardown() - elif hasattr(self.telephone_manager, "shutdown"): - self.telephone_manager.shutdown() - except Exception as e: - print(f"Error while tearing down telephone: {e}") - - if hasattr(self, "voicemail_manager") and self.voicemail_manager: - try: - self.voicemail_manager.stop_recording() - except Exception: - pass - - # 5. Close database - if hasattr(self, "database") and self.database: - try: - self.database.close() - except Exception: - pass + if self.current_context: + self.running = False + identity_hash = self.current_context.identity_hash + self.current_context.teardown() + if identity_hash in self.contexts: + del self.contexts[identity_hash] + self.current_context = None async def reload_reticulum(self): print("Hot reloading Reticulum stack...") @@ -845,7 +696,7 @@ class ReticulumMeshChat: try: interface.server.shutdown() interface.server.server_close() - except Exception: + except Exception: # noqa: S110 pass # AutoInterface specific @@ -854,7 +705,7 @@ class ReticulumMeshChat: try: server.shutdown() server.server_close() - except Exception: + except Exception: # noqa: S110 pass # For LocalServerInterface which Reticulum doesn't close properly @@ -862,7 +713,7 @@ class ReticulumMeshChat: try: interface.server.shutdown() interface.server.server_close() - except Exception: + except Exception: # noqa: S110 pass # TCPClientInterface/etc @@ -875,10 +726,13 @@ class ReticulumMeshChat: ): try: interface.socket.shutdown(socket.SHUT_RDWR) - except Exception: + except Exception: # noqa: S110 pass - interface.socket.close() - except Exception: + try: + interface.socket.close() + except Exception: # noqa: S110 + pass + except Exception: # noqa: S110 pass interface.detach() @@ -938,7 +792,7 @@ class ReticulumMeshChat: try: # Reticulum uses a staticmethod exit_handler atexit.unregister(RNS.Reticulum.exit_handler) - except Exception: + except Exception: # noqa: S110 pass except Exception as e: @@ -951,7 +805,6 @@ class ReticulumMeshChat: # Wait another moment for sockets to definitely be released by OS # Also give some time for the RPC listener port to settle print("Waiting for ports to settle...") - # We add a settle time here similar to Sideband's logic await asyncio.sleep(4) # Detect RPC type from reticulum instance if possible, otherwise default to both @@ -1059,7 +912,7 @@ class ReticulumMeshChat: # Match IP and port for IPv4 if conn.laddr.port == addr[1] and ( conn.laddr.ip == addr[0] - or addr[0] == "0.0.0.0" + or addr[0] == "0.0.0.0" # noqa: S104 ): match = True elif family_str == "AF_UNIX": @@ -1084,14 +937,22 @@ class ReticulumMeshChat: else b"" ) - if current_laddr == target_addr or ( - target_addr.startswith(b"\0") - and current_laddr - == target_addr[1:] - ) or ( - current_laddr.startswith(b"\0") - and target_addr - == current_laddr[1:] + if ( + current_laddr == target_addr + or ( + target_addr.startswith( + b"\0", + ) + and current_laddr + == target_addr[1:] + ) + or ( + current_laddr.startswith( + b"\0", + ) + and target_addr + == current_laddr[1:] + ) ): match = True elif ( @@ -1122,12 +983,15 @@ class ReticulumMeshChat: hasattr(conn, "fd") and conn.fd != -1 ): - os.close(conn.fd) - except Exception as fd_err: - print( - f"Failed to close FD {getattr(conn, 'fd', 'N/A')}: {fd_err}", - ) - except Exception: + try: + os.close(conn.fd) + except Exception as fd_err: + print( + f"Failed to close FD {getattr(conn, 'fd', 'N/A')}: {fd_err}", + ) + except Exception: # noqa: S110 + pass + except Exception: # noqa: S110 pass except Exception as e: print( @@ -1164,7 +1028,9 @@ class ReticulumMeshChat: last_check_all_free = False s.close() break - except Exception: + except Exception: # noqa: S110 + pass + except Exception: # noqa: S110 pass if not last_check_all_free: @@ -1190,12 +1056,21 @@ class ReticulumMeshChat: if not hasattr(self, "reticulum"): try: self.setup_identity(self.identity) - except Exception: + except Exception: # noqa: S110 pass return False - async def hotswap_identity(self, identity_hash): + async def hotswap_identity(self, identity_hash, keep_alive=False): + old_identity = self.identity + + main_identity_file = self.identity_file_path or os.path.join( + self.storage_dir, + "identity", + ) + backup_identity_file = main_identity_file + ".bak" + backup_created = False + try: # load the new identity identity_dir = os.path.join(self.storage_dir, "identities", identity_hash) @@ -1204,29 +1079,30 @@ class ReticulumMeshChat: raise ValueError("Identity file not found") # Validate that the identity file can be loaded - RNS.Identity.from_file(identity_file) + new_identity = RNS.Identity.from_file(identity_file) + if not new_identity: + raise ValueError("Identity file corrupted or invalid") - # 1. teardown old identity - self.teardown_identity() + # 1. Backup current identity file + if os.path.exists(main_identity_file): + shutil.copy2(main_identity_file, backup_identity_file) + backup_created = True - # Wait a moment for threads to notice self.running=False and destinations to clear - await asyncio.sleep(3) - - # 2. update main identity file - main_identity_file = self.identity_file_path or os.path.join( - self.storage_dir, - "identity", - ) + # 2. teardown old identity if not keeping alive + if not keep_alive: + self.teardown_identity() + # Give a moment for destinations to clear from transport + await asyncio.sleep(2) + # 3. update main identity file shutil.copy2(identity_file, main_identity_file) - # 3. reset state and setup new identity + # 4. setup new identity self.running = True - # Close old reticulum before setting up new one to avoid port conflicts - await self.reload_reticulum() - # Note: reload_reticulum already calls setup_identity + # setup_identity initializes context if needed and sets it as current + self.setup_identity(new_identity) - # 4. broadcast update to clients + # 5. broadcast update to clients await self.websocket_broadcast( json.dumps( { @@ -1241,145 +1117,111 @@ class ReticulumMeshChat: ), ) + # Clean up backup on success + if backup_created and os.path.exists(backup_identity_file): + os.remove(backup_identity_file) + return True except Exception as e: print(f"Hotswap failed: {e}") - traceback.print_exc() + + # RECOVERY: Try to switch back to last identity + try: + print("Attempting to restore previous identity...") + if backup_created and os.path.exists(backup_identity_file): + shutil.copy2(backup_identity_file, main_identity_file) + os.remove(backup_identity_file) + + self.running = True + if old_identity: + self.setup_identity(old_identity) + except Exception as recovery_err: + print(f"Recovery failed: {recovery_err}") + traceback.print_exc() + + # FINAL FAILSAFE: Create a brand new identity + try: + print( + "CRITICAL: Restoration of previous identity failed. Creating a brand new emergency identity...", + ) + new_id_data = self.create_identity( + display_name="Emergency Recovery", + ) + new_id_hash = new_id_data["hash"] + + # Try to load the newly created identity + emergency_identity_file = os.path.join( + self.storage_dir, + "identities", + new_id_hash, + "identity", + ) + emergency_id = RNS.Identity.from_file(emergency_identity_file) + + if emergency_id: + # Copy to main identity file + shutil.copy2(emergency_identity_file, main_identity_file) + self.running = True + self.setup_identity(emergency_id) + print(f"Emergency identity created and loaded: {new_id_hash}") + else: + raise RuntimeError( + "Failed to load newly created emergency identity", + ) + + except Exception as final_err: + print( + f"ULTIMATE FAILURE: Could not even create emergency identity: {final_err}", + ) + traceback.print_exc() + return False def backup_identity(self): - identity_bytes = self._get_identity_bytes() - target_path = self.identity_file_path or os.path.join( - self.storage_dir, - "identity", - ) - os.makedirs(os.path.dirname(target_path), exist_ok=True) - with open(target_path, "wb") as f: - f.write(identity_bytes) - return { - "path": target_path, - "size": os.path.getsize(target_path), - } + return self.identity_manager.backup_identity(self.identity) def backup_identity_base32(self) -> str: - return base64.b32encode(self._get_identity_bytes()).decode("utf-8") + return self.identity_manager.backup_identity_base32(self.identity) def list_identities(self): - identities = [] - identities_base_dir = os.path.join(self.storage_dir, "identities") - if not os.path.exists(identities_base_dir): - return identities - - for identity_hash in os.listdir(identities_base_dir): - identity_path = os.path.join(identities_base_dir, identity_hash) - if not os.path.isdir(identity_path): - continue - - db_path = os.path.join(identity_path, "database.db") - if not os.path.exists(db_path): - continue - - # try to get config from database - display_name = "Anonymous Peer" - icon_name = None - icon_foreground_colour = None - icon_background_colour = None - - try: - # use a temporary provider to avoid messing with current DB - from meshchatx.src.backend.database.config import ConfigDAO - from meshchatx.src.backend.database.provider import DatabaseProvider - - temp_provider = DatabaseProvider(db_path) - temp_config_dao = ConfigDAO(temp_provider) - display_name = temp_config_dao.get("display_name", "Anonymous Peer") - icon_name = temp_config_dao.get("lxmf_user_icon_name") - icon_foreground_colour = temp_config_dao.get( - "lxmf_user_icon_foreground_colour", - ) - icon_background_colour = temp_config_dao.get( - "lxmf_user_icon_background_colour", - ) - temp_provider.close() - except Exception as e: - print(f"Error reading config for {identity_hash}: {e}") - - identities.append( - { - "hash": identity_hash, - "display_name": display_name, - "icon_name": icon_name, - "icon_foreground_colour": icon_foreground_colour, - "icon_background_colour": icon_background_colour, - "is_current": identity_hash == self.identity.hash.hex(), - }, - ) - return identities + return self.identity_manager.list_identities( + self.identity.hash.hex() + if hasattr(self, "identity") and self.identity + else None, + ) def create_identity(self, display_name=None): - new_identity = RNS.Identity(create_keys=True) - identity_hash = new_identity.hash.hex() - - identity_dir = os.path.join(self.storage_dir, "identities", identity_hash) - os.makedirs(identity_dir, exist_ok=True) - - # save identity file in its own directory - identity_file = os.path.join(identity_dir, "identity") - with open(identity_file, "wb") as f: - f.write(new_identity.get_private_key()) - - # initialize its database and set display name - db_path = os.path.join(identity_dir, "database.db") - - # Avoid using the Database class singleton behavior - from meshchatx.src.backend.database.config import ConfigDAO - from meshchatx.src.backend.database.provider import DatabaseProvider - from meshchatx.src.backend.database.schema import DatabaseSchema - - new_provider = DatabaseProvider(db_path) - new_schema = DatabaseSchema(new_provider) - new_schema.initialize() - - if display_name: - new_config_dao = ConfigDAO(new_provider) - new_config_dao.set("display_name", display_name) - - new_provider.close() - - return { - "hash": identity_hash, - "display_name": display_name or "Anonymous Peer", - } + return self.identity_manager.create_identity(display_name) def delete_identity(self, identity_hash): - if identity_hash == self.identity.hash.hex(): - raise ValueError("Cannot delete the current active identity") - - identity_dir = os.path.join(self.storage_dir, "identities", identity_hash) - if os.path.exists(identity_dir): - shutil.rmtree(identity_dir) - return True - return False + current_hash = ( + self.identity.hash.hex() + if hasattr(self, "identity") and self.identity + else None + ) + return self.identity_manager.delete_identity(identity_hash, current_hash) def restore_identity_from_bytes(self, identity_bytes: bytes): - target_path = self.identity_file_path or os.path.join( - self.storage_dir, - "identity", - ) - os.makedirs(os.path.dirname(target_path), exist_ok=True) - with open(target_path, "wb") as f: - f.write(identity_bytes) - return {"path": target_path, "size": os.path.getsize(target_path)} + return self.identity_manager.restore_identity_from_bytes(identity_bytes) def restore_identity_from_base32(self, base32_value: str): - try: - identity_bytes = base64.b32decode(base32_value, casefold=True) - except Exception as exc: - msg = f"Invalid base32 identity: {exc}" - raise ValueError(msg) from exc + return self.identity_manager.restore_identity_from_base32(base32_value) - return self.restore_identity_from_bytes(identity_bytes) + def update_identity_metadata_cache(self): + if not hasattr(self, "identity") or not self.identity: + return + + identity_hash = self.identity.hash.hex() + metadata = { + "display_name": self.config.display_name.get(), + "icon_name": self.config.lxmf_user_icon_name.get(), + "icon_foreground_colour": self.config.lxmf_user_icon_foreground_colour.get(), + "icon_background_colour": self.config.lxmf_user_icon_background_colour.get(), + "lxmf_address": self.config.lxmf_address_hash.get(), + "lxst_address": self.config.lxst_address_hash.get(), + } + self.identity_manager.update_metadata_cache(identity_hash, metadata) def _run_startup_auto_recovery(self): try: @@ -1399,7 +1241,7 @@ class ReticulumMeshChat: }, ) self.database.provider.vacuum() - self._tune_sqlite_pragmas() + self.database._tune_sqlite_pragmas() actions.append( { "step": "quick_check_after", @@ -1418,19 +1260,40 @@ class ReticulumMeshChat: def get_app_version() -> str: return app_version + @staticmethod + def get_package_version(package_name: str, default: str = "unknown") -> str: + try: + return importlib.metadata.version(package_name) + except Exception: + try: + # try to import the package and get __version__ + # some packages use underscores instead of hyphens in module names + module_name = package_name.replace("-", "_") + module = __import__(module_name) + return getattr(module, "__version__", default) + except Exception: + return default + + def get_lxst_version(self) -> str: + return self.get_package_version("lxst", getattr(LXST, "__version__", "unknown")) + # automatically announces based on user config - async def announce_loop(self, session_id): - while self.running and self._identity_session_id == session_id: + async def announce_loop(self, session_id, context=None): + ctx = context or self.current_context + if not ctx: + return + + while self.running and ctx.running and ctx.session_id == session_id: should_announce = False # check if auto announce is enabled - if self.config.auto_announce_enabled.get(): + if ctx.config.auto_announce_enabled.get(): # check if we have announced recently - last_announced_at = self.config.last_announced_at.get() + last_announced_at = ctx.config.last_announced_at.get() if last_announced_at is not None: # determine when next announce should be sent auto_announce_interval_seconds = ( - self.config.auto_announce_interval_seconds.get() + ctx.config.auto_announce_interval_seconds.get() ) next_announce_at = ( last_announced_at + auto_announce_interval_seconds @@ -1446,26 +1309,30 @@ class ReticulumMeshChat: # announce if should_announce: - await self.announce() + await self.announce(context=ctx) # also announce forwarding aliases if any - if self.forwarding_manager: - await asyncio.to_thread(self.forwarding_manager.announce_aliases) + if ctx.forwarding_manager: + await asyncio.to_thread(ctx.forwarding_manager.announce_aliases) # wait 1 second before next loop await asyncio.sleep(1) # automatically syncs propagation nodes based on user config - async def announce_sync_propagation_nodes(self, session_id): - while self.running and self._identity_session_id == session_id: + async def announce_sync_propagation_nodes(self, session_id, context=None): + ctx = context or self.current_context + if not ctx: + return + + while self.running and ctx.running and ctx.session_id == session_id: should_sync = False # check if auto sync is enabled - auto_sync_interval_seconds = self.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get() + auto_sync_interval_seconds = ctx.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get() if auto_sync_interval_seconds > 0: # check if we have synced recently last_synced_at = ( - self.config.lxmf_preferred_propagation_node_last_synced_at.get() + ctx.config.lxmf_preferred_propagation_node_last_synced_at.get() ) if last_synced_at is not None: # determine when next sync should happen @@ -1481,54 +1348,70 @@ class ReticulumMeshChat: # sync if should_sync: - await self.sync_propagation_nodes() + await self.sync_propagation_nodes(context=ctx) # wait 1 second before next loop await asyncio.sleep(1) - async def crawler_loop(self, session_id): - while self.running and self._identity_session_id == session_id: + async def crawler_loop(self, session_id, context=None): + ctx = context or self.current_context + if not ctx: + return + + while self.running and ctx.running and ctx.session_id == session_id: try: - if self.config.crawler_enabled.get(): + if ctx.config.crawler_enabled.get(): # Proactively queue any known nodes from the database that haven't been queued yet # get known propagation nodes from database - known_nodes = self.database.announces.get_announces( + known_nodes = ctx.database.announces.get_announces( aspect="nomadnetwork.node", ) for node in known_nodes: - if not self.running or self._identity_session_id != session_id: + if ( + not self.running + or not ctx.running + or ctx.session_id != session_id + ): break self.queue_crawler_task( node["destination_hash"], "/page/index.mu", + context=ctx, ) # process pending or failed tasks # ensure we handle potential string comparison issues in SQLite - tasks = self.database.misc.get_pending_or_failed_crawl_tasks( - max_retries=self.config.crawler_max_retries.get(), - max_concurrent=self.config.crawler_max_concurrent.get(), + tasks = ctx.database.misc.get_pending_or_failed_crawl_tasks( + max_retries=ctx.config.crawler_max_retries.get(), + max_concurrent=ctx.config.crawler_max_concurrent.get(), ) # process tasks concurrently up to the limit - if tasks and self.running: + if tasks and self.running and ctx.running: await asyncio.gather( - *[self.process_crawler_task(task) for task in tasks], + *[ + self.process_crawler_task(task, context=ctx) + for task in tasks + ], ) except Exception as e: - print(f"Error in crawler loop: {e}") + print(f"Error in crawler loop for {ctx.identity_hash}: {e}") # wait 30 seconds before checking again for _ in range(30): - if not self.running or self._identity_session_id != session_id: + if not self.running or not ctx.running or ctx.session_id != session_id: return await asyncio.sleep(1) - async def process_crawler_task(self, task): + async def process_crawler_task(self, task, context=None): + ctx = context or self.current_context + if not ctx: + return + # mark as crawling task_id = task["id"] - self.database.misc.update_crawl_task( + ctx.database.misc.update_crawl_task( task_id, status="crawling", last_retry_at=datetime.now(UTC), @@ -1596,60 +1479,85 @@ class ReticulumMeshChat: page_path, content_received[0], is_manual=False, + context=ctx, + ) + ctx.database.misc.update_crawl_task( + task_id, + status="completed", + updated_at=datetime.now(UTC), ) - task.status = "completed" - task.save() else: print( f"Crawler: Failed to archive {destination_hash}:{page_path} - {failure_reason[0]}", ) - task.retry_count += 1 - task.status = "failed" + retry_count = task["retry_count"] + 1 # calculate next retry time - retry_delay = self.config.crawler_retry_delay_seconds.get() + retry_delay = ctx.config.crawler_retry_delay_seconds.get() # simple backoff - backoff_delay = retry_delay * (2 ** (task.retry_count - 1)) - task.next_retry_at = datetime.now(UTC) + timedelta(seconds=backoff_delay) - task.save() + backoff_delay = retry_delay * (2 ** (retry_count - 1)) + next_retry_at = datetime.now(UTC) + timedelta(seconds=backoff_delay) + + ctx.database.misc.update_crawl_task( + task_id, + status="failed", + retry_count=retry_count, + next_retry_at=next_retry_at, + updated_at=datetime.now(UTC), + ) # uses the provided destination hash as the active propagation node - def set_active_propagation_node(self, destination_hash: str | None): + def set_active_propagation_node(self, destination_hash: str | None, context=None): + ctx = context or self.current_context + if not ctx: + return + # set outbound propagation node if destination_hash is not None and destination_hash != "": try: - self.message_router.set_outbound_propagation_node( + ctx.message_router.set_outbound_propagation_node( bytes.fromhex(destination_hash), ) except Exception: # failed to set propagation node, clear it to ensure we don't use an old one by mistake - self.remove_active_propagation_node() + self.remove_active_propagation_node(context=ctx) # stop using propagation node else: - self.remove_active_propagation_node() + self.remove_active_propagation_node(context=ctx) # stops the in progress propagation node sync - def stop_propagation_node_sync(self): - self.message_router.cancel_propagation_node_requests() + def stop_propagation_node_sync(self, context=None): + ctx = context or self.current_context + if not ctx: + return + ctx.message_router.cancel_propagation_node_requests() # stops and removes the active propagation node - def remove_active_propagation_node(self): + def remove_active_propagation_node(self, context=None): + ctx = context or self.current_context + if not ctx: + return # fixme: it's possible for internal transfer state to get stuck if we change propagation node during a sync # this still happens even if we cancel the propagation node requests # for now, the user can just manually cancel syncing in the ui if they think it's stuck... - self.stop_propagation_node_sync() - self.message_router.outbound_propagation_node = None + self.stop_propagation_node_sync(context=ctx) + ctx.message_router.outbound_propagation_node = None # enables or disables the local lxmf propagation node - def enable_local_propagation_node(self, enabled: bool = True): + def enable_local_propagation_node(self, enabled: bool = True, context=None): + ctx = context or self.current_context + if not ctx: + return try: if enabled: - self.message_router.enable_propagation() + ctx.message_router.enable_propagation() else: - self.message_router.disable_propagation() + ctx.message_router.disable_propagation() except Exception: - print("failed to enable or disable propagation node") + print( + f"failed to enable or disable propagation node for {ctx.identity_hash}", + ) def _get_reticulum_section(self): try: @@ -1754,7 +1662,7 @@ class ReticulumMeshChat: # returns the latest message for the provided destination hash def get_conversation_latest_message(self, destination_hash: str): - local_hash = self.identity.hexhash + local_hash = self.identity.hash.hex() messages = self.message_handler.get_conversation_messages( local_hash, destination_hash, @@ -1764,33 +1672,16 @@ class ReticulumMeshChat: # returns true if the conversation with the provided destination hash has any attachments def conversation_has_attachments(self, destination_hash: str): - local_hash = self.identity.hexhash + local_hash = self.identity.hash.hex() messages = self.message_handler.get_conversation_messages( local_hash, destination_hash, ) for message in messages: - if self.message_fields_have_attachments(message["fields"]): + if message_fields_have_attachments(message["fields"]): return True return False - @staticmethod - def message_fields_have_attachments(fields_json: str | None): - if not fields_json: - return False - try: - fields = json.loads(fields_json) - except Exception: - return False - if "image" in fields or "audio" in fields: - return True - if "file_attachments" in fields and isinstance( - fields["file_attachments"], - list, - ): - return len(fields["file_attachments"]) > 0 - return False - def search_destination_hashes_by_message(self, search_term: str): if search_term is None or search_term.strip() == "": return set() @@ -1820,14 +1711,24 @@ class ReticulumMeshChat: return matches - @staticmethod - def parse_bool_query_param(value: str | None) -> bool: - if value is None: - return False - value = value.lower() - return value in {"1", "true", "yes", "on"} + def on_new_voicemail_received( + self, + remote_hash, + remote_name, + duration, + context=None, + ): + ctx = context or self.current_context + if not ctx: + return + # Add system notification + self.database.misc.add_notification( + type="telephone_voicemail", + remote_hash=remote_hash, + title="New Voicemail", + content=f"New voicemail from {remote_name or remote_hash} ({duration}s)", + ) - def on_new_voicemail_received(self, remote_hash, remote_name, duration): AsyncUtils.run_async( self.websocket_broadcast( json.dumps( @@ -1843,7 +1744,17 @@ class ReticulumMeshChat: ) # handle receiving a new audio call - def on_incoming_telephone_call(self, caller_identity: RNS.Identity): + def on_incoming_telephone_call(self, caller_identity: RNS.Identity, context=None): + ctx = context or self.current_context + if not ctx: + return + + if ctx.telephone_manager and ctx.telephone_manager.initiation_status: + print( + "on_incoming_telephone_call: Ignoring as we are currently initiating an outgoing call.", + ) + return + caller_hash = caller_identity.hash.hex() # Check if caller is blocked @@ -1890,7 +1801,14 @@ class ReticulumMeshChat: ), ) - def on_telephone_call_established(self, caller_identity: RNS.Identity): + def on_telephone_call_established( + self, + caller_identity: RNS.Identity, + context=None, + ): + ctx = context or self.current_context + if not ctx: + return print(f"on_telephone_call_established: {caller_identity.hash.hex()}") AsyncUtils.run_async( self.websocket_broadcast( @@ -1902,13 +1820,20 @@ class ReticulumMeshChat: ), ) - def on_telephone_call_ended(self, caller_identity: RNS.Identity): + def on_telephone_call_ended(self, caller_identity: RNS.Identity, context=None): + ctx = context or self.current_context + if not ctx: + return # Stop voicemail recording if active self.voicemail_manager.stop_recording() print( f"on_telephone_call_ended: {caller_identity.hash.hex() if caller_identity else 'Unknown'}", ) + try: + self.web_audio_bridge.on_call_ended() + except Exception as e: + logging.exception(f"Error in web_audio_bridge.on_call_ended: {e}") # Record call history if caller_identity: @@ -1942,8 +1867,8 @@ class ReticulumMeshChat: timestamp=time.time(), ) - # Trigger missed call notification if it was an incoming call that ended while ringing - if is_incoming and status_code == 4: + # Trigger missed call notification if it was an incoming call that ended without being established + if is_incoming and not self.telephone_manager.call_was_established: # Check if we should suppress the notification/websocket message # If DND was on, we still record it but maybe skip the noisy websocket? # Actually, persistent notification is good. @@ -1990,82 +1915,84 @@ class ReticulumMeshChat: ), ) + def on_telephone_initiation_status(self, status, target_hash, context=None): + ctx = context or self.current_context + if not ctx: + return + + target_name = None + if target_hash: + try: + contact = ctx.database.contacts.get_contact_by_identity_hash( + target_hash, + ) + if contact: + target_name = contact.name + except Exception: # noqa: S110 + pass + + AsyncUtils.run_async( + self.websocket_broadcast( + json.dumps( + { + "type": "telephone_initiation_status", + "status": status, + "target_hash": target_hash, + "target_name": target_name, + }, + ), + ), + ) + # web server has shutdown, likely ctrl+c, but if we don't do the following, the script never exits async def shutdown(self, app): # force close websocket clients for websocket_client in self.websocket_clients: try: await websocket_client.close(code=WSCloseCode.GOING_AWAY) - except Exception: + except Exception: # noqa: S110 pass # stop reticulum try: RNS.Transport.detach_interfaces() - except Exception: + except Exception: # noqa: S110 pass if hasattr(self, "reticulum") and self.reticulum: try: self.reticulum.exit_handler() - except Exception: + except Exception: # noqa: S110 pass try: RNS.exit() - except Exception: + except Exception: # noqa: S110 pass - def run(self, host, port, launch_browser: bool, enable_https: bool = True): - # create route table + def exit_app(self, code=0): + sys.exit(code) + + def get_routes(self): + # This is a bit of a hack to get the routes without running the full server + # It's mainly for testing purposes routes = web.RouteTableDef() - ssl_context = None - use_https = enable_https - if enable_https: - cert_dir = os.path.join(self.storage_path, "ssl") - cert_path = os.path.join(cert_dir, "cert.pem") - key_path = os.path.join(cert_dir, "key.pem") - - try: - generate_ssl_certificate(cert_path, key_path) - ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) - ssl_context.load_cert_chain(cert_path, key_path) - print(f"HTTPS enabled with certificate at {cert_path}") - except Exception as e: - print(f"Failed to generate SSL certificate: {e}") - print("Falling back to HTTP") - use_https = False - - # session secret for encrypted cookies (generate once and store in shared storage) - session_secret_path = os.path.join(self.storage_dir, "session_secret") - self.session_secret_key = None - - if os.path.exists(session_secret_path): - try: - with open(session_secret_path) as f: - self.session_secret_key = f.read().strip() - except Exception as e: - print(f"Failed to read session secret from {session_secret_path}: {e}") - - if not self.session_secret_key: - # try to migrate from current identity config if available - self.session_secret_key = self.config.auth_session_secret.get() - if not self.session_secret_key: - self.session_secret_key = secrets.token_urlsafe(32) - - try: - with open(session_secret_path, "w") as f: - f.write(self.session_secret_key) - except Exception as e: - print(f"Failed to write session secret to {session_secret_path}: {e}") - - # ensure it's also in the current config for consistency - self.config.auth_session_secret.set(self.session_secret_key) + # We need to mock some things that are usually setup in run() + # but for just getting the route handlers, we can skip most of it + self._define_routes(routes) + return routes + def _define_routes(self, routes): # authentication middleware @web.middleware async def auth_middleware(request, handler): + if not self.current_context or not self.current_context.running: + return web.json_response( + {"error": "Application is initializing or switching identity"}, + status=503, + ) + if not self.auth_enabled: return await handler(request) @@ -2148,8 +2075,26 @@ class ReticulumMeshChat: # serve index.html @routes.get("/") async def index(request): + index_path = self.get_public_path("index.html") + if not os.path.exists(index_path): + return web.Response( + text=""" + + MeshChatX - Frontend Missing + +

Frontend Missing

+

The MeshChatX web interface files were not found.

+

If you are running from source, you must build the frontend first:

+
pnpm install && pnpm run build-frontend
+

For more information, see the README.

+ + + """, + content_type="text/html", + status=500, + ) return web.FileResponse( - path=get_file_path("public/index.html"), + path=index_path, headers={ # don't allow browser to store page in cache, otherwise new app versions may get stale ui "Cache-Control": "no-cache, no-store", @@ -2159,13 +2104,263 @@ class ReticulumMeshChat: # allow serving manifest.json and service-worker.js directly at root @routes.get("/manifest.json") async def manifest(request): - return web.FileResponse(get_file_path("public/manifest.json")) + return web.FileResponse(self.get_public_path("manifest.json")) @routes.get("/service-worker.js") async def service_worker(request): - return web.FileResponse(get_file_path("public/service-worker.js")) + return web.FileResponse(self.get_public_path("service-worker.js")) + + @routes.get("/call.html") + async def call_html_redirect(request): + return web.HTTPFound("/#/popout/call") + + # serve debug logs + @routes.get("/api/v1/debug/logs") + async def get_debug_logs(request): + search = request.query.get("search") + level = request.query.get("level") + module = request.query.get("module") + is_anomaly = parse_bool_query_param(request.query.get("is_anomaly")) + limit = int(request.query.get("limit", 100)) + offset = int(request.query.get("offset", 0)) + + logs = memory_log_handler.get_logs( + limit=limit, + offset=offset, + search=search, + level=level, + module=module, + is_anomaly=is_anomaly, + ) + total = memory_log_handler.get_total_count( + search=search, + level=level, + module=module, + is_anomaly=is_anomaly, + ) + + return web.json_response( + { + "logs": logs, + "total": total, + "limit": limit, + "offset": offset, + }, + ) + + @routes.post("/api/v1/database/snapshot") + async def create_db_snapshot(request): + try: + data = await request.json() + name = data.get("name", f"snapshot-{int(time.time())}") + result = self.database.create_snapshot(self.storage_dir, name) + return web.json_response({"status": "success", "result": result}) + except Exception as e: + return web.json_response( + {"status": "error", "message": str(e)}, + status=500, + ) + + @routes.get("/api/v1/database/snapshots") + async def list_db_snapshots(request): + try: + limit = int(request.query.get("limit", 100)) + offset = int(request.query.get("offset", 0)) + snapshots = self.database.list_snapshots(self.storage_dir) + total = len(snapshots) + paginated_snapshots = snapshots[offset : offset + limit] + return web.json_response( + { + "snapshots": paginated_snapshots, + "total": total, + "limit": limit, + "offset": offset, + }, + ) + except Exception as e: + return web.json_response( + {"status": "error", "message": str(e)}, + status=500, + ) + + @routes.delete("/api/v1/database/snapshots/{filename}") + async def delete_db_snapshot(request): + try: + filename = request.match_info.get("filename") + if not filename.endswith(".zip"): + filename += ".zip" + self.database.delete_snapshot_or_backup( + self.storage_dir, + filename, + is_backup=False, + ) + return web.json_response({"status": "success"}) + except Exception as e: + return web.json_response( + {"status": "error", "message": str(e)}, + status=500, + ) + + @routes.post("/api/v1/database/restore") + async def restore_db_snapshot(request): + try: + data = await request.json() + path = data.get("path") + if not path: + return web.json_response( + {"status": "error", "message": "No path provided"}, + status=400, + ) + + # Verify path is within storage_dir/snapshots or provided directly + if not os.path.exists(path): + # Try relative to snapshots dir + potential_path = os.path.join(self.storage_dir, "snapshots", path) + if os.path.exists(potential_path): + path = potential_path + elif os.path.exists(potential_path + ".zip"): + path = potential_path + ".zip" + else: + return web.json_response( + {"status": "error", "message": "Snapshot not found"}, + status=404, + ) + + result = self.database.restore_database(path) + # Note: This might require an app relaunch to be fully effective + return web.json_response( + {"status": "success", "result": result, "requires_relaunch": True}, + ) + except Exception as e: + return web.json_response( + {"status": "error", "message": str(e)}, + status=500, + ) + + @routes.get("/api/v1/database/backups") + async def list_db_backups(request): + try: + limit = int(request.query.get("limit", 100)) + offset = int(request.query.get("offset", 0)) + backup_dir = os.path.join(self.storage_dir, "database-backups") + if not os.path.exists(backup_dir): + return web.json_response( + {"backups": [], "total": 0, "limit": limit, "offset": offset}, + ) + + backups = [] + for file in os.listdir(backup_dir): + if file.endswith(".zip"): + full_path = os.path.join(backup_dir, file) + stats = os.stat(full_path) + backups.append( + { + "name": file, + "path": full_path, + "size": stats.st_size, + "created_at": datetime.fromtimestamp( + stats.st_mtime, + UTC, + ).isoformat(), + }, + ) + sorted_backups = sorted( + backups, + key=lambda x: x["created_at"], + reverse=True, + ) + total = len(sorted_backups) + paginated_backups = sorted_backups[offset : offset + limit] + return web.json_response( + { + "backups": paginated_backups, + "total": total, + "limit": limit, + "offset": offset, + }, + ) + except Exception as e: + return web.json_response( + {"status": "error", "message": str(e)}, + status=500, + ) + + @routes.delete("/api/v1/database/backups/{filename}") + async def delete_db_backup(request): + try: + filename = request.match_info.get("filename") + if not filename.endswith(".zip"): + filename += ".zip" + self.database.delete_snapshot_or_backup( + self.storage_dir, + filename, + is_backup=True, + ) + return web.json_response({"status": "success"}) + except Exception as e: + return web.json_response( + {"status": "error", "message": str(e)}, + status=500, + ) + + @routes.get("/api/v1/database/backups/{filename}/download") + async def download_db_backup(request): + try: + filename = request.match_info.get("filename") + if not filename.endswith(".zip"): + filename += ".zip" + backup_dir = os.path.join(self.storage_dir, "database-backups") + full_path = os.path.join(backup_dir, filename) + + if not os.path.exists(full_path) or not full_path.startswith( + backup_dir, + ): + return web.json_response( + {"status": "error", "message": "Backup not found"}, + status=404, + ) + + return web.FileResponse( + path=full_path, + headers={ + "Content-Disposition": f'attachment; filename="{filename}"', + }, + ) + except Exception as e: + return web.json_response( + {"status": "error", "message": str(e)}, + status=500, + ) + + @routes.get("/api/v1/database/snapshots/{filename}/download") + async def download_db_snapshot(request): + try: + filename = request.match_info.get("filename") + if not filename.endswith(".zip"): + filename += ".zip" + snapshot_dir = os.path.join(self.storage_dir, "snapshots") + full_path = os.path.join(snapshot_dir, filename) + + if not os.path.exists(full_path) or not full_path.startswith( + snapshot_dir, + ): + return web.json_response( + {"status": "error", "message": "Snapshot not found"}, + status=404, + ) + + return web.FileResponse( + path=full_path, + headers={ + "Content-Disposition": f'attachment; filename="{filename}"', + }, + ) + except Exception as e: + return web.json_response( + {"status": "error", "message": str(e)}, + status=500, + ) - # serve ping @routes.get("/api/v1/status") async def status(request): return web.json_response( @@ -2302,6 +2497,47 @@ class ReticulumMeshChat: }, ) + @routes.get("/api/v1/tools/rnode/download_firmware") + async def tools_rnode_download_firmware(request): + url = request.query.get("url") + if not url: + return web.json_response({"error": "URL is required"}, status=400) + + # Restrict to allowed sources for safety + gitea_url = "https://git.quad4.io" + if self.current_context and self.current_context.config: + gitea_url = self.current_context.config.gitea_base_url.get() + + if ( + not url.startswith(gitea_url + "/") + and not url.startswith("https://git.quad4.io/") + and not url.startswith("https://github.com/") + and not url.startswith("https://objects.githubusercontent.com/") + ): + return web.json_response({"error": "Invalid download URL"}, status=403) + + try: + async with aiohttp.ClientSession() as session: + async with session.get(url, allow_redirects=True) as response: + if response.status != 200: + return web.json_response( + {"error": f"Failed to download: {response.status}"}, + status=response.status, + ) + + data = await response.read() + filename = url.split("/")[-1] + + return web.Response( + body=data, + content_type="application/zip", + headers={ + "Content-Disposition": f'attachment; filename="{filename}"', + }, + ) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + # fetch reticulum interfaces @routes.get("/api/v1/reticulum/interfaces") async def reticulum_interfaces(request): @@ -2340,6 +2576,12 @@ class ReticulumMeshChat: }, ) + # fetch community interfaces + @routes.get("/api/v1/community-interfaces") + async def community_interfaces(request): + interfaces = await self.community_interfaces_manager.get_interfaces() + return web.json_response({"interfaces": interfaces}) + # enable reticulum interface @routes.post("/api/v1/reticulum/interfaces/enable") async def reticulum_interfaces_enable(request): @@ -2671,8 +2913,11 @@ class ReticulumMeshChat: # set optional UDPInterface options InterfaceEditor.update_value(interface_details, data, "device") - # handle RNodeInterface - if interface_type == "RNodeInterface": + # handle RNodeInterface and RNodeIPInterface + if interface_type in ("RNodeInterface", "RNodeIPInterface"): + # map RNodeIPInterface to RNodeInterface for Reticulum config + interface_details["type"] = "RNodeInterface" + # ensure port provided interface_port = data.get("port") if interface_port is None or interface_port == "": @@ -2900,6 +3145,24 @@ class ReticulumMeshChat: interface_details["command"] = interface_command interface_details["respawn_delay"] = interface_respawn_delay + # interface discovery options + for discovery_key in ( + "discoverable", + "discovery_name", + "announce_interval", + "reachable_on", + "discovery_stamp_value", + "discovery_encrypt", + "publish_ifac", + "latitude", + "longitude", + "height", + "discovery_frequency", + "discovery_bandwidth", + "discovery_modulation", + ): + InterfaceEditor.update_value(interface_details, data, discovery_key) + # set common interface options InterfaceEditor.update_value(interface_details, data, "bitrate") InterfaceEditor.update_value(interface_details, data, "mode") @@ -3113,6 +3376,53 @@ class ReticulumMeshChat: return websocket_response + @routes.get("/ws/telephone/audio") + async def telephone_audio_ws(request): + websocket_response = web.WebSocketResponse( + max_msg_size=5 * 1024 * 1024, + ) + await websocket_response.prepare(request) + + # Early guard on config + if not self.web_audio_bridge.config_enabled(): + await websocket_response.send_str( + json.dumps( + {"type": "error", "message": "Web audio is disabled in config"}, + ), + ) + else: + await self.web_audio_bridge.send_status(websocket_response) + attached = self.web_audio_bridge.attach_client(websocket_response) + if not attached: + await websocket_response.send_str( + json.dumps( + {"type": "error", "message": "No active call to attach"}, + ), + ) + + async for msg in websocket_response: + msg: WSMessage = msg + if msg.type == WSMsgType.BINARY: + self.web_audio_bridge.push_client_frame(msg.data) + elif msg.type == WSMsgType.TEXT: + try: + data = json.loads(msg.data) + if data.get("type") == "attach": + self.web_audio_bridge.attach_client(websocket_response) + elif data.get("type") == "ping": + await websocket_response.send_str( + json.dumps({"type": "pong"}), + ) + except Exception as e: + logging.exception( + f"Error processing websocket text message: {e}", + ) + elif msg.type == WSMsgType.ERROR: + print(f"telephone audio ws error {websocket_response.exception()}") + + self.web_audio_bridge.detach_client(websocket_response) + return websocket_response + # get app info @routes.get("/api/v1/app/info") async def app_info(request): @@ -3125,13 +3435,79 @@ class ReticulumMeshChat: # Get total paths total_paths = 0 + is_connected_to_shared_instance = False + shared_instance_address = None if hasattr(self, "reticulum") and self.reticulum: try: path_table = self.reticulum.get_path_table() total_paths = len(path_table) - except Exception: + except Exception: # noqa: S110 pass + is_connected_to_shared_instance = getattr( + self.reticulum, + "is_connected_to_shared_instance", + False, + ) + + if is_connected_to_shared_instance: + # Try to find the shared instance address from active connections + try: + for conn in process.connections(kind="all"): + if conn.status == psutil.CONN_ESTABLISHED and conn.raddr: + # Check for common Reticulum shared instance ports or UNIX sockets + if ( + isinstance(conn.raddr, tuple) + and conn.raddr[1] == 37428 + ): + shared_instance_address = ( + f"{conn.raddr[0]}:{conn.raddr[1]}" + ) + break + if ( + isinstance(conn.raddr, str) + and ( + "rns" in conn.raddr or "reticulum" in conn.raddr + ) + and ".sock" in conn.raddr + ): + shared_instance_address = conn.raddr + break + except Exception: # noqa: S110 + pass + + # Fallback to reading config if not found via connections + if not shared_instance_address: + try: + config_dir = getattr(self, "reticulum_config_dir", None) + if not config_dir: + config_dir = getattr( + RNS.Reticulum, + "configdir", + os.path.expanduser("~/.reticulum"), + ) + + config_path = os.path.join(config_dir, "config") + if os.path.isfile(config_path): + cp = configparser.ConfigParser() + cp.read(config_path) + if cp.has_section("reticulum"): + shared_port = cp.getint( + "reticulum", + "shared_instance_port", + fallback=37428, + ) + shared_bind = cp.get( + "reticulum", + "shared_instance_bind", + fallback="127.0.0.1", + ) + shared_instance_address = ( + f"{shared_bind}:{shared_port}" + ) + except Exception: # noqa: S110 + pass + # Calculate announce rates current_time = time.time() announces_per_second = len( @@ -3157,7 +3533,7 @@ class ReticulumMeshChat: if total_duration > 0: avg_download_speed_bps = total_bytes / total_duration - db_files = self._get_database_file_stats() + db_files = self.database._get_database_file_stats() return web.json_response( { @@ -3165,25 +3541,44 @@ class ReticulumMeshChat: "version": self.get_app_version(), "lxmf_version": LXMF.__version__, "rns_version": RNS.__version__, + "lxst_version": self.get_lxst_version(), "python_version": platform.python_version(), + "dependencies": { + "aiohttp": self.get_package_version("aiohttp"), + "aiohttp_session": self.get_package_version( + "aiohttp-session", + ), + "cryptography": self.get_package_version("cryptography"), + "psutil": self.get_package_version("psutil"), + "requests": self.get_package_version("requests"), + "websockets": self.get_package_version("websockets"), + "audioop_lts": ( + self.get_package_version("audioop-lts") + if sys.version_info >= (3, 13) + else "n/a" + ), + "ply": self.get_package_version("ply"), + "bcrypt": self.get_package_version("bcrypt"), + "lxmfy": self.get_package_version("lxmfy"), + }, "storage_path": self.storage_path, "database_path": self.database_path, "database_file_size": db_files["main_bytes"], "database_files": db_files, "sqlite": { - "journal_mode": self._get_pragma_value( + "journal_mode": self.database._get_pragma_value( "journal_mode", "unknown", ), - "synchronous": self._get_pragma_value( + "synchronous": self.database._get_pragma_value( "synchronous", None, ), - "wal_autocheckpoint": self._get_pragma_value( + "wal_autocheckpoint": self.database._get_pragma_value( "wal_autocheckpoint", None, ), - "busy_timeout": self._get_pragma_value( + "busy_timeout": self.database._get_pragma_value( "busy_timeout", None, ), @@ -3193,15 +3588,8 @@ class ReticulumMeshChat: if hasattr(self, "reticulum") and self.reticulum else None ), - "is_connected_to_shared_instance": ( - getattr( - self.reticulum, - "is_connected_to_shared_instance", - False, - ) - if hasattr(self, "reticulum") and self.reticulum - else False - ), + "is_connected_to_shared_instance": is_connected_to_shared_instance, + "shared_instance_address": shared_instance_address, "is_transport_enabled": ( self.reticulum.transport_enabled() if hasattr(self, "reticulum") and self.reticulum @@ -3228,17 +3616,218 @@ class ReticulumMeshChat: "download_stats": { "avg_download_speed_bps": avg_download_speed_bps, }, + "emergency": getattr(self, "emergency", False), + "integrity_issues": getattr(self, "integrity_issues", []), "user_guidance": self.build_user_guidance_messages(), + "tutorial_seen": self.config.get("tutorial_seen", "false") + == "true", + "changelog_seen_version": self.config.get( + "changelog_seen_version", + "0.0.0", + ), }, }, ) + # get changelog + @routes.get("/api/v1/app/changelog") + async def app_changelog(request): + changelog_path = get_file_path("CHANGELOG.md") + if not os.path.exists(changelog_path): + # try project root if not found in package + changelog_path = os.path.join( + os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "CHANGELOG.md", + ) + + if not os.path.exists(changelog_path): + return web.json_response({"error": "Changelog not found"}, status=404) + + try: + with open(changelog_path) as f: + content = f.read() + + # Render markdown to HTML + html_content = MarkdownRenderer.render(content) + + return web.json_response( + { + "changelog": content, + "html": html_content, + "version": app_version, + }, + ) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + + # mark tutorial as seen + @routes.post("/api/v1/app/tutorial/seen") + async def app_tutorial_seen(request): + self.config.set("tutorial_seen", True) + return web.json_response({"message": "Tutorial marked as seen"}) + + # acknowledge and reset integrity issues + @routes.post("/api/v1/app/integrity/acknowledge") + async def app_integrity_acknowledge(request): + if self.current_context: + self.current_context.integrity_manager.save_manifest() + self.integrity_issues = [] + return web.json_response( + {"message": "Integrity issues acknowledged and manifest reset"}, + ) + + # mark changelog as seen + @routes.post("/api/v1/app/changelog/seen") + async def app_changelog_seen(request): + data = await request.json() + version = data.get("version") + if not version: + return web.json_response({"error": "Version required"}, status=400) + + self.config.set("changelog_seen_version", version) + return web.json_response( + {"message": f"Changelog version {version} marked as seen"}, + ) + + # shutdown app + @routes.post("/api/v1/app/shutdown") + async def app_shutdown(request): + # perform shutdown in a separate task so we can respond to the request + async def do_shutdown(): + await asyncio.sleep(0.5) # give some time for the response to be sent + await self.shutdown(None) + self.exit_app(0) + + asyncio.create_task(do_shutdown()) + return web.json_response({"message": "Shutting down..."}) + + # get docs status + @routes.get("/api/v1/docs/status") + async def docs_status(request): + return web.json_response(self.docs_manager.get_status()) + + # update docs + @routes.post("/api/v1/docs/update") + async def docs_update(request): + version = request.query.get("version", "latest") + success = self.docs_manager.update_docs(version=version) + return web.json_response({"success": success}) + + # upload docs zip + @routes.post("/api/v1/docs/upload") + async def docs_upload(request): + try: + reader = await request.multipart() + field = await reader.next() + if field.name != "file": + return web.json_response( + {"error": "No file field in multipart request"}, + status=400, + ) + + version = request.query.get("version") + if not version: + # use timestamp if no version provided + version = f"upload-{int(time.time())}" + + zip_data = await field.read() + success = self.docs_manager.upload_zip(zip_data, version) + return web.json_response({"success": success, "version": version}) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + + # switch docs version + @routes.post("/api/v1/docs/switch") + async def docs_switch(request): + try: + data = await request.json() + version = data.get("version") + if not version: + return web.json_response( + {"error": "No version provided"}, + status=400, + ) + + success = self.docs_manager.switch_version(version) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + + # delete docs version + @routes.delete("/api/v1/docs/version/{version}") + async def docs_delete_version(request): + try: + version = request.match_info.get("version") + if not version: + return web.json_response( + {"error": "No version provided"}, + status=400, + ) + + success = self.docs_manager.delete_version(version) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + + # clear reticulum docs + @routes.delete("/api/v1/maintenance/docs/reticulum") + async def docs_clear(request): + try: + success = self.docs_manager.clear_reticulum_docs() + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + + # search docs + @routes.get("/api/v1/docs/search") + async def docs_search(request): + query = request.query.get("q", "") + lang = request.query.get("lang", "en") + results = self.docs_manager.search(query, lang) + return web.json_response({"results": results}) + + # get meshchatx docs list + @routes.get("/api/v1/meshchatx-docs/list") + async def meshchatx_docs_list(request): + return web.json_response(self.docs_manager.get_meshchatx_docs_list()) + + # get meshchatx doc content + @routes.get("/api/v1/meshchatx-docs/content") + async def meshchatx_doc_content(request): + path = request.query.get("path") + if not path: + return web.json_response({"error": "No path provided"}, status=400) + + content = self.docs_manager.get_doc_content(path) + if not content: + return web.json_response({"error": "Document not found"}, status=404) + + return web.json_response(content) + + # export docs + @routes.get("/api/v1/docs/export") + async def docs_export(request): + try: + zip_data = self.docs_manager.export_docs() + filename = ( + f"meshchatx_docs_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip" + ) + return web.Response( + body=zip_data, + content_type="application/zip", + headers={ + "Content-Disposition": f'attachment; filename="{filename}"', + }, + ) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + @routes.get("/api/v1/database/health") async def database_health(request): try: return web.json_response( { - "database": self.get_database_health_snapshot(), + "database": self.database.get_database_health_snapshot(), }, ) except Exception as e: @@ -3252,7 +3841,7 @@ class ReticulumMeshChat: @routes.post("/api/v1/database/vacuum") async def database_vacuum(request): try: - result = self.run_database_vacuum() + result = self.database.run_database_vacuum() return web.json_response( { "message": "Database vacuum completed", @@ -3270,7 +3859,7 @@ class ReticulumMeshChat: @routes.post("/api/v1/database/recover") async def database_recover(request): try: - result = self.run_database_recovery() + result = self.database.run_database_recovery() return web.json_response( { "message": "Database recovery routine completed", @@ -3288,7 +3877,7 @@ class ReticulumMeshChat: @routes.post("/api/v1/database/backup") async def database_backup(request): try: - result = self.backup_database() + result = self.database.backup_database(self.storage_path) return web.json_response( { "message": "Database backup created", @@ -3306,7 +3895,7 @@ class ReticulumMeshChat: @routes.get("/api/v1/database/backup/download") async def database_backup_download(request): try: - backup_info = self.backup_database() + backup_info = self.database.backup_database(self.storage_path) file_path = backup_info["path"] with open(file_path, "rb") as f: data = f.read() @@ -3383,7 +3972,7 @@ class ReticulumMeshChat: tmp.write(chunk) temp_path = tmp.name - result = self.restore_database(temp_path) + result = self.database.restore_database(temp_path) os.remove(temp_path) return web.json_response( @@ -3513,9 +4102,13 @@ class ReticulumMeshChat: try: data = await request.json() identity_hash = data.get("identity_hash") + keep_alive = data.get("keep_alive", False) # attempt hotswap first - success = await self.hotswap_identity(identity_hash) + success = await self.hotswap_identity( + identity_hash, + keep_alive=keep_alive, + ) if success: return web.json_response( @@ -3542,7 +4135,7 @@ class ReticulumMeshChat: def restart(): time.sleep(1) try: - os.execv(sys.executable, [sys.executable] + sys.argv) + os.execv(sys.executable, [sys.executable] + sys.argv) # noqa: S606 except Exception as e: print(f"Failed to restart: {e}") os._exit(0) @@ -3564,6 +4157,68 @@ class ReticulumMeshChat: status=500, ) + # maintenance - clear messages + @routes.delete("/api/v1/maintenance/messages") + async def maintenance_clear_messages(request): + self.database.messages.delete_all_lxmf_messages() + return web.json_response({"message": "All messages cleared"}) + + # maintenance - clear announces + @routes.delete("/api/v1/maintenance/announces") + async def maintenance_clear_announces(request): + aspect = request.query.get("aspect") + self.database.announces.delete_all_announces(aspect=aspect) + return web.json_response( + { + "message": f"Announces cleared{' for aspect ' + aspect if aspect else ''}", + }, + ) + + # maintenance - clear favorites + @routes.delete("/api/v1/maintenance/favourites") + async def maintenance_clear_favourites(request): + aspect = request.query.get("aspect") + self.database.announces.delete_all_favourites(aspect=aspect) + return web.json_response( + { + "message": f"Favourites cleared{' for aspect ' + aspect if aspect else ''}", + }, + ) + + # maintenance - clear archives + @routes.delete("/api/v1/maintenance/archives") + async def maintenance_clear_archives(request): + self.database.misc.delete_archived_pages() + return web.json_response({"message": "All archived pages cleared"}) + + # maintenance - clear LXMF icons + @routes.delete("/api/v1/maintenance/lxmf-icons") + async def maintenance_clear_lxmf_icons(request): + self.database.misc.delete_all_user_icons() + return web.json_response({"message": "All LXMF icons cleared"}) + + # maintenance - export messages + @routes.get("/api/v1/maintenance/messages/export") + async def maintenance_export_messages(request): + messages = self.database.messages.get_all_lxmf_messages() + # Convert sqlite3.Row to dict if necessary + messages_list = [dict(m) for m in messages] + return web.json_response({"messages": messages_list}) + + # maintenance - import messages + @routes.post("/api/v1/maintenance/messages/import") + async def maintenance_import_messages(request): + try: + data = await request.json() + messages = data.get("messages", []) + for msg in messages: + self.database.messages.upsert_lxmf_message(msg) + return web.json_response( + {"message": f"Successfully imported {len(messages)} messages"}, + ) + except Exception as e: + return web.json_response({"error": str(e)}, status=400) + # get config @routes.get("/api/v1/config") async def config_get(request): @@ -3577,16 +4232,181 @@ class ReticulumMeshChat: @routes.patch("/api/v1/config") async def config_update(request): # get request body as json - data = await request.json() + try: + data = await request.json() + await self.update_config(data) + try: + AsyncUtils.run_async(self.send_config_to_websocket_clients()) + except Exception as e: + print(f"Failed to broadcast config update: {e}") - # update config - await self.update_config(data) + return web.json_response( + { + "config": self.get_config_dict(), + }, + ) + except Exception: + import traceback - return web.json_response( - { - "config": self.get_config_dict(), - }, - ) + print("config_update failed:\n" + traceback.format_exc()) + return web.json_response({"error": "config_update_failed"}, status=500) + + # get or update reticulum discovery configuration + @routes.get("/api/v1/reticulum/discovery") + async def reticulum_discovery_get(request): + reticulum_config = self._get_reticulum_section() + discovery_config = { + "discover_interfaces": reticulum_config.get("discover_interfaces"), + "interface_discovery_sources": reticulum_config.get( + "interface_discovery_sources", + ), + "required_discovery_value": reticulum_config.get( + "required_discovery_value", + ), + "autoconnect_discovered_interfaces": reticulum_config.get( + "autoconnect_discovered_interfaces", + ), + "network_identity": reticulum_config.get("network_identity"), + } + + return web.json_response({"discovery": discovery_config}) + + @routes.patch("/api/v1/reticulum/discovery") + async def reticulum_discovery_patch(request): + try: + data = await request.json() + except Exception: + return web.json_response( + {"message": "Invalid request body"}, + status=400, + ) + + reticulum_config = self._get_reticulum_section() + + def update_config_value(key): + if key not in data: + return + value = data.get(key) + if value is None or value == "": + reticulum_config.pop(key, None) + else: + reticulum_config[key] = value + + for key in ( + "discover_interfaces", + "interface_discovery_sources", + "required_discovery_value", + "autoconnect_discovered_interfaces", + "network_identity", + ): + update_config_value(key) + + if not self._write_reticulum_config(): + return web.json_response( + {"message": "Failed to write Reticulum config"}, + status=500, + ) + + discovery_config = { + "discover_interfaces": reticulum_config.get("discover_interfaces"), + "interface_discovery_sources": reticulum_config.get( + "interface_discovery_sources", + ), + "required_discovery_value": reticulum_config.get( + "required_discovery_value", + ), + "autoconnect_discovered_interfaces": reticulum_config.get( + "autoconnect_discovered_interfaces", + ), + "network_identity": reticulum_config.get("network_identity"), + } + + return web.json_response({"discovery": discovery_config}) + + @routes.get("/api/v1/reticulum/discovered-interfaces") + async def reticulum_discovered_interfaces(request): + try: + discovery = InterfaceDiscovery(discover_interfaces=False) + interfaces = discovery.list_discovered_interfaces() + active = [] + try: + if hasattr(self, "reticulum") and self.reticulum: + stats = self.reticulum.get_interface_stats().get( + "interfaces", + [], + ) + active = [] + for s in stats: + name = s.get("name") or "" + parsed_host = None + parsed_port = None + if "/" in name: + try: + host_port = name.split("/")[-1].strip("[]") + if ":" in host_port: + parsed_host, parsed_port = host_port.rsplit( + ":", + 1, + ) + try: + parsed_port = int(parsed_port) + except Exception: + parsed_port = None + else: + parsed_host = host_port + except Exception: + parsed_host = None + parsed_port = None + + host = ( + s.get("target_host") or s.get("remote") or parsed_host + ) + port = ( + s.get("target_port") + or s.get("listen_port") + or parsed_port + ) + transport_id = s.get("transport_id") + if isinstance(transport_id, (bytes, bytearray)): + transport_id = transport_id.hex() + + active.append( + { + "name": name, + "short_name": s.get("short_name"), + "type": s.get("type"), + "target_host": host, + "target_port": port, + "listen_ip": s.get("listen_ip"), + "connected": s.get("connected"), + "online": s.get("online"), + "transport_id": transport_id, + "network_id": s.get("network_id"), + }, + ) + except Exception as e: + logger.debug(f"Failed to get interface stats: {e}") + + def to_jsonable(obj): + if isinstance(obj, bytes): + return obj.hex() + if isinstance(obj, dict): + return {k: to_jsonable(v) for k, v in obj.items()} + if isinstance(obj, list): + return [to_jsonable(v) for v in obj] + return obj + + return web.json_response( + { + "interfaces": to_jsonable(interfaces), + "active": to_jsonable(active), + }, + ) + except Exception as e: + return web.json_response( + {"message": f"Failed to load discovered interfaces: {e!s}"}, + status=500, + ) # enable transport mode @routes.post("/api/v1/reticulum/enable-transport") @@ -3661,68 +4481,101 @@ class ReticulumMeshChat: # Don't report active call if DND is on and it's ringing telephone_active_call = None elif self.config.telephone_allow_calls_from_contacts_only.get(): - caller_hash = ( - telephone_active_call.get_remote_identity().hash.hex() - ) - contact = self.database.contacts.get_contact_by_identity_hash( - caller_hash, - ) - if not contact: - # Don't report active call if contacts-only is on and caller is not a contact + remote_identity = telephone_active_call.get_remote_identity() + if remote_identity: + caller_hash = remote_identity.hash.hex() + contact = ( + self.database.contacts.get_contact_by_identity_hash( + caller_hash, + ) + ) + if not contact: + # Don't report active call if contacts-only is on and caller is not a contact + telephone_active_call = None + else: + # Don't report active call if we cannot identify the caller telephone_active_call = None if telephone_active_call is not None: - # get remote identity hash - remote_identity_hash = None - remote_identity_name = None - remote_icon = None remote_identity = telephone_active_call.get_remote_identity() - if remote_identity is not None: - remote_identity_hash = remote_identity.hash.hex() - remote_identity_name = self.get_name_for_identity_hash( - remote_identity_hash, + if remote_identity is None: + telephone_active_call = None + + if telephone_active_call is not None: + # remote_identity is already fetched and checked for None above + remote_hash = remote_identity.hash.hex() + remote_destination_hash = RNS.Destination.hash( + remote_identity, + "lxmf", + "delivery", + ).hex() + remote_telephony_hash = self.get_lxst_telephony_hash_for_identity_hash( + remote_hash, + ) + remote_name = None + if self.telephone_manager.get_name_for_identity_hash: + remote_name = self.telephone_manager.get_name_for_identity_hash( + remote_hash, ) - # get lxmf destination hash to look up icon - lxmf_destination_hash = RNS.Destination.hash( - remote_identity, - "lxmf", - "delivery", - ).hex() - remote_icon = self.database.misc.get_user_icon( - lxmf_destination_hash, - ) + # get lxmf destination hash to look up icon + lxmf_destination_hash = RNS.Destination.hash( + remote_identity, + "lxmf", + "delivery", + ).hex() + + remote_icon = self.database.misc.get_user_icon(lxmf_destination_hash) + + # Check if contact and get custom image + contact = self.database.contacts.get_contact_by_identity_hash( + remote_hash, + ) + custom_image = contact["custom_image"] if contact else None active_call = { "hash": telephone_active_call.hash.hex(), - "status": self.telephone_manager.telephone.call_status, - "is_incoming": telephone_active_call.is_incoming, - "is_outgoing": telephone_active_call.is_outgoing, - "remote_identity_hash": remote_identity_hash, - "remote_identity_name": remote_identity_name, + "remote_identity_hash": remote_hash, + "remote_destination_hash": remote_destination_hash, + "remote_identity_name": remote_name, "remote_icon": dict(remote_icon) if remote_icon else None, + "custom_image": custom_image, + "is_incoming": telephone_active_call.is_incoming, + "status": self.telephone_manager.telephone.call_status, + "remote_telephony_hash": remote_telephony_hash, "audio_profile_id": self.telephone_manager.telephone.transmit_codec.profile if hasattr( self.telephone_manager.telephone.transmit_codec, "profile", ) else None, - "tx_packets": getattr(telephone_active_call, "tx", 0), - "rx_packets": getattr(telephone_active_call, "rx", 0), - "tx_bytes": getattr(telephone_active_call, "txbytes", 0), - "rx_bytes": getattr(telephone_active_call, "rxbytes", 0), - "is_mic_muted": self.telephone_manager.telephone.transmit_muted, - "is_speaker_muted": self.telephone_manager.telephone.receive_muted, + "is_recording": self.telephone_manager.is_recording, "is_voicemail": self.voicemail_manager.is_recording, "call_start_time": self.telephone_manager.call_start_time, - "is_contact": bool( - self.database.contacts.get_contact_by_identity_hash( - remote_identity_hash, - ), - ) - if remote_identity_hash - else False, + "is_contact": contact is not None, + "tx_bytes": 0, + "rx_bytes": 0, + "tx_packets": 0, + "rx_packets": 0, } + link = getattr(self.telephone_manager, "call_stats", {}).get("link") + if link: + active_call["tx_bytes"] = getattr(link, "txbytes", 0) + active_call["rx_bytes"] = getattr(link, "rxbytes", 0) + active_call["tx_packets"] = getattr(link, "tx", 0) + active_call["rx_packets"] = getattr(link, "rx", 0) + + initiation_target_hash = self.telephone_manager.initiation_target_hash + initiation_target_name = None + if initiation_target_hash: + try: + contact = self.database.contacts.get_contact_by_identity_hash( + initiation_target_hash, + ) + if contact: + initiation_target_name = contact.name + except Exception: # noqa: S110 + pass return web.json_response( { @@ -3730,11 +4583,35 @@ class ReticulumMeshChat: "is_busy": self.telephone_manager.telephone.busy, "call_status": self.telephone_manager.telephone.call_status, "active_call": active_call, - "is_mic_muted": self.telephone_manager.telephone.transmit_muted, - "is_speaker_muted": self.telephone_manager.telephone.receive_muted, + "is_mic_muted": self.telephone_manager.transmit_muted, + "is_speaker_muted": self.telephone_manager.receive_muted, "voicemail": { "is_recording": self.voicemail_manager.is_recording, "unread_count": self.database.voicemails.get_unread_count(), + "latest_id": self.database.voicemails.get_latest_voicemail_id(), + }, + "initiation_status": self.telephone_manager.initiation_status, + "initiation_target_hash": initiation_target_hash, + "initiation_target_name": initiation_target_name, + "web_audio": { + "enabled": getattr( + self.config.telephone_web_audio_enabled, + "get", + lambda: False, + )(), + "allow_fallback": getattr( + self.config.telephone_web_audio_allow_fallback, + "get", + lambda: True, + )(), + "has_client": bool( + getattr(self.web_audio_bridge, "clients", []), + ), + "frame_ms": getattr( + self.telephone_manager.telephone, + "target_frame_time_ms", + None, + ), }, }, ) @@ -3748,6 +4625,11 @@ class ReticulumMeshChat: return web.json_response({"message": "No active call"}, status=404) caller_identity = active_call.get_remote_identity() + if not caller_identity: + return web.json_response( + {"message": "Caller identity not found"}, + status=404, + ) # answer call await asyncio.to_thread( @@ -3764,7 +4646,8 @@ class ReticulumMeshChat: # hangup active telephone call @routes.get("/api/v1/telephone/hangup") async def telephone_hangup(request): - await asyncio.to_thread(self.telephone_manager.telephone.hangup) + await asyncio.to_thread(self.telephone_manager.hangup) + return web.json_response( { "message": "Hanging up call...", @@ -3797,23 +4680,23 @@ class ReticulumMeshChat: # mute/unmute transmit @routes.get("/api/v1/telephone/mute-transmit") async def telephone_mute_transmit(request): - await asyncio.to_thread(self.telephone_manager.telephone.mute_transmit) + await asyncio.to_thread(self.telephone_manager.mute_transmit) return web.json_response({"message": "Microphone muted"}) @routes.get("/api/v1/telephone/unmute-transmit") async def telephone_unmute_transmit(request): - await asyncio.to_thread(self.telephone_manager.telephone.unmute_transmit) + await asyncio.to_thread(self.telephone_manager.unmute_transmit) return web.json_response({"message": "Microphone unmuted"}) # mute/unmute receive @routes.get("/api/v1/telephone/mute-receive") async def telephone_mute_receive(request): - await asyncio.to_thread(self.telephone_manager.telephone.mute_receive) + await asyncio.to_thread(self.telephone_manager.mute_receive) return web.json_response({"message": "Speaker muted"}) @routes.get("/api/v1/telephone/unmute-receive") async def telephone_unmute_receive(request): - await asyncio.to_thread(self.telephone_manager.telephone.unmute_receive) + await asyncio.to_thread(self.telephone_manager.unmute_receive) return web.json_response({"message": "Speaker unmuted"}) # get call history @@ -3833,18 +4716,37 @@ class ReticulumMeshChat: d = dict(row) remote_identity_hash = d.get("remote_identity_hash") if remote_identity_hash: + # try to resolve name if unknown or missing + if ( + not d.get("remote_identity_name") + or d.get("remote_identity_name") == "Unknown" + ): + resolved_name = self.get_name_for_identity_hash( + remote_identity_hash, + ) + if resolved_name: + d["remote_identity_name"] = resolved_name + lxmf_hash = self.get_lxmf_destination_hash_for_identity_hash( remote_identity_hash, ) + tele_hash = self.get_lxst_telephony_hash_for_identity_hash( + remote_identity_hash, + ) if lxmf_hash: + d["remote_destination_hash"] = lxmf_hash icon = self.database.misc.get_user_icon(lxmf_hash) if icon: d["remote_icon"] = dict(icon) - d["is_contact"] = bool( - self.database.contacts.get_contact_by_identity_hash( - remote_identity_hash, - ), + if tele_hash: + d["remote_telephony_hash"] = tele_hash + + contact = self.database.contacts.get_contact_by_identity_hash( + remote_identity_hash, ) + d["is_contact"] = contact is not None + if contact: + d["contact_image"] = contact.get("custom_image") call_history.append(d) return web.json_response( @@ -3864,6 +4766,12 @@ class ReticulumMeshChat: async def telephone_switch_audio_profile(request): profile_id = request.match_info.get("profile_id") try: + if self.telephone_manager.telephone is None: + return web.json_response( + {"message": "Telephone not initialized"}, + status=400, + ) + await asyncio.to_thread( self.telephone_manager.telephone.switch_profile, int(profile_id), @@ -3875,6 +4783,7 @@ class ReticulumMeshChat: return web.json_response({"message": str(e)}, status=500) # initiate a telephone call + # initiate outgoing telephone call @routes.get("/api/v1/telephone/call/{identity_hash}") async def telephone_call(request): # make sure telephone enabled @@ -3886,75 +4795,52 @@ class ReticulumMeshChat: status=503, ) + # check if busy, but ignore stale busy when no active call + is_busy = self.telephone_manager.telephone.busy + if is_busy and not self.telephone_manager.telephone.active_call: + # If there's no active call and we're not currently initiating, + # we shouldn't be busy. + if not self.telephone_manager.initiation_status: + is_busy = False + + if is_busy or self.telephone_manager.initiation_status: + return web.json_response( + { + "message": "Telephone is busy", + }, + status=400, + ) + # get path params identity_hash_hex = request.match_info.get("identity_hash", "") timeout_seconds = int(request.query.get("timeout", 15)) - # convert hash to bytes - identity_hash_bytes = bytes.fromhex(identity_hash_hex) - - # try to find identity - destination_identity = self.recall_identity(identity_hash_hex) - - # if identity not found, try to resolve it by requesting a path - if destination_identity is None: - # determine identity hash - # if the provided hash is a known destination, get its identity hash - announce = self.database.announces.get_announce_by_hash( - identity_hash_hex, - ) - if announce: - identity_hash_bytes = bytes.fromhex(announce["identity_hash"]) - - # calculate telephony destination hash - telephony_destination_hash = ( - RNS.Destination.hash_from_name_and_identity( - f"{LXST.APP_NAME}.telephony", - identity_hash_bytes, - ) - ) - - # request path to telephony destination - if not RNS.Transport.has_path(telephony_destination_hash): - print( - f"Requesting path to telephony destination: {telephony_destination_hash.hex()}", - ) - RNS.Transport.request_path(telephony_destination_hash) - - # wait for path - timeout_after_seconds = time.time() + timeout_seconds - while ( - not RNS.Transport.has_path(telephony_destination_hash) - and time.time() < timeout_after_seconds - ): - await asyncio.sleep(0.1) - - # try to recall again now that we might have a path/announce - destination_identity = self.recall_identity(identity_hash_hex) - if destination_identity is None: - # try recalling by telephony destination hash - destination_identity = self.recall_identity( - telephony_destination_hash.hex(), - ) - - # ensure identity was found - if destination_identity is None: + try: + # convert hash to bytes + identity_hash_bytes = bytes.fromhex(identity_hash_hex) + except Exception: return web.json_response( { - "message": "Call Failed: Destination identity not found.", + "message": "Invalid identity hash", }, - status=503, + status=400, ) - # initiate call - await asyncio.to_thread( - self.telephone_manager.telephone.call, - destination_identity, - ) + # initiate call in background to be non-blocking for the UI + async def _initiate(): + try: + await self.telephone_manager.initiate( + identity_hash_bytes, + timeout_seconds=timeout_seconds, + ) + except Exception as e: + print(f"Failed to initiate call to {identity_hash_hex}: {e}") + + asyncio.create_task(_initiate()) return web.json_response( { - "message": "Calling...", + "message": "Call initiation started", }, ) @@ -3964,14 +4850,13 @@ class ReticulumMeshChat: from LXST.Primitives.Telephony import Profiles # get audio profiles - audio_profiles = [] - for available_profile in Profiles.available_profiles(): - audio_profiles.append( - { - "id": available_profile, - "name": Profiles.profile_name(available_profile), - }, - ) + audio_profiles = [ + { + "id": available_profile, + "name": Profiles.profile_name(available_profile), + } + for available_profile in Profiles.available_profiles() + ] return web.json_response( { @@ -4029,10 +4914,16 @@ class ReticulumMeshChat: lxmf_hash = self.get_lxmf_destination_hash_for_identity_hash( remote_identity_hash, ) + tele_hash = self.get_lxst_telephony_hash_for_identity_hash( + remote_identity_hash, + ) if lxmf_hash: + d["remote_destination_hash"] = lxmf_hash icon = self.database.misc.get_user_icon(lxmf_hash) if icon: d["remote_icon"] = dict(icon) + if tele_hash: + d["remote_telephony_hash"] = tele_hash voicemails.append(d) return web.json_response( @@ -4073,7 +4964,10 @@ class ReticulumMeshChat: "greeting.opus", ) if os.path.exists(filepath): - return web.FileResponse(filepath) + return web.FileResponse( + filepath, + headers={"Content-Type": "audio/opus"}, + ) return web.json_response( {"message": "Greeting audio not found"}, status=404, @@ -4083,6 +4977,20 @@ class ReticulumMeshChat: @routes.get("/api/v1/telephone/voicemails/{id}/audio") async def telephone_voicemail_audio(request): voicemail_id = request.match_info.get("id") + try: + voicemail_id = int(voicemail_id) + except (ValueError, TypeError): + return web.json_response( + {"message": "Invalid voicemail ID"}, + status=400, + ) + + if not self.voicemail_manager: + return web.json_response( + {"message": "Voicemail manager not available"}, + status=503, + ) + voicemail = self.database.voicemails.get_voicemail(voicemail_id) if voicemail: filepath = os.path.join( @@ -4090,7 +4998,11 @@ class ReticulumMeshChat: voicemail["filename"], ) if os.path.exists(filepath): - return web.FileResponse(filepath) + # Browsers might need a proper content type for .opus files + return web.FileResponse( + filepath, + headers={"Content-Type": "audio/opus"}, + ) RNS.log( f"Voicemail: Recording file missing for ID {voicemail_id}: {filepath}", RNS.LOG_ERROR, @@ -4100,6 +5012,85 @@ class ReticulumMeshChat: status=404, ) + # list call recordings + @routes.get("/api/v1/telephone/recordings") + async def telephone_recordings(request): + search = request.query.get("search", None) + limit = int(request.query.get("limit", 10)) + offset = int(request.query.get("offset", 0)) + recordings_rows = self.database.telephone.get_call_recordings( + search=search, + limit=limit, + offset=offset, + ) + recordings = [] + for row in recordings_rows: + d = dict(row) + remote_identity_hash = d.get("remote_identity_hash") + if remote_identity_hash: + lxmf_hash = self.get_lxmf_destination_hash_for_identity_hash( + remote_identity_hash, + ) + if lxmf_hash: + icon = self.database.misc.get_user_icon(lxmf_hash) + if icon: + d["remote_icon"] = dict(icon) + recordings.append(d) + + return web.json_response({"recordings": recordings}) + + # serve call recording audio + @routes.get("/api/v1/telephone/recordings/{id}/audio/{side}") + async def telephone_recording_audio(request): + recording_id = request.match_info.get("id") + try: + recording_id = int(recording_id) + except (ValueError, TypeError): + return web.json_response( + {"message": "Invalid recording ID"}, + status=400, + ) + + side = request.match_info.get("side") # rx or tx + recording = self.database.telephone.get_call_recording(recording_id) + if recording: + filename = recording[f"filename_{side}"] + if not filename: + return web.json_response( + {"message": f"No {side} recording found"}, + status=404, + ) + + filepath = os.path.join( + self.telephone_manager.recordings_dir, + filename, + ) + if os.path.exists(filepath): + return web.FileResponse( + filepath, + headers={"Content-Type": "audio/opus"}, + ) + + return web.json_response({"message": "Recording not found"}, status=404) + + # delete call recording + @routes.delete("/api/v1/telephone/recordings/{id}") + async def telephone_recording_delete(request): + recording_id = request.match_info.get("id") + recording = self.database.telephone.get_call_recording(recording_id) + if recording: + for side in ["rx", "tx"]: + filename = recording[f"filename_{side}"] + if filename: + filepath = os.path.join( + self.telephone_manager.recordings_dir, + filename, + ) + if os.path.exists(filepath): + os.remove(filepath) + self.database.telephone.delete_call_recording(recording_id) + return web.json_response({"message": "ok"}) + # generate greeting @routes.post("/api/v1/telephone/voicemail/generate-greeting") async def telephone_voicemail_generate_greeting(request): @@ -4188,15 +5179,68 @@ class ReticulumMeshChat: @routes.get("/api/v1/telephone/ringtones/status") async def telephone_ringtone_status(request): - primary = self.database.ringtones.get_primary() - return web.json_response( - { - "has_custom_ringtone": primary is not None, - "enabled": self.config.custom_ringtone_enabled.get(), - "filename": primary["filename"] if primary else None, - "id": primary["id"] if primary else None, - }, - ) + try: + caller_hash = request.query.get("caller_hash") + + ringtone_id = None + + # 1. check contact preferred ringtone + if caller_hash: + contact = self.database.contacts.get_contact_by_identity_hash( + caller_hash, + ) + if contact and contact.get("preferred_ringtone_id"): + ringtone_id = contact["preferred_ringtone_id"] + + # 2. check global preferred for non-contacts + if ringtone_id is None: + preferred_id = self.config.ringtone_preferred_id.get() + if preferred_id: + ringtone_id = preferred_id + + # 3. fallback to primary + if ringtone_id is None: + primary = self.database.ringtones.get_primary() + if primary: + ringtone_id = primary["id"] + + # 4. handle random if selected (-1) + if ringtone_id == -1: + import random + + ringtones = self.database.ringtones.get_all() + if ringtones: + ringtone_id = random.choice(ringtones)["id"] # noqa: S311 + else: + ringtone_id = None + + has_custom = ringtone_id is not None + ringtone = ( + self.database.ringtones.get_by_id(ringtone_id) + if has_custom + else None + ) + + return web.json_response( + { + "has_custom_ringtone": has_custom and ringtone is not None, + "enabled": self.config.custom_ringtone_enabled.get(), + "filename": ringtone["filename"] if ringtone else None, + "id": ringtone_id if ringtone_id != -1 else None, + "volume": self.config.ringtone_volume.get() / 100.0, + }, + ) + except Exception as e: + logger.error(f"Error in telephone_ringtone_status: {e}") + return web.json_response( + { + "has_custom_ringtone": False, + "enabled": self.config.custom_ringtone_enabled.get(), + "filename": None, + "id": None, + "volume": self.config.ringtone_volume.get() / 100.0, + }, + ) @routes.get("/api/v1/telephone/ringtones/{id}/audio") async def telephone_ringtone_audio(request): @@ -4205,10 +5249,19 @@ class ReticulumMeshChat: if not ringtone: return web.json_response({"message": "Ringtone not found"}, status=404) + download = request.query.get("download") == "1" + filepath = self.ringtone_manager.get_ringtone_path( ringtone["storage_filename"], ) if os.path.exists(filepath): + if download: + return web.FileResponse( + filepath, + headers={ + "Content-Disposition": f'attachment; filename="{ringtone["filename"]}"', + }, + ) return web.FileResponse(filepath) return web.json_response( {"message": "Ringtone audio file not found"}, @@ -4322,10 +5375,16 @@ class ReticulumMeshChat: lxmf_hash = self.get_lxmf_destination_hash_for_identity_hash( remote_identity_hash, ) + tele_hash = self.get_lxst_telephony_hash_for_identity_hash( + remote_identity_hash, + ) if lxmf_hash: + d["remote_destination_hash"] = lxmf_hash icon = self.database.misc.get_user_icon(lxmf_hash) if icon: d["remote_icon"] = dict(icon) + if tele_hash: + d["remote_telephony_hash"] = tele_hash contacts.append(d) return web.json_response(contacts) @@ -4335,14 +5394,46 @@ class ReticulumMeshChat: data = await request.json() name = data.get("name") remote_identity_hash = data.get("remote_identity_hash") + lxmf_address = data.get("lxmf_address") + lxst_address = data.get("lxst_address") + preferred_ringtone_id = data.get("preferred_ringtone_id") + custom_image = data.get("custom_image") + is_telemetry_trusted = data.get("is_telemetry_trusted", 0) - if not name or not remote_identity_hash: + if not name: return web.json_response( - {"message": "Name and identity hash required"}, + {"message": "Name is required"}, status=400, ) - self.database.contacts.add_contact(name, remote_identity_hash) + if not remote_identity_hash: + # Try to derive identity from LXMF or LXST address + lookup_hash = lxmf_address or lxst_address + if lookup_hash: + announce = self.database.announces.get_announce_by_hash(lookup_hash) + if announce: + remote_identity_hash = announce.get("identity_hash") + else: + # try to recall identity from RNS + ident = self.recall_identity(lookup_hash) + if ident: + remote_identity_hash = ident.hash.hex() + + if not remote_identity_hash: + return web.json_response( + {"message": "Identity hash is required or could not be derived"}, + status=400, + ) + + self.database.contacts.add_contact( + name, + remote_identity_hash, + lxmf_address=lxmf_address, + lxst_address=lxst_address, + preferred_ringtone_id=preferred_ringtone_id, + custom_image=custom_image, + is_telemetry_trusted=is_telemetry_trusted, + ) return web.json_response({"message": "Contact added"}) @routes.patch("/api/v1/telephone/contacts/{id}") @@ -4351,11 +5442,23 @@ class ReticulumMeshChat: data = await request.json() name = data.get("name") remote_identity_hash = data.get("remote_identity_hash") + lxmf_address = data.get("lxmf_address") + lxst_address = data.get("lxst_address") + preferred_ringtone_id = data.get("preferred_ringtone_id") + custom_image = data.get("custom_image") + clear_image = data.get("clear_image", False) + is_telemetry_trusted = data.get("is_telemetry_trusted") self.database.contacts.update_contact( contact_id, - name, - remote_identity_hash, + name=name, + remote_identity_hash=remote_identity_hash, + lxmf_address=lxmf_address, + lxst_address=lxst_address, + preferred_ringtone_id=preferred_ringtone_id, + custom_image=custom_image, + clear_image=clear_image, + is_telemetry_trusted=is_telemetry_trusted, ) return web.json_response({"message": "Contact updated"}) @@ -4395,8 +5498,19 @@ class ReticulumMeshChat: identity_hash = request.query.get("identity_hash", None) destination_hash = request.query.get("destination_hash", None) search_query = request.query.get("search", None) - limit = request.query.get("limit", None) - offset = request.query.get("offset", None) + + try: + limit = request.query.get("limit") + limit = int(limit) if limit is not None else None + except ValueError: + limit = None + + try: + offset = request.query.get("offset") + offset = int(offset) if offset is not None else 0 + except ValueError: + offset = 0 + include_blocked = ( request.query.get("include_blocked", "false").lower() == "true" ) @@ -4415,16 +5529,130 @@ class ReticulumMeshChat: blocked_identity_hashes=blocked_identity_hashes, ) - # process all announces to get display names and associated LXMF hashes - all_announces = [ - self.convert_db_announce_to_dict(announce) for announce in results - ] + # pre-fetch icons and other data to avoid N+1 queries in convert_db_announce_to_dict + other_user_hashes = [r["destination_hash"] for r in results] + user_icons = {} + if other_user_hashes: + db_icons = self.database.misc.get_user_icons(other_user_hashes) + for icon in db_icons: + user_icons[icon["destination_hash"]] = { + "icon_name": icon["icon_name"], + "foreground_colour": icon["foreground_colour"], + "background_colour": icon["background_colour"], + } + + # fetch custom display names + custom_names = {} + lxmf_names_for_telephony = {} + if other_user_hashes: + db_custom_names = self.database.provider.fetchall( + f"SELECT destination_hash, display_name FROM custom_destination_display_names WHERE destination_hash IN ({','.join(['?'] * len(other_user_hashes))})", # noqa: S608 + other_user_hashes, + ) + for row in db_custom_names: + custom_names[row["destination_hash"]] = row["display_name"] + + # If we're looking for telephony announces, pre-fetch LXMF announces for the same identities + if aspect == "lxst.telephony": + identity_hashes = list( + set( + [ + r["identity_hash"] + for r in results + if r.get("identity_hash") + ], + ), + ) + if identity_hashes: + lxmf_results = self.database.announces.provider.fetchall( + f"SELECT identity_hash, app_data FROM announces WHERE aspect = 'lxmf.delivery' AND identity_hash IN ({','.join(['?'] * len(identity_hashes))})", # noqa: S608 + identity_hashes, + ) + for row in lxmf_results: + lxmf_names_for_telephony[row["identity_hash"]] = ( + parse_lxmf_display_name(row["app_data"]) + ) + + # process all announces + all_announces = [] + for announce in results: + # Optimized convert_db_announce_to_dict logic inline to use pre-fetched data + if not isinstance(announce, dict): + announce = dict(announce) + + # parse display name from announce + display_name = None + is_local = ( + self.current_context + and announce["identity_hash"] == self.current_context.identity_hash + ) + + if announce["aspect"] == "lxmf.delivery": + display_name = parse_lxmf_display_name(announce["app_data"]) + elif announce["aspect"] == "nomadnetwork.node": + display_name = parse_nomadnetwork_node_display_name( + announce["app_data"], + ) + elif announce["aspect"] == "lxst.telephony": + display_name = parse_lxmf_display_name(announce["app_data"]) + if not display_name or display_name == "Anonymous Peer": + # Try pre-fetched LXMF name + display_name = lxmf_names_for_telephony.get( + announce["identity_hash"], + ) + + if not display_name or display_name == "Anonymous Peer": + if is_local and self.current_context: + display_name = self.current_context.config.display_name.get() + else: + # try to resolve name from identity hash (checks contacts too) + display_name = ( + self.get_name_for_identity_hash(announce["identity_hash"]) + or "Anonymous Peer" + ) + + # get current hops away + hops = RNS.Transport.hops_to( + bytes.fromhex(announce["destination_hash"]), + ) + + # ensure created_at and updated_at have Z suffix + created_at = str(announce["created_at"]) + if created_at and "+" not in created_at and "Z" not in created_at: + created_at += "Z" + updated_at = str(announce["updated_at"]) + if updated_at and "+" not in updated_at and "Z" not in updated_at: + updated_at += "Z" + + all_announces.append( + { + "id": announce["id"], + "destination_hash": announce["destination_hash"], + "aspect": announce["aspect"], + "identity_hash": announce["identity_hash"], + "identity_public_key": announce["identity_public_key"], + "app_data": announce["app_data"], + "hops": hops, + "rssi": announce["rssi"], + "snr": announce["snr"], + "quality": announce["quality"], + "created_at": created_at, + "updated_at": updated_at, + "display_name": display_name, + "custom_display_name": custom_names.get( + announce["destination_hash"], + ), + "lxmf_user_icon": user_icons.get(announce["destination_hash"]), + "contact_image": announce.get("contact_image"), + }, + ) # apply search query filter if provided if search_query: q = search_query.lower() - filtered = [] - for a in all_announces: + all_announces = [ + a + for a in all_announces if ( (a.get("display_name") and q in a["display_name"].lower()) or ( @@ -4433,18 +5661,17 @@ class ReticulumMeshChat: ) or (a.get("identity_hash") and q in a["identity_hash"].lower()) or ( - a.get("lxmf_destination_hash") - and q in a["lxmf_destination_hash"].lower() + a.get("custom_display_name") + and q in a["custom_display_name"].lower() ) - ): - filtered.append(a) - all_announces = filtered + ) + ] # apply pagination total_count = len(all_announces) if offset is not None or limit is not None: - start = int(offset) if offset else 0 - end = start + int(limit) if limit else total_count + start = offset + end = start + (limit if limit is not None else total_count) paginated_results = all_announces[start:end] else: paginated_results = all_announces @@ -4467,7 +5694,7 @@ class ReticulumMeshChat: # process favourites favourites = [ - self.convert_db_favourite_to_dict(favourite) for favourite in results + convert_db_favourite_to_dict(favourite) for favourite in results ] return web.json_response( @@ -4592,10 +5819,8 @@ class ReticulumMeshChat: archive["destination_hash"], ) if db_announce and db_announce["aspect"] == "nomadnetwork.node": - node_name = ( - ReticulumMeshChat.parse_nomadnetwork_node_display_name( - db_announce["app_data"], - ) + node_name = parse_nomadnetwork_node_display_name( + db_announce["app_data"], ) archives.append( @@ -4622,12 +5847,36 @@ class ReticulumMeshChat: }, ) + # delete archived pages + @routes.delete("/api/v1/nomadnet/archives") + async def delete_archived_pages(request): + # get archive IDs from body + data = await request.json() + ids = data.get("ids", []) + + if not ids: + return web.json_response( + { + "message": "No archive IDs provided!", + }, + status=400, + ) + + # delete archives from database + self.database.misc.delete_archived_pages(ids=ids) + + return web.json_response( + { + "message": f"Deleted {len(ids)} archives!", + }, + ) + @routes.get("/api/v1/lxmf/propagation-node/status") async def propagation_node_status(request): return web.json_response( { "propagation_node_status": { - "state": self.convert_propagation_node_state_to_string( + "state": convert_propagation_node_state_to_string( self.message_router.propagation_transfer_state, ), "progress": self.message_router.propagation_transfer_progress @@ -4680,7 +5929,10 @@ class ReticulumMeshChat: # limit results if limit is not None: - results = results[: int(limit)] + try: + results = results[: int(limit)] + except (ValueError, TypeError): + pass # process announces lxmf_propagation_nodes = [] @@ -4711,7 +5963,7 @@ class ReticulumMeshChat: lxmf_delivery_announce is not None and lxmf_delivery_announce["app_data"] is not None ): - operator_display_name = self.parse_lxmf_display_name( + operator_display_name = parse_lxmf_display_name( lxmf_delivery_announce["app_data"], None, ) @@ -4719,25 +5971,30 @@ class ReticulumMeshChat: nomadnetwork_node_announce is not None and nomadnetwork_node_announce["app_data"] is not None ): - operator_display_name = ( - ReticulumMeshChat.parse_nomadnetwork_node_display_name( - nomadnetwork_node_announce["app_data"], - None, - ) + operator_display_name = parse_nomadnetwork_node_display_name( + nomadnetwork_node_announce["app_data"], + None, ) # parse app_data so we can see if propagation is enabled or disabled for this node is_propagation_enabled = None per_transfer_limit = None - propagation_node_data = ( - ReticulumMeshChat.parse_lxmf_propagation_node_app_data( - announce["app_data"], - ) + propagation_node_data = parse_lxmf_propagation_node_app_data( + announce["app_data"], ) if propagation_node_data is not None: is_propagation_enabled = propagation_node_data["enabled"] per_transfer_limit = propagation_node_data["per_transfer_limit"] + # ensure created_at and updated_at have Z suffix for UTC if they don't have a timezone + created_at = str(announce["created_at"]) + if created_at and "+" not in created_at and "Z" not in created_at: + created_at += "Z" + + updated_at = str(announce["updated_at"]) + if updated_at and "+" not in updated_at and "Z" not in updated_at: + updated_at += "Z" + lxmf_propagation_nodes.append( { "destination_hash": announce["destination_hash"], @@ -4745,8 +6002,8 @@ class ReticulumMeshChat: "operator_display_name": operator_display_name, "is_propagation_enabled": is_propagation_enabled, "per_transfer_limit": per_transfer_limit, - "created_at": announce["created_at"], - "updated_at": announce["updated_at"], + "created_at": created_at, + "updated_at": updated_at, }, ) @@ -5185,6 +6442,120 @@ class ReticulumMeshChat: status=500, ) + @routes.get("/api/v1/rnpath/table") + async def rnpath_table(request): + max_hops = request.query.get("max_hops") + if max_hops: + max_hops = int(max_hops) + + search = request.query.get("search") + interface = request.query.get("interface") + hops = request.query.get("hops") + if hops: + hops = int(hops) + + page = int(request.query.get("page", 1)) + limit = int(request.query.get("limit", 50)) + + try: + result = self.rnpath_handler.get_path_table( + max_hops=max_hops, + search=search, + interface=interface, + hops=hops, + page=page, + limit=limit, + ) + return web.json_response(result) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.get("/api/v1/rnpath/rates") + async def rnpath_rates(request): + try: + rates = self.rnpath_handler.get_rate_table() + return web.json_response({"rates": rates}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.post("/api/v1/rnpath/drop") + async def rnpath_drop(request): + data = await request.json() + destination_hash = data.get("destination_hash") + if not destination_hash: + return web.json_response( + {"message": "destination_hash is required"}, + status=400, + ) + try: + success = self.rnpath_handler.drop_path(destination_hash) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.post("/api/v1/rnpath/drop-via") + async def rnpath_drop_via(request): + data = await request.json() + transport_instance_hash = data.get("transport_instance_hash") + if not transport_instance_hash: + return web.json_response( + {"message": "transport_instance_hash is required"}, + status=400, + ) + try: + success = self.rnpath_handler.drop_all_via(transport_instance_hash) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.post("/api/v1/rnpath/drop-queues") + async def rnpath_drop_queues(request): + try: + self.rnpath_handler.drop_announce_queues() + return web.json_response({"success": True}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.post("/api/v1/rnpath/request") + async def rnpath_request(request): + data = await request.json() + destination_hash = data.get("destination_hash") + if not destination_hash: + return web.json_response( + {"message": "destination_hash is required"}, + status=400, + ) + try: + success = self.rnpath_handler.request_path(destination_hash) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.get("/api/v1/rnpath/trace/{destination_hash}") + async def rnpath_trace(request): + destination_hash = request.match_info.get("destination_hash") + if not destination_hash: + return web.json_response( + {"error": "destination_hash is required"}, + status=400, + ) + try: + if not self.rnpath_trace_handler: + return web.json_response( + { + "error": "RNPathTraceHandler not initialized for current context", + }, + status=503, + ) + result = await self.rnpath_trace_handler.trace_path(destination_hash) + return web.json_response(result) + except Exception as e: + import traceback + + error_msg = f"Trace route failed: {e}\n{traceback.format_exc()}" + print(error_msg) + return web.json_response({"error": error_msg}, status=500) + @routes.post("/api/v1/rnprobe") async def rnprobe(request): data = await request.json() @@ -5296,6 +6667,140 @@ class ReticulumMeshChat: status=500, ) + @routes.get("/api/v1/bots/status") + async def bots_status(request): + try: + status = self.bot_handler.get_status() + templates = self.bot_handler.get_available_templates() + return web.json_response( + { + "status": status, + "templates": templates, + "detection_error": status.get("detection_error"), + }, + ) + except Exception as e: + return web.json_response( + {"message": str(e)}, + status=500, + ) + + @routes.post("/api/v1/bots/start") + async def bots_start(request): + data = await request.json() + template_id = data.get("template_id") + name = data.get("name") + bot_id = data.get("bot_id") + + if not template_id: + return web.json_response( + {"message": "template_id is required"}, + status=400, + ) + + try: + bot_id = self.bot_handler.start_bot( + template_id, + name=name, + bot_id=bot_id, + ) + return web.json_response({"bot_id": bot_id, "success": True}) + except Exception as e: + return web.json_response( + {"message": str(e)}, + status=500, + ) + + @routes.post("/api/v1/bots/stop") + async def bots_stop(request): + data = await request.json() + bot_id = data.get("bot_id") + + if not bot_id: + return web.json_response( + {"message": "bot_id is required"}, + status=400, + ) + + try: + success = self.bot_handler.stop_bot(bot_id) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response( + {"message": str(e)}, + status=500, + ) + + @routes.post("/api/v1/bots/restart") + async def bots_restart(request): + data = await request.json() + bot_id = data.get("bot_id") + + if not bot_id: + return web.json_response( + {"message": "bot_id is required"}, + status=400, + ) + + try: + new_id = self.bot_handler.restart_bot(bot_id) + return web.json_response({"bot_id": new_id, "success": True}) + except Exception as e: + return web.json_response( + {"message": str(e)}, + status=500, + ) + + @routes.post("/api/v1/bots/delete") + async def bots_delete(request): + data = await request.json() + bot_id = data.get("bot_id") + + if not bot_id: + return web.json_response( + {"message": "bot_id is required"}, + status=400, + ) + + try: + success = self.bot_handler.delete_bot(bot_id) + return web.json_response({"success": success}) + except Exception as e: + return web.json_response( + {"message": str(e)}, + status=500, + ) + + @routes.get("/api/v1/bots/export") + async def bots_export(request): + bot_id = request.query.get("bot_id") + + if not bot_id: + return web.json_response( + {"message": "bot_id is required"}, + status=400, + ) + + try: + id_path = self.bot_handler.get_bot_identity_path(bot_id) + if not id_path or not os.path.exists(id_path): + return web.json_response( + {"message": "Identity file not found"}, + status=404, + ) + + return web.FileResponse( + id_path, + headers={ + "Content-Disposition": f'attachment; filename="bot_{bot_id}_identity"', + }, + ) + except Exception as e: + return web.json_response( + {"message": str(e)}, + status=500, + ) + # get custom destination display name @routes.get("/api/v1/destination/{destination_hash}/custom-display-name") async def destination_custom_display_name_get(request): @@ -5355,7 +6860,7 @@ class ReticulumMeshChat: lxmf_stamp_cost = None announce = self.database.announces.get_announce_by_hash(destination_hash) if announce is not None: - lxmf_stamp_cost = ReticulumMeshChat.parse_lxmf_stamp_cost( + lxmf_stamp_cost = parse_lxmf_stamp_cost( announce["app_data"], ) @@ -5415,9 +6920,12 @@ class ReticulumMeshChat: "ifac_signature" ].hex() - if interface.get("hash"): - interface["hash"] = interface["hash"].hex() - except Exception: + try: + if interface.get("hash"): + interface["hash"] = interface["hash"].hex() + except Exception: # noqa: S110 + pass + except Exception: # noqa: S110 pass return web.json_response( @@ -5437,7 +6945,7 @@ class ReticulumMeshChat: if hasattr(self, "reticulum") and self.reticulum: try: all_paths = self.reticulum.get_path_table() - except Exception: + except Exception: # noqa: S110 pass total_count = len(all_paths) @@ -5558,9 +7066,10 @@ class ReticulumMeshChat: return web.json_response( { - "lxmf_message": self.convert_lxmf_message_to_dict( + "lxmf_message": convert_lxmf_message_to_dict( lxmf_message, include_attachments=False, + reticulum=self.reticulum, ), }, ) @@ -5591,7 +7100,7 @@ class ReticulumMeshChat: message_hash, ) if db_lxmf_message is not None: - lxmf_message = self.convert_db_lxmf_message_to_dict(db_lxmf_message) + lxmf_message = convert_db_lxmf_message_to_dict(db_lxmf_message) return web.json_response( { @@ -5675,7 +7184,7 @@ class ReticulumMeshChat: # convert to response json lxmf_messages = [ - self.convert_db_lxmf_message_to_dict(db_lxmf_message) + convert_db_lxmf_message_to_dict(db_lxmf_message) for db_lxmf_message in results ] @@ -5786,166 +7295,253 @@ class ReticulumMeshChat: @routes.get("/api/v1/lxmf/conversations") async def lxmf_conversations_get(request): # get query params - search_query = request.query.get("q", None) - filter_unread = ReticulumMeshChat.parse_bool_query_param( + search_query = request.query.get("search", request.query.get("q", None)) + filter_unread = parse_bool_query_param( request.query.get( "unread", request.query.get("filter_unread", "false"), ), ) - filter_failed = ReticulumMeshChat.parse_bool_query_param( + filter_failed = parse_bool_query_param( request.query.get( "failed", request.query.get("filter_failed", "false"), ), ) - filter_has_attachments = ReticulumMeshChat.parse_bool_query_param( + filter_has_attachments = parse_bool_query_param( request.query.get( "has_attachments", request.query.get("filter_has_attachments", "false"), ), ) + folder_id = request.query.get("folder_id") + if folder_id is not None: + try: + folder_id = int(folder_id) + except ValueError: + folder_id = None + + # get pagination params + try: + limit = request.query.get("limit") + limit = int(limit) if limit is not None else None + except ValueError: + limit = None + + try: + offset = request.query.get("offset") + offset = int(offset) if offset is not None else 0 + except ValueError: + offset = 0 local_hash = self.local_lxmf_destination.hexhash - search_destination_hashes = set() - if search_query is not None and search_query != "": - search_destination_hashes = self.search_destination_hashes_by_message( - search_query, - ) - # fetch conversations from database - db_conversations = self.message_handler.get_conversations(local_hash) + # fetch conversations from database with optimized query + db_conversations = self.message_handler.get_conversations( + local_hash, + search=search_query, + filter_unread=filter_unread, + filter_failed=filter_failed, + filter_has_attachments=filter_has_attachments, + folder_id=folder_id, + limit=limit, + offset=offset, + ) conversations = [] - for db_message in db_conversations: - # determine other user hash - if db_message["source_hash"] == local_hash: - other_user_hash = db_message["destination_hash"] - else: - other_user_hash = db_message["source_hash"] + for row in db_conversations: + other_user_hash = row["peer_hash"] - # determine latest message data - latest_message_title = db_message["title"] - latest_message_preview = db_message["content"] - latest_message_timestamp = db_message["timestamp"] - latest_message_has_attachments = self.message_fields_have_attachments( - db_message["fields"], + # determine display name + display_name = "Anonymous Peer" + if row["peer_app_data"]: + display_name = parse_lxmf_display_name( + app_data_base64=row["peer_app_data"], + ) + + # user icon + user_icon = None + if row["icon_name"]: + user_icon = { + "icon_name": row["icon_name"], + "foreground_colour": row["foreground_colour"], + "background_colour": row["background_colour"], + } + + # contact image + contact_image = ( + row["contact_image"] if "contact_image" in row.keys() else None ) - # using timestamp (sent time) for updated_at as it is more reliable across restarts - # and represents the actual time the message was created by the sender. - # we convert it to ISO format for the frontend. - updated_at = datetime.fromtimestamp( - latest_message_timestamp, - UTC, - ).isoformat() + # check if is_unread (using last_read_at from join) + is_unread = False + if not row["last_read_at"]: + is_unread = True + else: + last_read_at = datetime.fromisoformat(row["last_read_at"]) + if last_read_at.tzinfo is None: + last_read_at = last_read_at.replace(tzinfo=UTC) + is_unread = row["timestamp"] > last_read_at.timestamp() - # check if conversation has attachments - has_attachments = self.conversation_has_attachments(other_user_hash) - - # find user icon from database - lxmf_user_icon = None - db_lxmf_user_icon = self.database.misc.get_user_icon(other_user_hash) - if db_lxmf_user_icon: - lxmf_user_icon = { - "icon_name": db_lxmf_user_icon["icon_name"], - "foreground_colour": db_lxmf_user_icon["foreground_colour"], - "background_colour": db_lxmf_user_icon["background_colour"], - } + # Add extra check for notification viewed state if unread + if is_unread and filter_unread: + if self.database.messages.is_notification_viewed( + other_user_hash, + row["timestamp"], + ): + is_unread = False + if filter_unread: + continue # Skip this conversation if filtering unread and it's actually viewed # add to conversations conversations.append( { - "display_name": self.get_lxmf_conversation_name( - other_user_hash, - ), - "custom_display_name": self.get_custom_destination_display_name( - other_user_hash, - ), + "display_name": display_name, + "custom_display_name": row["custom_display_name"], + "contact_image": contact_image, "destination_hash": other_user_hash, - "is_unread": self.database.messages.is_conversation_unread( + "is_unread": is_unread, + "is_tracking": self.database.telemetry.is_tracking( other_user_hash, ), - "failed_messages_count": self.lxmf_conversation_failed_messages_count( - other_user_hash, + "failed_messages_count": row["failed_count"], + "has_attachments": message_fields_have_attachments( + row["fields"], ), - "has_attachments": has_attachments, - "latest_message_title": latest_message_title, - "latest_message_preview": latest_message_preview, - "latest_message_created_at": latest_message_timestamp, - "latest_message_has_attachments": latest_message_has_attachments, - "lxmf_user_icon": lxmf_user_icon, - "updated_at": updated_at, + "latest_message_title": row["title"], + "latest_message_preview": row["content"], + "latest_message_created_at": row["timestamp"], + "lxmf_user_icon": user_icon, + "updated_at": datetime.fromtimestamp( + row["timestamp"], + UTC, + ).isoformat(), }, ) - if search_query is not None and search_query != "": - lowered_query = search_query.lower() - filtered = [] - for conversation in conversations: - matches_display = ( - conversation["display_name"] - and lowered_query in conversation["display_name"].lower() - ) - matches_custom = ( - conversation["custom_display_name"] - and lowered_query in conversation["custom_display_name"].lower() - ) - matches_destination = ( - conversation["destination_hash"] - and lowered_query in conversation["destination_hash"].lower() - ) - matches_latest_title = ( - conversation["latest_message_title"] - and lowered_query - in conversation["latest_message_title"].lower() - ) - matches_latest_preview = ( - conversation["latest_message_preview"] - and lowered_query - in conversation["latest_message_preview"].lower() - ) - matches_history = ( - conversation["destination_hash"] in search_destination_hashes - ) - if ( - matches_display - or matches_custom - or matches_destination - or matches_latest_title - or matches_latest_preview - or matches_history - ): - filtered.append(conversation) - conversations = filtered - - if filter_unread: - conversations = [c for c in conversations if c["is_unread"]] - # Filter out notifications that have been viewed - filtered_conversations = [] - for c in conversations: - message_timestamp = c["latest_message_created_at"] - if not self.database.messages.is_notification_viewed( - c["destination_hash"], - message_timestamp, - ): - filtered_conversations.append(c) - conversations = filtered_conversations - - if filter_failed: - conversations = [ - c for c in conversations if c["failed_messages_count"] > 0 - ] - - if filter_has_attachments: - conversations = [c for c in conversations if c["has_attachments"]] - return web.json_response( { "conversations": conversations, }, ) + @routes.get("/api/v1/lxmf/folders") + async def lxmf_folders_get(request): + folders = self.database.messages.get_all_folders() + return web.json_response([dict(f) for f in folders]) + + @routes.post("/api/v1/lxmf/folders") + async def lxmf_folders_post(request): + data = await request.json() + name = data.get("name") + if not name: + return web.json_response({"message": "Name is required"}, status=400) + try: + self.database.messages.create_folder(name) + return web.json_response({"message": "Folder created"}) + except Exception as e: + return web.json_response({"message": str(e)}, status=500) + + @routes.patch("/api/v1/lxmf/folders/{id}") + async def lxmf_folders_patch(request): + folder_id = int(request.match_info["id"]) + data = await request.json() + name = data.get("name") + if not name: + return web.json_response({"message": "Name is required"}, status=400) + self.database.messages.rename_folder(folder_id, name) + return web.json_response({"message": "Folder renamed"}) + + @routes.delete("/api/v1/lxmf/folders/{id}") + async def lxmf_folders_delete(request): + folder_id = int(request.match_info["id"]) + self.database.messages.delete_folder(folder_id) + return web.json_response({"message": "Folder deleted"}) + + @routes.post("/api/v1/lxmf/conversations/move-to-folder") + async def lxmf_conversations_move_to_folder(request): + data = await request.json() + peer_hashes = data.get("peer_hashes", []) + folder_id = data.get("folder_id") # Can be None to remove from folder + if not peer_hashes: + return web.json_response( + {"message": "peer_hashes is required"}, + status=400, + ) + self.database.messages.move_conversations_to_folder(peer_hashes, folder_id) + return web.json_response({"message": "Conversations moved"}) + + @routes.post("/api/v1/lxmf/conversations/bulk-mark-as-read") + async def lxmf_conversations_bulk_mark_read(request): + data = await request.json() + destination_hashes = data.get("destination_hashes", []) + if not destination_hashes: + return web.json_response( + {"message": "destination_hashes is required"}, + status=400, + ) + self.database.messages.mark_conversations_as_read(destination_hashes) + return web.json_response({"message": "Conversations marked as read"}) + + @routes.post("/api/v1/lxmf/conversations/bulk-delete") + async def lxmf_conversations_bulk_delete(request): + data = await request.json() + destination_hashes = data.get("destination_hashes", []) + if not destination_hashes: + return web.json_response( + {"message": "destination_hashes is required"}, + status=400, + ) + local_hash = self.local_lxmf_destination.hexhash + for dest_hash in destination_hashes: + self.message_handler.delete_conversation(local_hash, dest_hash) + return web.json_response({"message": "Conversations deleted"}) + + @routes.get("/api/v1/lxmf/folders/export") + async def lxmf_folders_export(request): + folders = [dict(f) for f in self.database.messages.get_all_folders()] + mappings = [ + dict(m) for m in self.database.messages.get_all_conversation_folders() + ] + return web.json_response({"folders": folders, "mappings": mappings}) + + @routes.post("/api/v1/lxmf/folders/import") + async def lxmf_folders_import(request): + data = await request.json() + folders = data.get("folders", []) + mappings = data.get("mappings", []) + + # We'll try to recreate folders by name to avoid ID conflicts + folder_name_to_new_id = {} + for f in folders: + try: + self.database.messages.create_folder(f["name"]) + except Exception as e: + logger.debug(f"Folder '{f['name']}' likely already exists: {e}") + + # Refresh folder list to get new IDs + all_folders = self.database.messages.get_all_folders() + for f in all_folders: + folder_name_to_new_id[f["name"]] = f["id"] + + # Map old IDs to new IDs if possible, or just use names if we had them + # Since IDs might change, we should have exported names too + # Let's assume the export had folder names in mappings or we match by old folder info + old_id_to_name = {f["id"]: f["name"] for f in folders} + + for m in mappings: + peer_hash = m["peer_hash"] + old_folder_id = m["folder_id"] + folder_name = old_id_to_name.get(old_folder_id) + if folder_name and folder_name in folder_name_to_new_id: + new_folder_id = folder_name_to_new_id[folder_name] + self.database.messages.move_conversation_to_folder( + peer_hash, + new_folder_id, + ) + + return web.json_response({"message": "Folders and mappings imported"}) + # mark lxmf conversation as read @routes.get("/api/v1/lxmf/conversations/{destination_hash}/mark-as-read") async def lxmf_conversations_mark_read(request): @@ -5987,7 +7583,7 @@ class ReticulumMeshChat: @routes.get("/api/v1/notifications") async def notifications_get(request): try: - filter_unread = ReticulumMeshChat.parse_bool_query_param( + filter_unread = parse_bool_query_param( request.query.get("unread", "false"), ) limit = int(request.query.get("limit", 50)) @@ -6018,7 +7614,7 @@ class ReticulumMeshChat: other_user_hash = db_message["source_hash"] # Determine display name - display_name = self.get_name_for_lxmf_destination_hash( + display_name = self.get_lxmf_conversation_name( other_user_hash, ) custom_display_name = ( @@ -6076,7 +7672,7 @@ class ReticulumMeshChat: or n["remote_hash"] ) else: - display_name = self.get_name_for_lxmf_destination_hash( + display_name = self.get_lxmf_conversation_name( lxmf_hash, ) icon = self.database.misc.get_user_icon(lxmf_hash) @@ -6161,12 +7757,47 @@ class ReticulumMeshChat: try: self.database.misc.add_blocked_destination(destination_hash) - # drop any existing paths to this destination - try: - if hasattr(self, "reticulum") and self.reticulum: - self.reticulum.drop_path(bytes.fromhex(destination_hash)) - except Exception as e: - print(f"Failed to drop path for blocked destination: {e}") + + # add to Reticulum blackhole if available and enabled + if self.config.blackhole_integration_enabled.get(): + try: + if hasattr(self, "reticulum") and self.reticulum: + # Try to resolve identity hash from destination hash + identity_hash = None + announce = self.database.announces.get_announce_by_hash( + destination_hash, + ) + if announce and announce.get("identity_hash"): + identity_hash = announce["identity_hash"] + + # Use resolved identity hash or fallback to destination hash + target_hash = identity_hash or destination_hash + dest_bytes = bytes.fromhex(target_hash) + + # Reticulum 1.1.0+ + if hasattr(self.reticulum, "blackhole_identity"): + reason = ( + f"Blocked in MeshChatX (from {destination_hash})" + if identity_hash + else "Blocked in MeshChatX" + ) + self.reticulum.blackhole_identity( + dest_bytes, + reason=reason, + ) + else: + # fallback to dropping path + self.reticulum.drop_path(dest_bytes) + except Exception as e: + print(f"Failed to blackhole identity in Reticulum: {e}") + else: + # fallback to just dropping path if integration disabled + try: + if hasattr(self, "reticulum") and self.reticulum: + self.reticulum.drop_path(bytes.fromhex(destination_hash)) + except Exception as e: + print(f"Failed to drop path for blocked destination: {e}") + return web.json_response({"message": "ok"}) except Exception: return web.json_response( @@ -6186,10 +7817,58 @@ class ReticulumMeshChat: try: self.database.misc.delete_blocked_destination(destination_hash) + + # remove from Reticulum blackhole if available and enabled + if self.config.blackhole_integration_enabled.get(): + try: + if hasattr(self, "reticulum") and self.reticulum: + # Try to resolve identity hash from destination hash + identity_hash = None + announce = self.database.announces.get_announce_by_hash( + destination_hash, + ) + if announce and announce.get("identity_hash"): + identity_hash = announce["identity_hash"] + + # Use resolved identity hash or fallback to destination hash + target_hash = identity_hash or destination_hash + dest_bytes = bytes.fromhex(target_hash) + + if hasattr(self.reticulum, "unblackhole_identity"): + self.reticulum.unblackhole_identity(dest_bytes) + except Exception as e: + print(f"Failed to unblackhole identity in Reticulum: {e}") + return web.json_response({"message": "ok"}) except Exception as e: return web.json_response({"error": str(e)}, status=500) + @routes.get("/api/v1/reticulum/blackhole") + async def reticulum_blackhole_get(request): + if not hasattr(self, "reticulum") or not self.reticulum: + return web.json_response( + {"error": "Reticulum not initialized"}, + status=503, + ) + + try: + if hasattr(self.reticulum, "get_blackholed_identities"): + identities = self.reticulum.get_blackholed_identities() + # Convert bytes keys to hex strings + formatted = {} + for h, info in identities.items(): + formatted[h.hex()] = { + "source": info.get("source", b"").hex() + if info.get("source") + else None, + "until": info.get("until"), + "reason": info.get("reason"), + } + return web.json_response({"blackholed_identities": formatted}) + return web.json_response({"blackholed_identities": {}}) + except Exception as e: + return web.json_response({"error": str(e)}, status=500) + # get spam keywords @routes.get("/api/v1/spam-keywords") async def spam_keywords_get(request): @@ -6264,7 +7943,7 @@ class ReticulumMeshChat: metadata = self.map_manager.get_metadata() if metadata: return web.json_response(metadata) - return web.json_response({"error": "No offline map loaded"}, status=404) + return web.json_response({"loaded": False}) # get map tile @routes.get("/api/v1/map/tiles/{z}/{x}/{y}") @@ -6280,7 +7959,10 @@ class ReticulumMeshChat: tile_data = self.map_manager.get_tile(z, x, y) if tile_data: return web.Response(body=tile_data, content_type="image/png") - return web.Response(status=404) + + # If tile not found, return a transparent 1x1 PNG instead of 404 + # to avoid browser console errors in offline mode. + return web.Response(body=TRANSPARENT_TILE, content_type="image/png") except Exception: return web.Response(status=400) @@ -6321,6 +8003,38 @@ class ReticulumMeshChat: ) return web.json_response({"error": "File not found"}, status=404) + # map drawings + @routes.get("/api/v1/map/drawings") + async def get_map_drawings(request): + identity_hash = self.identity.hash.hex() + rows = self.database.map_drawings.get_drawings(identity_hash) + drawings = [dict(row) for row in rows] + return web.json_response({"drawings": drawings}) + + @routes.post("/api/v1/map/drawings") + async def save_map_drawing(request): + identity_hash = self.identity.hash.hex() + data = await request.json() + name = data.get("name") + drawing_data = data.get("data") + self.database.map_drawings.upsert_drawing(identity_hash, name, drawing_data) + return web.json_response({"message": "Drawing saved successfully"}) + + @routes.delete("/api/v1/map/drawings/{drawing_id}") + async def delete_map_drawing(request): + drawing_id = request.match_info.get("drawing_id") + self.database.map_drawings.delete_drawing(drawing_id) + return web.json_response({"message": "Drawing deleted successfully"}) + + @routes.patch("/api/v1/map/drawings/{drawing_id}") + async def update_map_drawing(request): + drawing_id = request.match_info.get("drawing_id") + data = await request.json() + name = data.get("name") + drawing_data = data.get("data") + self.database.map_drawings.update_drawing(drawing_id, name, drawing_data) + return web.json_response({"message": "Drawing updated successfully"}) + # get latest telemetry for all peers @routes.get("/api/v1/telemetry/peers") async def get_all_latest_telemetry(request): @@ -6337,10 +8051,40 @@ class ReticulumMeshChat: if r["physical_link"] else None, "updated_at": r["updated_at"], + "is_tracking": self.database.telemetry.is_tracking( + r["destination_hash"], + ), }, ) return web.json_response({"telemetry": telemetry_list}) + @routes.get("/api/v1/telemetry/trusted-peers") + async def telemetry_trusted_peers_get(request): + # get all contacts that are telemetry trusted + contacts = self.database.provider.fetchall( + "SELECT * FROM contacts WHERE is_telemetry_trusted = 1 ORDER BY name ASC", + ) + return web.json_response({"trusted_peers": [dict(c) for c in contacts]}) + + # toggle telemetry tracking for a destination + @routes.post("/api/v1/telemetry/tracking/{destination_hash}/toggle") + async def toggle_telemetry_tracking(request): + destination_hash = request.match_info["destination_hash"] + data = await request.json() + is_tracking = data.get("is_tracking") + + new_status = self.database.telemetry.toggle_tracking( + destination_hash, + is_tracking, + ) + return web.json_response({"status": "ok", "is_tracking": new_status}) + + # get all tracked peers + @routes.get("/api/v1/telemetry/tracking") + async def get_tracked_peers(request): + results = self.database.telemetry.get_tracked_peers() + return web.json_response({"tracked_peers": results}) + # get telemetry history for a destination @routes.get("/api/v1/telemetry/history/{destination_hash}") async def get_telemetry_history(request): @@ -6514,6 +8258,8 @@ class ReticulumMeshChat: @web.middleware async def mime_type_middleware(request, handler): response = await handler(request) + if response is None: + return None path = request.path if path.endswith(".js") or path.endswith(".mjs"): response.headers["Content-Type"] = ( @@ -6527,33 +8273,214 @@ class ReticulumMeshChat: response.headers["Content-Type"] = "application/wasm" elif path.endswith(".html"): response.headers["Content-Type"] = "text/html; charset=utf-8" + elif path.endswith(".opus"): + response.headers["Content-Type"] = "audio/opus" + elif path.endswith(".ogg"): + response.headers["Content-Type"] = "audio/ogg" + elif path.endswith(".wav"): + response.headers["Content-Type"] = "audio/wav" + elif path.endswith(".mp3"): + response.headers["Content-Type"] = "audio/mpeg" return response # security headers middleware @web.middleware async def security_middleware(request, handler): response = await handler(request) + if response is None: + return None # Add security headers to all responses response.headers["X-Content-Type-Options"] = "nosniff" - response.headers["X-Frame-Options"] = "DENY" + + # Allow framing for docs and rnode flasher + if request.path.startswith("/reticulum-docs/") or request.path.startswith( + "/rnode-flasher/", + ): + response.headers["X-Frame-Options"] = "SAMEORIGIN" + else: + response.headers["X-Frame-Options"] = "DENY" + response.headers["X-XSS-Protection"] = "1; mode=block" response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin" - # CSP: allow localhost for development and Electron, websockets, and blob URLs + + # CSP base configuration + connect_sources = [ + "'self'", + "ws://localhost:*", + "wss://localhost:*", + "blob:", + "https://*.tile.openstreetmap.org", + "https://tile.openstreetmap.org", + "https://nominatim.openstreetmap.org", + "https://*.cartocdn.com", + ] + + img_sources = [ + "'self'", + "data:", + "blob:", + "https://*.tile.openstreetmap.org", + "https://tile.openstreetmap.org", + "https://*.cartocdn.com", + ] + + frame_sources = [ + "'self'", + "https://reticulum.network", + ] + + script_sources = ["'self'", "'unsafe-inline'", "'unsafe-eval'"] + style_sources = ["'self'", "'unsafe-inline'"] + + if self.current_context and self.current_context.config: + # Helper to add domain from URL + def add_domain_from_url(url, target_list): + if not url: + return None + try: + parsed = urlparse(url) + if parsed.netloc: + domain = f"{parsed.scheme}://{parsed.netloc}" + if domain not in target_list: + target_list.append(domain) + return domain + except Exception: # noqa: S110 + pass + return None + + # Add configured Gitea base URL + add_domain_from_url( + self.current_context.config.gitea_base_url.get(), + connect_sources, + ) + + # Add configured docs download URLs domains + docs_urls_str = self.current_context.config.docs_download_urls.get() + docs_urls = [ + u.strip() + for u in docs_urls_str.replace("\n", ",").split(",") + if u.strip() + ] + for url in docs_urls: + domain = add_domain_from_url(url, connect_sources) + if domain and "github.com" in domain: + content_domain = "https://objects.githubusercontent.com" + if content_domain not in connect_sources: + connect_sources.append(content_domain) + + # Add map tile server domain + map_tile_url = self.current_context.config.map_tile_server_url.get() + add_domain_from_url(map_tile_url, img_sources) + add_domain_from_url(map_tile_url, connect_sources) + + # Add nominatim API domain + nominatim_url = self.current_context.config.map_nominatim_api_url.get() + add_domain_from_url(nominatim_url, connect_sources) + + # Add custom CSP sources from config + def add_extra_sources(extra_str, target_list): + if not extra_str: + return + sources = [ + s.strip() + for s in extra_str.replace("\n", ",") + .replace(";", ",") + .split(",") + if s.strip() + ] + for s in sources: + if s not in target_list: + target_list.append(s) + + add_extra_sources( + self.current_context.config.csp_extra_connect_src.get(), + connect_sources, + ) + add_extra_sources( + self.current_context.config.csp_extra_img_src.get(), + img_sources, + ) + add_extra_sources( + self.current_context.config.csp_extra_frame_src.get(), + frame_sources, + ) + add_extra_sources( + self.current_context.config.csp_extra_script_src.get(), + script_sources, + ) + add_extra_sources( + self.current_context.config.csp_extra_style_src.get(), + style_sources, + ) + csp = ( "default-src 'self'; " - "script-src 'self' 'unsafe-inline' 'unsafe-eval'; " - "style-src 'self' 'unsafe-inline'; " - "img-src 'self' data: blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org; " + f"script-src {' '.join(script_sources)}; " + f"style-src {' '.join(style_sources)}; " + f"img-src {' '.join(img_sources)}; " "font-src 'self' data:; " - "connect-src 'self' ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org; " + f"connect-src {' '.join(connect_sources)}; " "media-src 'self' blob:; " "worker-src 'self' blob:; " + f"frame-src {' '.join(frame_sources)}; " "object-src 'none'; " "base-uri 'self';" ) response.headers["Content-Security-Policy"] = csp return response + return auth_middleware, mime_type_middleware, security_middleware + + def run(self, host, port, launch_browser: bool, enable_https: bool = True): + # create route table + routes = web.RouteTableDef() + auth_middleware, mime_type_middleware, security_middleware = ( + self._define_routes(routes) + ) + + ssl_context = None + use_https = enable_https + if enable_https: + cert_dir = os.path.join(self.storage_path, "ssl") + cert_path = os.path.join(cert_dir, "cert.pem") + key_path = os.path.join(cert_dir, "key.pem") + + try: + generate_ssl_certificate(cert_path, key_path) + ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + ssl_context.load_cert_chain(cert_path, key_path) + print(f"HTTPS enabled with certificate at {cert_path}") + except Exception as e: + print(f"Failed to generate SSL certificate: {e}") + print("Falling back to HTTP") + use_https = False + + # session secret for encrypted cookies (generate once and store in shared storage) + session_secret_path = os.path.join(self.storage_dir, "session_secret") + self.session_secret_key = None + + if os.path.exists(session_secret_path): + try: + with open(session_secret_path) as f: + self.session_secret_key = f.read().strip() + except Exception as e: + print(f"Failed to read session secret from {session_secret_path}: {e}") + + if not self.session_secret_key: + # try to migrate from current identity config if available + self.session_secret_key = self.config.auth_session_secret.get() + if not self.session_secret_key: + self.session_secret_key = secrets.token_urlsafe(32) + + try: + with open(session_secret_path, "w") as f: + f.write(self.session_secret_key) + except Exception as e: + print(f"Failed to write session secret to {session_secret_path}: {e}") + + # ensure it's also in the current config for consistency + self.config.auth_session_secret.set(self.session_secret_key) + # called when web app has started async def on_startup(app): # remember main event loop @@ -6605,7 +8532,42 @@ class ReticulumMeshChat: # serve anything else from public folder # we use add_static here as it's more robust for serving directories - public_dir = get_file_path("public") + public_dir = self.get_public_path() + + # Handle documentation directories that might be in a writable storage location + # (e.g. when running from a read-only AppImage) + if self.current_context and hasattr(self.current_context, "docs_manager"): + dm = self.current_context.docs_manager + + # Custom handler for reticulum docs to allow fallback to official website + async def reticulum_docs_handler(request): + path = request.match_info.get("filename", "index.html") + if not path: + path = "index.html" + if path.endswith("/"): + path += "index.html" + + local_path = os.path.join(dm.docs_dir, path) + if os.path.exists(local_path) and os.path.isfile(local_path): + return web.FileResponse(local_path) + + # Fallback to official website + return web.HTTPFound(f"https://reticulum.network/manual/{path}") + + app.router.add_get("/reticulum-docs/{filename:.*}", reticulum_docs_handler) + + if ( + dm.meshchatx_docs_dir + and os.path.exists(dm.meshchatx_docs_dir) + and not dm.meshchatx_docs_dir.startswith(public_dir) + ): + app.router.add_static( + "/meshchatx-docs/", + dm.meshchatx_docs_dir, + name="meshchatx_docs_storage", + follow_symlinks=True, + ) + if os.path.exists(public_dir): app.router.add_static("/", public_dir, name="static", follow_symlinks=True) else: @@ -6624,35 +8586,107 @@ class ReticulumMeshChat: else: web.run_app(app, host=host, port=port) + # auto backup loop + async def auto_backup_loop(self, session_id, context=None): + ctx = context or self.current_context + if not ctx: + return + + # wait 5 minutes before first backup + await asyncio.sleep(300) + + while self.running and ctx.running and ctx.session_id == session_id: + try: + if not self.emergency: + print( + f"Performing scheduled auto-backup for {ctx.identity_hash}...", + ) + max_count = ctx.config.backup_max_count.get() + ctx.database.backup_database(self.storage_dir, max_count=max_count) + except Exception as e: + print(f"Auto-backup failed: {e}") + + # Sleep for 12 hours + await asyncio.sleep(12 * 3600) + + async def telemetry_tracking_loop(self, session_id, context=None): + ctx = context or self.current_context + if not ctx: + return + + while self.running and ctx.running and ctx.session_id == session_id: + try: + # Only run if telemetry is enabled globally + if not ctx.config.telemetry_enabled.get(): + await asyncio.sleep(60) + continue + + # Get all tracked peers + tracked_peers = ctx.database.telemetry.get_tracked_peers() + now = time.time() + + for peer in tracked_peers: + dest_hash = peer["destination_hash"] + interval = peer.get("interval_seconds", 60) + last_req = peer.get("last_request_at") + + if last_req is None or now - last_req >= interval: + print(f"Sending telemetry request to tracked peer: {dest_hash}") + # Send telemetry request + await self.send_message( + destination_hash=dest_hash, + content="", + commands=[{SidebandCommands.TELEMETRY_REQUEST: 0}], + delivery_method="opportunistic", + no_display=False, + context=ctx, + ) + # Update last request time + ctx.database.telemetry.update_last_request_at(dest_hash, now) + + except Exception as e: + print(f"Telemetry tracking loop error: {e}") + + # Check every 10 seconds + await asyncio.sleep(10) + # handle announcing - async def announce(self): + async def announce(self, context=None): + ctx = context or self.current_context + if not ctx: + return + # update last announced at timestamp - self.config.last_announced_at.set(int(time.time())) + ctx.config.last_announced_at.set(int(time.time())) # send announce for lxmf (ensuring name is updated before announcing) - self.local_lxmf_destination.display_name = self.config.display_name.get() - self.message_router.announce(destination_hash=self.local_lxmf_destination.hash) + ctx.local_lxmf_destination.display_name = ctx.config.display_name.get() + ctx.message_router.announce(destination_hash=ctx.local_lxmf_destination.hash) # send announce for local propagation node (if enabled) - if self.config.lxmf_local_propagation_node_enabled.get(): - self.message_router.announce_propagation_node() + if ctx.config.lxmf_local_propagation_node_enabled.get(): + ctx.message_router.announce_propagation_node() # send announce for telephone - self.telephone_manager.announce() + ctx.telephone_manager.announce(display_name=ctx.config.display_name.get()) # tell websocket clients we just announced - await self.send_announced_to_websocket_clients() + await self.send_announced_to_websocket_clients(context=ctx) # handle syncing propagation nodes - async def sync_propagation_nodes(self): + async def sync_propagation_nodes(self, context=None): + ctx = context or self.current_context + if not ctx: + return + # update last synced at timestamp - self.config.lxmf_preferred_propagation_node_last_synced_at.set(int(time.time())) + ctx.config.lxmf_preferred_propagation_node_last_synced_at.set(int(time.time())) # request messages from propagation node - self.message_router.request_messages_from_propagation_node(self.identity) + ctx.message_router.request_messages_from_propagation_node(ctx.identity) # send config to websocket clients (used to tell ui last synced at) - await self.send_config_to_websocket_clients() + await self.send_config_to_websocket_clients(context=ctx) # helper to parse boolean from possible string or bool @staticmethod @@ -6667,6 +8701,8 @@ class ReticulumMeshChat: # update display name in config if "display_name" in data and data["display_name"] != "": self.config.display_name.set(data["display_name"]) + # Update identity metadata cache + self.update_identity_metadata_cache() # update theme in config if "theme" in data and data["theme"] != "": @@ -6720,6 +8756,12 @@ class ReticulumMeshChat: # update active propagation node self.set_active_propagation_node(value) + if "lxmf_preferred_propagation_node_auto_select" in data: + value = self._parse_bool( + data["lxmf_preferred_propagation_node_auto_select"], + ) + self.config.lxmf_preferred_propagation_node_auto_select.set(value) + # update inbound stamp cost (for direct delivery messages) if "lxmf_inbound_stamp_cost" in data: value = int(data["lxmf_inbound_stamp_cost"]) @@ -6775,18 +8817,24 @@ class ReticulumMeshChat: # update lxmf user icon name in config if "lxmf_user_icon_name" in data: self.config.lxmf_user_icon_name.set(data["lxmf_user_icon_name"]) + self.database.misc.clear_last_sent_icon_hashes() + self.update_identity_metadata_cache() # update lxmf user icon foreground colour in config if "lxmf_user_icon_foreground_colour" in data: self.config.lxmf_user_icon_foreground_colour.set( data["lxmf_user_icon_foreground_colour"], ) + self.database.misc.clear_last_sent_icon_hashes() + self.update_identity_metadata_cache() # update lxmf user icon background colour in config if "lxmf_user_icon_background_colour" in data: self.config.lxmf_user_icon_background_colour.set( data["lxmf_user_icon_background_colour"], ) + self.database.misc.clear_last_sent_icon_hashes() + self.update_identity_metadata_cache() # update archiver settings if "page_archiver_enabled" in data: @@ -6804,6 +8852,14 @@ class ReticulumMeshChat: int(data["archives_max_storage_gb"]), ) + if "backup_max_count" in data: + try: + value = int(data["backup_max_count"]) + except (TypeError, ValueError): + value = self.config.backup_max_count.default_value + value = max(1, min(value, 50)) + self.config.backup_max_count.set(value) + # update crawler settings if "crawler_enabled" in data: self.config.crawler_enabled.set(self._parse_bool(data["crawler_enabled"])) @@ -6822,7 +8878,6 @@ class ReticulumMeshChat: if "auth_enabled" in data: value = self._parse_bool(data["auth_enabled"]) self.config.auth_enabled.set(value) - self.auth_enabled = value # if disabling auth, also remove the password hash from config if not value: @@ -6841,7 +8896,12 @@ class ReticulumMeshChat: self.config.map_default_lon.set(str(data["map_default_lon"])) if "map_default_zoom" in data: - self.config.map_default_zoom.set(int(data["map_default_zoom"])) + try: + value = int(data["map_default_zoom"]) + except (TypeError, ValueError): + value = None + if value is not None: + self.config.map_default_zoom.set(value) if "map_mbtiles_dir" in data: self.config.map_mbtiles_dir.set(data["map_mbtiles_dir"]) @@ -6857,6 +8917,90 @@ class ReticulumMeshChat: if "map_nominatim_api_url" in data: self.config.map_nominatim_api_url.set(data["map_nominatim_api_url"]) + # update location settings + if "location_source" in data: + self.config.location_source.set(data["location_source"]) + + if "location_manual_lat" in data: + self.config.location_manual_lat.set(str(data["location_manual_lat"])) + + if "location_manual_lon" in data: + self.config.location_manual_lon.set(str(data["location_manual_lon"])) + + if "location_manual_alt" in data: + self.config.location_manual_alt.set(str(data["location_manual_alt"])) + + if "telemetry_enabled" in data: + self.config.telemetry_enabled.set( + self._parse_bool(data["telemetry_enabled"]), + ) + + # update banishment settings + if "banished_effect_enabled" in data: + self.config.banished_effect_enabled.set( + self._parse_bool(data["banished_effect_enabled"]), + ) + + if "banished_text" in data: + self.config.banished_text.set(data["banished_text"]) + + if "banished_color" in data: + self.config.banished_color.set(data["banished_color"]) + + if "message_font_size" in data: + try: + value = int(data["message_font_size"]) + except (TypeError, ValueError): + value = None + if value is not None: + self.config.message_font_size.set(value) + + if "message_icon_size" in data: + try: + value = int(data["message_icon_size"]) + except (TypeError, ValueError): + value = None + if value is not None: + value = max(12, min(value, 96)) + self.config.message_icon_size.set(value) + + # update desktop settings + if "desktop_open_calls_in_separate_window" in data: + self.config.desktop_open_calls_in_separate_window.set( + self._parse_bool(data["desktop_open_calls_in_separate_window"]), + ) + + if "desktop_hardware_acceleration_enabled" in data: + enabled = self._parse_bool(data["desktop_hardware_acceleration_enabled"]) + self.config.desktop_hardware_acceleration_enabled.set(enabled) + + # write flag for electron to read on next launch + try: + disable_gpu_file = os.path.join(self.storage_dir, "disable-gpu") + if not enabled: + with open(disable_gpu_file, "w") as f: + f.write("true") + elif os.path.exists(disable_gpu_file): + os.remove(disable_gpu_file) + except Exception as e: + print(f"Failed to update GPU disable flag: {e}") + + if "blackhole_integration_enabled" in data: + value = self._parse_bool(data["blackhole_integration_enabled"]) + self.config.blackhole_integration_enabled.set(value) + + # update csp extra sources + if "csp_extra_connect_src" in data: + self.config.csp_extra_connect_src.set(data["csp_extra_connect_src"]) + if "csp_extra_img_src" in data: + self.config.csp_extra_img_src.set(data["csp_extra_img_src"]) + if "csp_extra_frame_src" in data: + self.config.csp_extra_frame_src.set(data["csp_extra_frame_src"]) + if "csp_extra_script_src" in data: + self.config.csp_extra_script_src.set(data["csp_extra_script_src"]) + if "csp_extra_style_src" in data: + self.config.csp_extra_style_src.set(data["csp_extra_style_src"]) + # update voicemail settings if "voicemail_enabled" in data: self.config.voicemail_enabled.set( @@ -6876,11 +9020,92 @@ class ReticulumMeshChat: int(data["voicemail_max_recording_seconds"]), ) + if "voicemail_tts_speed" in data: + self.config.voicemail_tts_speed.set(int(data["voicemail_tts_speed"])) + + if "voicemail_tts_pitch" in data: + self.config.voicemail_tts_pitch.set(int(data["voicemail_tts_pitch"])) + + if "voicemail_tts_voice" in data: + self.config.voicemail_tts_voice.set(data["voicemail_tts_voice"]) + + if "voicemail_tts_word_gap" in data: + self.config.voicemail_tts_word_gap.set(int(data["voicemail_tts_word_gap"])) + # update ringtone settings if "custom_ringtone_enabled" in data: self.config.custom_ringtone_enabled.set( self._parse_bool(data["custom_ringtone_enabled"]), ) + if "ringtone_preferred_id" in data: + self.config.ringtone_preferred_id.set(int(data["ringtone_preferred_id"])) + if "ringtone_volume" in data: + self.config.ringtone_volume.set(int(data["ringtone_volume"])) + + if "do_not_disturb_enabled" in data: + self.config.do_not_disturb_enabled.set( + self._parse_bool(data["do_not_disturb_enabled"]), + ) + + if "telephone_allow_calls_from_contacts_only" in data: + self.config.telephone_allow_calls_from_contacts_only.set( + self._parse_bool(data["telephone_allow_calls_from_contacts_only"]), + ) + + if "call_recording_enabled" in data: + value = self._parse_bool(data["call_recording_enabled"]) + self.config.call_recording_enabled.set(value) + # if a call is active, start or stop recording immediately + if ( + self.telephone_manager + and self.telephone_manager.telephone + and self.telephone_manager.telephone.active_call + ): + if value: + self.telephone_manager.start_recording() + else: + self.telephone_manager.stop_recording() + + if "telephone_tone_generator_enabled" in data: + self.config.telephone_tone_generator_enabled.set( + self._parse_bool(data["telephone_tone_generator_enabled"]), + ) + + if "telephone_tone_generator_volume" in data: + self.config.telephone_tone_generator_volume.set( + int(data["telephone_tone_generator_volume"]), + ) + + if "telephone_audio_profile_id" in data: + profile_id = int(data["telephone_audio_profile_id"]) + self.config.telephone_audio_profile_id.set(profile_id) + if self.telephone_manager and self.telephone_manager.telephone: + await asyncio.to_thread( + self.telephone_manager.telephone.switch_profile, + profile_id, + ) + + if "telephone_web_audio_enabled" in data: + self.config.telephone_web_audio_enabled.set( + self._parse_bool(data["telephone_web_audio_enabled"]), + ) + + if "telephone_web_audio_allow_fallback" in data: + self.config.telephone_web_audio_allow_fallback.set( + self._parse_bool(data["telephone_web_audio_allow_fallback"]), + ) + + if "translator_enabled" in data: + value = self._parse_bool(data["translator_enabled"]) + self.config.translator_enabled.set(value) + if hasattr(self, "translator_handler"): + self.translator_handler.enabled = value + + if "libretranslate_url" in data: + value = data["libretranslate_url"] + self.config.libretranslate_url.set(value) + if hasattr(self, "translator_handler"): + self.translator_handler.libretranslate_url = value # send config to websocket clients await self.send_config_to_websocket_clients() @@ -6890,68 +9115,42 @@ class ReticulumMeshChat: # to the following map: # - var_field1: 123 # - var_field2: 456 - @staticmethod - def convert_nomadnet_string_data_to_map(path_data: str | None): - data = {} - if path_data is not None: - for field in path_data.split("|"): - if "=" in field: - variable_name, variable_value = field.split("=") - data[f"var_{variable_name}"] = variable_value - else: - print(f"unhandled field: {field}") - return data - - @staticmethod - def convert_nomadnet_field_data_to_map(field_data): - data = {} - if field_data is not None or "{}": - try: - json_data = field_data - if isinstance(json_data, dict): - # add the prefixed keys to the result dictionary - data = {f"field_{key}": value for key, value in json_data.items()} - else: - return None - except Exception as e: - print(f"skipping invalid field data: {e}") - - return data - - # archives a page version def archive_page( self, destination_hash: str, page_path: str, content: str, is_manual: bool = False, + context=None, ): - if not is_manual and not self.config.page_archiver_enabled.get(): - return - - self.archiver_manager.archive_page( + ctx = context or self.current_context + if not ctx: + return None + return ctx.nomadnet_manager.archive_page( destination_hash, page_path, content, - max_versions=self.config.page_archiver_max_versions.get(), - max_storage_gb=self.config.archives_max_storage_gb.get(), + is_manual, ) - # returns archived page versions for a given destination and path def get_archived_page_versions(self, destination_hash: str, page_path: str): - return self.database.misc.get_archived_page_versions( + return self.nomadnet_manager.get_archived_page_versions( destination_hash, page_path, ) - # flushes all archived pages def flush_all_archived_pages(self): - self.database.misc.delete_archived_pages() + return self.nomadnet_manager.flush_all_archived_pages() # handle data received from websocket client async def on_websocket_data_received(self, client, data): # get type from client data - _type = data["type"] + if not isinstance(data, dict): + return + + _type = data.get("type") + if not _type: + return # handle ping if _type == "ping": @@ -6970,13 +9169,23 @@ class ReticulumMeshChat: # get config from websocket config = data["config"] - # update config - await self.update_config(config) + try: + await self.update_config(config) + try: + AsyncUtils.run_async(self.send_config_to_websocket_clients()) + except Exception as e: + print(f"Failed to broadcast config update: {e}") + except Exception: + import traceback + + print("config.set failed:\n" + traceback.format_exc()) # handle canceling a download elif _type == "nomadnet.download.cancel": # get data from websocket client - download_id = data["download_id"] + download_id = data.get("download_id") + if download_id is None: + return # cancel the download if download_id in self.active_downloads: @@ -6998,10 +9207,21 @@ class ReticulumMeshChat: # handle getting page archives elif _type == "nomadnet.page.archives.get": - destination_hash = data["destination_hash"] - page_path = data["page_path"] + destination_hash = data.get("destination_hash") + page_path = data.get("page_path") + + if not destination_hash or not page_path: + return + + # Try relative path first archives = self.get_archived_page_versions(destination_hash, page_path) + # If nothing found and path doesn't look like it's already absolute, + # try searching with the destination hash prefix (support for old buggy archives) + if not archives and not page_path.startswith(destination_hash): + buggy_path = f"{destination_hash}:{page_path}" + archives = self.get_archived_page_versions(destination_hash, buggy_path) + AsyncUtils.run_async( client.send_str( json.dumps( @@ -7011,11 +9231,13 @@ class ReticulumMeshChat: "page_path": page_path, "archives": [ { - "id": archive.id, - "hash": archive.hash, - "created_at": archive.created_at.isoformat() - if hasattr(archive.created_at, "isoformat") - else str(archive.created_at), + "id": archive["id"], + "hash": archive["hash"], + "destination_hash": archive["destination_hash"], + "page_path": archive["page_path"], + "created_at": archive["created_at"].isoformat() + if hasattr(archive["created_at"], "isoformat") + else str(archive["created_at"]), } for archive in archives ], @@ -7026,7 +9248,10 @@ class ReticulumMeshChat: # handle loading a specific archived page version elif _type == "nomadnet.page.archive.load": - archive_id = data["archive_id"] + archive_id = data.get("archive_id") + if archive_id is None: + return + archive = self.database.misc.get_archived_page_by_id(archive_id) if archive: @@ -7057,9 +9282,13 @@ class ReticulumMeshChat: # handle manual page archiving elif _type == "nomadnet.page.archive.add": - destination_hash = data["destination_hash"] - page_path = data["page_path"] - content = data["content"] + destination_hash = data.get("destination_hash") + page_path = data.get("page_path") + content = data.get("content") + + if not destination_hash or not page_path or not content: + return + self.archive_page(destination_hash, page_path, content, is_manual=True) # notify client that page was archived @@ -7078,8 +9307,15 @@ class ReticulumMeshChat: # handle downloading a file from a nomadnet node elif _type == "nomadnet.file.download": # get data from websocket client - destination_hash = data["nomadnet_file_download"]["destination_hash"] - file_path = data["nomadnet_file_download"]["file_path"] + download_data = data.get("nomadnet_file_download") + if not download_data: + return + + destination_hash = download_data.get("destination_hash") + file_path = download_data.get("file_path") + + if not destination_hash or not file_path: + return # convert destination hash to bytes destination_hash = bytes.fromhex(destination_hash) @@ -7199,9 +9435,16 @@ class ReticulumMeshChat: # handle downloading a page from a nomadnet node elif _type == "nomadnet.page.download": # get data from websocket client - destination_hash = data["nomadnet_page_download"]["destination_hash"] - page_path = data["nomadnet_page_download"]["page_path"] - field_data = data["nomadnet_page_download"]["field_data"] + page_download_data = data.get("nomadnet_page_download") + if not page_download_data: + return + + destination_hash = page_download_data.get("destination_hash") + page_path = page_download_data.get("page_path") + field_data = page_download_data.get("field_data") + + if not destination_hash or not page_path: + return # generate download id self.download_id_counter += 1 @@ -7215,10 +9458,10 @@ class ReticulumMeshChat: if "`" in page_path: page_path_parts = page_path.split("`") page_path_to_download = page_path_parts[0] - page_data = self.convert_nomadnet_string_data_to_map(page_path_parts[1]) + page_data = convert_nomadnet_string_data_to_map(page_path_parts[1]) # Field data - field_data = self.convert_nomadnet_field_data_to_map(field_data) + field_data = convert_nomadnet_field_data_to_map(field_data) # Combine page data and field data if page_data is not None: @@ -7411,7 +9654,10 @@ class ReticulumMeshChat: # handle ingesting an lxmf uri (paper message) elif _type == "lxm.ingest_uri": - uri = data["uri"] + uri = data.get("uri") + if not uri: + return + local_delivery_signal = "local_delivery_occurred" duplicate_signal = "duplicate_lxm" @@ -7470,10 +9716,13 @@ class ReticulumMeshChat: # handle generating a paper message uri elif _type == "lxm.generate_paper_uri": - destination_hash = data["destination_hash"] - content = data["content"] + destination_hash = data.get("destination_hash") + content = data.get("content") title = data.get("title", "") + if not destination_hash or not content: + return + try: destination_hash_bytes = bytes.fromhex(destination_hash) destination_identity = RNS.Identity.recall(destination_hash_bytes) @@ -7538,7 +9787,9 @@ class ReticulumMeshChat: # handle getting keyboard shortcuts elif _type == "keyboard_shortcuts.get": - shortcuts = self.database.misc.get_keyboard_shortcuts(self.identity.hexhash) + shortcuts = self.database.misc.get_keyboard_shortcuts( + self.identity.hash.hex(), + ) AsyncUtils.run_async( client.send_str( json.dumps( @@ -7561,7 +9812,7 @@ class ReticulumMeshChat: action = data["action"] keys = json.dumps(data["keys"]) self.database.misc.upsert_keyboard_shortcut( - self.identity.hexhash, + self.identity.hash.hex(), action, keys, ) @@ -7576,7 +9827,10 @@ class ReticulumMeshChat: # handle deleting a keyboard shortcut elif _type == "keyboard_shortcuts.delete": action = data["action"] - self.database.misc.delete_keyboard_shortcut(self.identity.hexhash, action) + self.database.misc.delete_keyboard_shortcut( + self.identity.hash.hex(), + action, + ) # notify updated AsyncUtils.run_async( self.on_websocket_data_received( @@ -7599,81 +9853,127 @@ class ReticulumMeshChat: print(f"Failed to broadcast to websocket client: {e}") # broadcasts config to all websocket clients - async def send_config_to_websocket_clients(self): + async def send_config_to_websocket_clients(self, context=None): + ctx = context or self.current_context + if not ctx: + return await self.websocket_broadcast( json.dumps( { "type": "config", - "config": self.get_config_dict(), + "config": self.get_config_dict(context=ctx), }, ), ) # broadcasts to all websocket clients that we just announced - async def send_announced_to_websocket_clients(self): + async def send_announced_to_websocket_clients(self, context=None): + ctx = context or self.current_context + if not ctx: + return await self.websocket_broadcast( json.dumps( { "type": "announced", + "identity_hash": ctx.identity_hash, }, ), ) # returns a dictionary of config - def get_config_dict(self): + def get_config_dict(self, context=None): + ctx = context or self.current_context + if not ctx: + return {} return { - "display_name": self.config.display_name.get(), - "identity_hash": self.identity.hexhash, - "lxmf_address_hash": self.local_lxmf_destination.hexhash, - "telephone_address_hash": self.telephone_manager.telephone.destination.hexhash - if self.telephone_manager.telephone + "display_name": ctx.config.display_name.get(), + "identity_hash": ctx.identity.hash.hex(), + "lxmf_address_hash": ctx.local_lxmf_destination.hexhash, + "telephone_address_hash": ctx.telephone_manager.telephone.destination.hexhash + if ctx.telephone_manager.telephone else None, "is_transport_enabled": ( self.reticulum.transport_enabled() if hasattr(self, "reticulum") and self.reticulum else False ), - "auto_announce_enabled": self.config.auto_announce_enabled.get(), - "auto_announce_interval_seconds": self.config.auto_announce_interval_seconds.get(), - "last_announced_at": self.config.last_announced_at.get(), - "theme": self.config.theme.get(), - "language": self.config.language.get(), - "auto_resend_failed_messages_when_announce_received": self.config.auto_resend_failed_messages_when_announce_received.get(), - "allow_auto_resending_failed_messages_with_attachments": self.config.allow_auto_resending_failed_messages_with_attachments.get(), - "auto_send_failed_messages_to_propagation_node": self.config.auto_send_failed_messages_to_propagation_node.get(), - "show_suggested_community_interfaces": self.config.show_suggested_community_interfaces.get(), - "lxmf_local_propagation_node_enabled": self.config.lxmf_local_propagation_node_enabled.get(), - "lxmf_local_propagation_node_address_hash": self.message_router.propagation_destination.hexhash, - "lxmf_preferred_propagation_node_destination_hash": self.config.lxmf_preferred_propagation_node_destination_hash.get(), - "lxmf_preferred_propagation_node_auto_sync_interval_seconds": self.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get(), - "lxmf_preferred_propagation_node_last_synced_at": self.config.lxmf_preferred_propagation_node_last_synced_at.get(), - "lxmf_user_icon_name": self.config.lxmf_user_icon_name.get(), - "lxmf_user_icon_foreground_colour": self.config.lxmf_user_icon_foreground_colour.get(), - "lxmf_user_icon_background_colour": self.config.lxmf_user_icon_background_colour.get(), - "lxmf_inbound_stamp_cost": self.config.lxmf_inbound_stamp_cost.get(), - "lxmf_propagation_node_stamp_cost": self.config.lxmf_propagation_node_stamp_cost.get(), - "page_archiver_enabled": self.config.page_archiver_enabled.get(), - "page_archiver_max_versions": self.config.page_archiver_max_versions.get(), - "archives_max_storage_gb": self.config.archives_max_storage_gb.get(), - "crawler_enabled": self.config.crawler_enabled.get(), - "crawler_max_retries": self.config.crawler_max_retries.get(), - "crawler_retry_delay_seconds": self.config.crawler_retry_delay_seconds.get(), - "crawler_max_concurrent": self.config.crawler_max_concurrent.get(), + "auto_announce_enabled": ctx.config.auto_announce_enabled.get(), + "auto_announce_interval_seconds": ctx.config.auto_announce_interval_seconds.get(), + "last_announced_at": ctx.config.last_announced_at.get(), + "theme": ctx.config.theme.get(), + "language": ctx.config.language.get(), + "auto_resend_failed_messages_when_announce_received": ctx.config.auto_resend_failed_messages_when_announce_received.get(), + "allow_auto_resending_failed_messages_with_attachments": ctx.config.allow_auto_resending_failed_messages_with_attachments.get(), + "auto_send_failed_messages_to_propagation_node": ctx.config.auto_send_failed_messages_to_propagation_node.get(), + "show_suggested_community_interfaces": ctx.config.show_suggested_community_interfaces.get(), + "lxmf_local_propagation_node_enabled": ctx.config.lxmf_local_propagation_node_enabled.get(), + "lxmf_local_propagation_node_address_hash": ctx.message_router.propagation_destination.hexhash, + "lxmf_preferred_propagation_node_destination_hash": ctx.config.lxmf_preferred_propagation_node_destination_hash.get(), + "lxmf_preferred_propagation_node_auto_select": ctx.config.lxmf_preferred_propagation_node_auto_select.get(), + "lxmf_preferred_propagation_node_auto_sync_interval_seconds": ctx.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get(), + "lxmf_preferred_propagation_node_last_synced_at": ctx.config.lxmf_preferred_propagation_node_last_synced_at.get(), + "lxmf_user_icon_name": ctx.config.lxmf_user_icon_name.get(), + "lxmf_user_icon_foreground_colour": ctx.config.lxmf_user_icon_foreground_colour.get(), + "lxmf_user_icon_background_colour": ctx.config.lxmf_user_icon_background_colour.get(), + "lxmf_inbound_stamp_cost": ctx.config.lxmf_inbound_stamp_cost.get(), + "lxmf_propagation_node_stamp_cost": ctx.config.lxmf_propagation_node_stamp_cost.get(), + "page_archiver_enabled": ctx.config.page_archiver_enabled.get(), + "page_archiver_max_versions": ctx.config.page_archiver_max_versions.get(), + "archives_max_storage_gb": ctx.config.archives_max_storage_gb.get(), + "backup_max_count": ctx.config.backup_max_count.get(), + "crawler_enabled": ctx.config.crawler_enabled.get(), + "crawler_max_retries": ctx.config.crawler_max_retries.get(), + "crawler_retry_delay_seconds": ctx.config.crawler_retry_delay_seconds.get(), + "crawler_max_concurrent": ctx.config.crawler_max_concurrent.get(), "auth_enabled": self.auth_enabled, - "voicemail_enabled": self.config.voicemail_enabled.get(), - "voicemail_greeting": self.config.voicemail_greeting.get(), - "voicemail_auto_answer_delay_seconds": self.config.voicemail_auto_answer_delay_seconds.get(), - "voicemail_max_recording_seconds": self.config.voicemail_max_recording_seconds.get(), - "custom_ringtone_enabled": self.config.custom_ringtone_enabled.get(), - "ringtone_filename": self.config.ringtone_filename.get(), - "map_offline_enabled": self.config.map_offline_enabled.get(), - "map_mbtiles_dir": self.config.map_mbtiles_dir.get(), - "map_tile_cache_enabled": self.config.map_tile_cache_enabled.get(), - "map_default_lat": self.config.map_default_lat.get(), - "map_default_lon": self.config.map_default_lon.get(), - "map_default_zoom": self.config.map_default_zoom.get(), - "map_tile_server_url": self.config.map_tile_server_url.get(), - "map_nominatim_api_url": self.config.map_nominatim_api_url.get(), + "voicemail_enabled": ctx.config.voicemail_enabled.get(), + "voicemail_greeting": ctx.config.voicemail_greeting.get(), + "voicemail_auto_answer_delay_seconds": ctx.config.voicemail_auto_answer_delay_seconds.get(), + "voicemail_max_recording_seconds": ctx.config.voicemail_max_recording_seconds.get(), + "voicemail_tts_speed": ctx.config.voicemail_tts_speed.get(), + "voicemail_tts_pitch": ctx.config.voicemail_tts_pitch.get(), + "voicemail_tts_voice": ctx.config.voicemail_tts_voice.get(), + "voicemail_tts_word_gap": ctx.config.voicemail_tts_word_gap.get(), + "custom_ringtone_enabled": ctx.config.custom_ringtone_enabled.get(), + "ringtone_filename": ctx.config.ringtone_filename.get(), + "ringtone_preferred_id": ctx.config.ringtone_preferred_id.get(), + "ringtone_volume": ctx.config.ringtone_volume.get(), + "map_offline_enabled": ctx.config.map_offline_enabled.get(), + "map_mbtiles_dir": ctx.config.map_mbtiles_dir.get(), + "map_tile_cache_enabled": ctx.config.map_tile_cache_enabled.get(), + "map_default_lat": ctx.config.map_default_lat.get(), + "map_default_lon": ctx.config.map_default_lon.get(), + "map_default_zoom": ctx.config.map_default_zoom.get(), + "map_tile_server_url": ctx.config.map_tile_server_url.get(), + "map_nominatim_api_url": ctx.config.map_nominatim_api_url.get(), + "do_not_disturb_enabled": ctx.config.do_not_disturb_enabled.get(), + "telephone_allow_calls_from_contacts_only": ctx.config.telephone_allow_calls_from_contacts_only.get(), + "telephone_audio_profile_id": ctx.config.telephone_audio_profile_id.get(), + "telephone_web_audio_enabled": ctx.config.telephone_web_audio_enabled.get(), + "telephone_web_audio_allow_fallback": ctx.config.telephone_web_audio_allow_fallback.get(), + "call_recording_enabled": ctx.config.call_recording_enabled.get(), + "banished_effect_enabled": ctx.config.banished_effect_enabled.get(), + "banished_text": ctx.config.banished_text.get(), + "banished_color": ctx.config.banished_color.get(), + "message_font_size": ctx.config.message_font_size.get(), + "message_icon_size": ctx.config.message_icon_size.get(), + "translator_enabled": ctx.config.translator_enabled.get(), + "libretranslate_url": ctx.config.libretranslate_url.get(), + "desktop_open_calls_in_separate_window": ctx.config.desktop_open_calls_in_separate_window.get(), + "desktop_hardware_acceleration_enabled": ctx.config.desktop_hardware_acceleration_enabled.get(), + "blackhole_integration_enabled": ctx.config.blackhole_integration_enabled.get(), + "csp_extra_connect_src": ctx.config.csp_extra_connect_src.get(), + "csp_extra_img_src": ctx.config.csp_extra_img_src.get(), + "csp_extra_frame_src": ctx.config.csp_extra_frame_src.get(), + "csp_extra_script_src": ctx.config.csp_extra_script_src.get(), + "csp_extra_style_src": ctx.config.csp_extra_style_src.get(), + "telephone_tone_generator_enabled": ctx.config.telephone_tone_generator_enabled.get(), + "telephone_tone_generator_volume": ctx.config.telephone_tone_generator_volume.get(), + "location_source": ctx.config.location_source.get(), + "location_manual_lat": ctx.config.location_manual_lat.get(), + "location_manual_lon": ctx.config.location_manual_lon.get(), + "location_manual_alt": ctx.config.location_manual_alt.get(), + "telemetry_enabled": ctx.config.telemetry_enabled.get(), } # try and get a name for the provided identity hash @@ -7725,7 +10025,7 @@ class ReticulumMeshChat: # check lxmf name from app_data if announce["app_data"] is not None: - lxmf_name = ReticulumMeshChat.parse_lxmf_display_name( + lxmf_name = parse_lxmf_display_name( app_data_base64=announce["app_data"], default_value=None, ) @@ -7752,6 +10052,26 @@ class ReticulumMeshChat: return announce["destination_hash"] return None + def get_lxst_telephony_hash_for_identity_hash(self, identity_hash: str): + # Primary: use announces table for lxst.telephony aspect + announces = self.database.announces.get_filtered_announces( + aspect="lxst.telephony", + search_term=identity_hash, + ) + if announces: + for announce in announces: + if announce["identity_hash"] == identity_hash: + return announce.get("destination_hash") + + # Fallback: derive from identity if available (same identity, different aspect) + identity = self.recall_identity(identity_hash) + if identity is not None: + try: + return RNS.Destination.hash(identity, "lxst", "telephony").hex() + except Exception: + return None + return None + def recall_identity(self, hash_hex: str) -> RNS.Identity | None: try: # 1. try reticulum recall (works for both identity and destination hashes) @@ -7791,174 +10111,6 @@ class ReticulumMeshChat: return None # convert an lxmf message to a dictionary, for sending over websocket - def convert_lxmf_message_to_dict( - self, - lxmf_message: LXMF.LXMessage, - include_attachments: bool = True, - ): - # handle fields - fields = {} - message_fields = lxmf_message.get_fields() - for field_type in message_fields: - value = message_fields[field_type] - - # handle file attachments field - if field_type == LXMF.FIELD_FILE_ATTACHMENTS: - # process file attachments - file_attachments = [] - for file_attachment in value: - file_name = file_attachment[0] - file_bytes = None - if include_attachments: - file_bytes = base64.b64encode(file_attachment[1]).decode( - "utf-8", - ) - - file_attachments.append( - { - "file_name": file_name, - "file_bytes": file_bytes, - }, - ) - - # add to fields - fields["file_attachments"] = file_attachments - - # handle image field - if field_type == LXMF.FIELD_IMAGE: - image_type = value[0] - image_bytes = None - if include_attachments: - image_bytes = base64.b64encode(value[1]).decode("utf-8") - - fields["image"] = { - "image_type": image_type, - "image_bytes": image_bytes, - } - - # handle audio field - if field_type == LXMF.FIELD_AUDIO: - audio_mode = value[0] - audio_bytes = None - if include_attachments: - audio_bytes = base64.b64encode(value[1]).decode("utf-8") - - fields["audio"] = { - "audio_mode": audio_mode, - "audio_bytes": audio_bytes, - } - - # handle telemetry field - if field_type == LXMF.FIELD_TELEMETRY: - fields["telemetry"] = Telemeter.from_packed(value) - - # convert 0.0-1.0 progress to 0.00-100 percentage - progress_percentage = round(lxmf_message.progress * 100, 2) - - # get rssi - rssi = lxmf_message.rssi - if rssi is None and hasattr(self, "reticulum") and self.reticulum: - rssi = self.reticulum.get_packet_rssi(lxmf_message.hash) - - # get snr - snr = lxmf_message.snr - if snr is None and hasattr(self, "reticulum") and self.reticulum: - snr = self.reticulum.get_packet_snr(lxmf_message.hash) - - # get quality - quality = lxmf_message.q - if quality is None and hasattr(self, "reticulum") and self.reticulum: - quality = self.reticulum.get_packet_q(lxmf_message.hash) - - return { - "hash": lxmf_message.hash.hex(), - "source_hash": lxmf_message.source_hash.hex(), - "destination_hash": lxmf_message.destination_hash.hex(), - "is_incoming": lxmf_message.incoming, - "state": self.convert_lxmf_state_to_string(lxmf_message), - "progress": progress_percentage, - "method": self.convert_lxmf_method_to_string(lxmf_message), - "delivery_attempts": lxmf_message.delivery_attempts, - "next_delivery_attempt_at": getattr( - lxmf_message, - "next_delivery_attempt", - None, - ), # attribute may not exist yet - "title": lxmf_message.title.decode("utf-8") if lxmf_message.title else "", - "content": lxmf_message.content.decode("utf-8") - if lxmf_message.content - else "", - "fields": fields, - "timestamp": lxmf_message.timestamp, - "rssi": rssi, - "snr": snr, - "quality": quality, - } - - # convert lxmf state to a human friendly string - @staticmethod - def convert_lxmf_state_to_string(lxmf_message: LXMF.LXMessage): - # convert state to string - lxmf_message_state = "unknown" - if lxmf_message.state == LXMF.LXMessage.GENERATING: - lxmf_message_state = "generating" - elif lxmf_message.state == LXMF.LXMessage.OUTBOUND: - lxmf_message_state = "outbound" - elif lxmf_message.state == LXMF.LXMessage.SENDING: - lxmf_message_state = "sending" - elif lxmf_message.state == LXMF.LXMessage.SENT: - lxmf_message_state = "sent" - elif lxmf_message.state == LXMF.LXMessage.DELIVERED: - lxmf_message_state = "delivered" - elif lxmf_message.state == LXMF.LXMessage.REJECTED: - lxmf_message_state = "rejected" - elif lxmf_message.state == LXMF.LXMessage.CANCELLED: - lxmf_message_state = "cancelled" - elif lxmf_message.state == LXMF.LXMessage.FAILED: - lxmf_message_state = "failed" - - return lxmf_message_state - - # convert lxmf method to a human friendly string - @staticmethod - def convert_lxmf_method_to_string(lxmf_message: LXMF.LXMessage): - # convert method to string - lxmf_message_method = "unknown" - if lxmf_message.method == LXMF.LXMessage.OPPORTUNISTIC: - lxmf_message_method = "opportunistic" - elif lxmf_message.method == LXMF.LXMessage.DIRECT: - lxmf_message_method = "direct" - elif lxmf_message.method == LXMF.LXMessage.PROPAGATED: - lxmf_message_method = "propagated" - elif lxmf_message.method == LXMF.LXMessage.PAPER: - lxmf_message_method = "paper" - - return lxmf_message_method - - @staticmethod - def convert_propagation_node_state_to_string(state): - # map states to strings - state_map = { - LXMRouter.PR_IDLE: "idle", - LXMRouter.PR_PATH_REQUESTED: "path_requested", - LXMRouter.PR_LINK_ESTABLISHING: "link_establishing", - LXMRouter.PR_LINK_ESTABLISHED: "link_established", - LXMRouter.PR_REQUEST_SENT: "request_sent", - LXMRouter.PR_RECEIVING: "receiving", - LXMRouter.PR_RESPONSE_RECEIVED: "response_received", - LXMRouter.PR_COMPLETE: "complete", - LXMRouter.PR_NO_PATH: "no_path", - LXMRouter.PR_LINK_FAILED: "link_failed", - LXMRouter.PR_TRANSFER_FAILED: "transfer_failed", - LXMRouter.PR_NO_IDENTITY_RCVD: "no_identity_received", - LXMRouter.PR_NO_ACCESS: "no_access", - LXMRouter.PR_FAILED: "failed", - } - - # return string for state, or fallback to unknown - if state in state_map: - return state_map[state] - return "unknown" # convert database announce to a dictionary def convert_db_announce_to_dict(self, announce): @@ -7969,13 +10121,13 @@ class ReticulumMeshChat: # parse display name from announce display_name = None if announce["aspect"] == "lxmf.delivery": - display_name = self.parse_lxmf_display_name(announce["app_data"]) + display_name = parse_lxmf_display_name(announce["app_data"]) elif announce["aspect"] == "nomadnetwork.node": - display_name = ReticulumMeshChat.parse_nomadnetwork_node_display_name( + display_name = parse_nomadnetwork_node_display_name( announce["app_data"], ) elif announce["aspect"] == "lxst.telephony": - display_name = announce.get("display_name") or "Anonymous Peer" + display_name = parse_lxmf_display_name(announce["app_data"]) # Try to find associated LXMF destination hash if this is a telephony announce lxmf_destination_hash = None @@ -7991,7 +10143,7 @@ class ReticulumMeshChat: lxmf_destination_hash = lxmf_a["destination_hash"] # Also update display name if telephony one was empty if not display_name or display_name == "Anonymous Peer": - display_name = self.parse_lxmf_display_name( + display_name = parse_lxmf_display_name( lxmf_a["app_data"], ) break @@ -8009,12 +10161,15 @@ class ReticulumMeshChat: identity = None if identity: - lxmf_destination_hash = RNS.Destination.hash( - identity, - "lxmf", - "delivery", - ).hex() - except Exception: + try: + lxmf_destination_hash = RNS.Destination.hash( + identity, + "lxmf", + "delivery", + ).hex() + except Exception: # noqa: S110 + pass + except Exception: # noqa: S110 pass # find lxmf user icon from database @@ -8025,8 +10180,16 @@ class ReticulumMeshChat: icon_hashes_to_check.append(lxmf_destination_hash) icon_hashes_to_check.append(announce["destination_hash"]) + # ensure we don't return the user's own icon for peers + local_hash = None + if self.current_context and self.current_context.local_lxmf_destination: + local_hash = self.current_context.local_lxmf_destination.hexhash + db_lxmf_user_icon = None for icon_hash in icon_hashes_to_check: + # skip if this is the user's own hash - don't return user's icon for peers + if local_hash and icon_hash == local_hash: + continue db_lxmf_user_icon = self.database.misc.get_user_icon(icon_hash) if db_lxmf_user_icon: break @@ -8071,133 +10234,35 @@ class ReticulumMeshChat: "updated_at": updated_at, } - # convert database favourite to a dictionary - @staticmethod - def convert_db_favourite_to_dict(favourite): - # ensure created_at and updated_at have Z suffix for UTC if they don't have a timezone - created_at = str(favourite["created_at"]) - if created_at and "+" not in created_at and "Z" not in created_at: - created_at += "Z" - - updated_at = str(favourite["updated_at"]) - if updated_at and "+" not in updated_at and "Z" not in updated_at: - updated_at += "Z" - - return { - "id": favourite["id"], - "destination_hash": favourite["destination_hash"], - "display_name": favourite["display_name"], - "aspect": favourite["aspect"], - "created_at": created_at, - "updated_at": updated_at, - } - # convert database lxmf message to a dictionary - @staticmethod - def convert_db_lxmf_message_to_dict( - db_lxmf_message, - include_attachments: bool = False, - ): - fields = json.loads(db_lxmf_message["fields"]) - - # strip attachments if requested - if not include_attachments: - if "image" in fields: - # keep type but strip bytes - image_size = 0 - if fields["image"].get("image_bytes"): - try: - image_size = len( - base64.b64decode(fields["image"]["image_bytes"]), - ) - except Exception as e: - print(f"Failed to decode image bytes: {e}") - fields["image"] = { - "image_type": fields["image"].get("image_type"), - "image_size": image_size, - "image_bytes": None, - } - if "audio" in fields: - # keep mode but strip bytes - audio_size = 0 - if fields["audio"].get("audio_bytes"): - try: - audio_size = len( - base64.b64decode(fields["audio"]["audio_bytes"]), - ) - except Exception as e: - print(f"Failed to decode audio bytes: {e}") - fields["audio"] = { - "audio_mode": fields["audio"].get("audio_mode"), - "audio_size": audio_size, - "audio_bytes": None, - } - if "file_attachments" in fields: - # keep file names but strip bytes - for i in range(len(fields["file_attachments"])): - file_size = 0 - if fields["file_attachments"][i].get("file_bytes"): - try: - file_size = len( - base64.b64decode( - fields["file_attachments"][i]["file_bytes"], - ), - ) - except Exception as e: - print(f"Failed to decode file attachment bytes: {e}") - fields["file_attachments"][i] = { - "file_name": fields["file_attachments"][i].get("file_name"), - "file_size": file_size, - "file_bytes": None, - } - - # ensure created_at and updated_at have Z suffix for UTC if they don't have a timezone - created_at = str(db_lxmf_message["created_at"]) - if created_at and "+" not in created_at and "Z" not in created_at: - created_at += "Z" - - updated_at = str(db_lxmf_message["updated_at"]) - if updated_at and "+" not in updated_at and "Z" not in updated_at: - updated_at += "Z" - - return { - "id": db_lxmf_message["id"], - "hash": db_lxmf_message["hash"], - "source_hash": db_lxmf_message["source_hash"], - "destination_hash": db_lxmf_message["destination_hash"], - "is_incoming": bool(db_lxmf_message["is_incoming"]), - "state": db_lxmf_message["state"], - "progress": db_lxmf_message["progress"], - "method": db_lxmf_message["method"], - "delivery_attempts": db_lxmf_message["delivery_attempts"], - "next_delivery_attempt_at": db_lxmf_message["next_delivery_attempt_at"], - "title": db_lxmf_message["title"], - "content": db_lxmf_message["content"], - "fields": fields, - "timestamp": db_lxmf_message["timestamp"], - "rssi": db_lxmf_message["rssi"], - "snr": db_lxmf_message["snr"], - "quality": db_lxmf_message["quality"], - "is_spam": bool(db_lxmf_message["is_spam"]), - "created_at": created_at, - "updated_at": updated_at, - } - # updates the lxmf user icon for the provided destination hash - @staticmethod def update_lxmf_user_icon( self, destination_hash: str, icon_name: str, foreground_colour: str, background_colour: str, + context=None, ): + ctx = context or self.current_context + if not ctx: + return + + # ensure we're not storing the user's own icon with a peer's hash + # only store icons for remote peers, not for the local user + if ( + ctx.local_lxmf_destination + and destination_hash == ctx.local_lxmf_destination.hexhash + ): + print(f"skipping icon update for local user's own hash: {destination_hash}") + return + # log print( f"updating lxmf user icon for {destination_hash} to icon_name={icon_name}, foreground_colour={foreground_colour}, background_colour={background_colour}", ) - self.database.misc.update_lxmf_user_icon( + ctx.database.misc.update_lxmf_user_icon( destination_hash, icon_name, foreground_colour, @@ -8205,56 +10270,118 @@ class ReticulumMeshChat: ) # check if a destination is blocked - def is_destination_blocked(self, destination_hash: str) -> bool: + def is_destination_blocked(self, destination_hash: str, context=None) -> bool: + ctx = context or self.current_context + if not ctx or not ctx.database: + return False try: - return self.database.misc.is_destination_blocked(destination_hash) + return ctx.database.misc.is_destination_blocked(destination_hash) except Exception: return False # check if message content matches spam keywords - def check_spam_keywords(self, title: str, content: str) -> bool: + def check_spam_keywords(self, title: str, content: str, context=None) -> bool: + ctx = context or self.current_context + if not ctx or not ctx.database: + return False try: - return self.database.misc.check_spam_keywords(title, content) + return ctx.database.misc.check_spam_keywords(title, content) except Exception: return False # check if message has attachments and should be rejected - @staticmethod - def has_attachments(lxmf_fields: dict) -> bool: - try: - if LXMF.FIELD_FILE_ATTACHMENTS in lxmf_fields: - return len(lxmf_fields[LXMF.FIELD_FILE_ATTACHMENTS]) > 0 - if LXMF.FIELD_IMAGE in lxmf_fields: - return True - if LXMF.FIELD_AUDIO in lxmf_fields: - return True - return False - except Exception: - return False # handle an lxmf delivery from reticulum # NOTE: cant be async, as Reticulum doesn't await it - def on_lxmf_delivery(self, lxmf_message: LXMF.LXMessage): + def on_lxmf_delivery(self, lxmf_message: LXMF.LXMessage, context=None): + ctx = context or self.current_context + if not ctx or not ctx.running or not ctx.database: + return + try: source_hash = lxmf_message.source_hash.hex() # check if source is blocked - reject immediately - if self.is_destination_blocked(source_hash): + if self.is_destination_blocked(source_hash, context=ctx): print(f"Rejecting LXMF message from blocked source: {source_hash}") return - # check if this lxmf message contains a telemetry request command from sideband is_sideband_telemetry_request = False lxmf_fields = lxmf_message.get_fields() + + # check both standard LXMF.FIELD_COMMANDS (9) and FIELD_COMMANDS (1) + commands = [] if LXMF.FIELD_COMMANDS in lxmf_fields: - for command in lxmf_fields[LXMF.FIELD_COMMANDS]: - if SidebandCommands.TELEMETRY_REQUEST in command: + val = lxmf_fields[LXMF.FIELD_COMMANDS] + if isinstance(val, list): + commands.extend(val) + elif isinstance(val, dict): + commands.append(val) + if 0x01 in lxmf_fields and LXMF.FIELD_COMMANDS != 0x01: + val = lxmf_fields[0x01] + if isinstance(val, list): + commands.extend(val) + elif isinstance(val, dict): + commands.append(val) + + if commands: + for command in commands: + if ( + ( + isinstance(command, dict) + and ( + SidebandCommands.TELEMETRY_REQUEST in command + or str(SidebandCommands.TELEMETRY_REQUEST) in command + or f"0x{SidebandCommands.TELEMETRY_REQUEST:02x}" + in command + ) + ) + or ( + isinstance(command, (list, tuple)) + and SidebandCommands.TELEMETRY_REQUEST in command + ) + or command == SidebandCommands.TELEMETRY_REQUEST + or str(command) == str(SidebandCommands.TELEMETRY_REQUEST) + ): is_sideband_telemetry_request = True - # respond to telemetry requests from sideband + # respond to telemetry requests if is_sideband_telemetry_request: - print(f"Responding to telemetry request from {source_hash}") - self.handle_telemetry_request(source_hash) + # Check if telemetry is enabled globally + if not ctx.config.telemetry_enabled.get(): + print(f"Telemetry is disabled, ignoring request from {source_hash}") + else: + # Check if peer is trusted + contact = ctx.database.contacts.get_contact_by_identity_hash( + source_hash, + ) + if not contact or not contact.get("is_telemetry_trusted"): + print( + f"Telemetry request from untrusted peer {source_hash}, ignoring", + ) + else: + print(f"Responding to telemetry request from {source_hash}") + self.handle_telemetry_request(source_hash) + + self.db_upsert_lxmf_message(lxmf_message, context=ctx) + + # broadcast notification + AsyncUtils.run_async( + self.websocket_broadcast( + json.dumps( + { + "type": "lxmf.delivery", + "remote_identity_name": source_hash[:8], + "lxmf_message": convert_db_lxmf_message_to_dict( + ctx.database.messages.get_lxmf_message_by_hash( + lxmf_message.hash.hex(), + ), + include_attachments=False, + ), + }, + ), + ), + ) return # check for spam keywords @@ -8272,7 +10399,7 @@ class ReticulumMeshChat: ) # reject attachments from blocked sources (already checked above, but double-check) - if self.has_attachments(lxmf_fields): + if has_attachments(lxmf_fields): if self.is_destination_blocked(source_hash): print( f"Rejecting LXMF message with attachments from blocked source: {source_hash}", @@ -8286,55 +10413,47 @@ class ReticulumMeshChat: return # upsert lxmf message to database with spam flag - self.db_upsert_lxmf_message(lxmf_message, is_spam=is_spam) + self.db_upsert_lxmf_message(lxmf_message, is_spam=is_spam, context=ctx) # handle forwarding - self.handle_forwarding(lxmf_message) + self.handle_forwarding(lxmf_message, context=ctx) # handle telemetry try: message_fields = lxmf_message.get_fields() + + # Single telemetry entry if LXMF.FIELD_TELEMETRY in message_fields: - telemetry_data = message_fields[LXMF.FIELD_TELEMETRY] - # unpack to get timestamp - unpacked = Telemeter.from_packed(telemetry_data) - if unpacked and "time" in unpacked: - timestamp = unpacked["time"]["utc"] + self.process_incoming_telemetry( + source_hash, + message_fields[LXMF.FIELD_TELEMETRY], + lxmf_message, + context=ctx, + ) - # physical link info - physical_link = { - "rssi": self.reticulum.get_packet_rssi(lxmf_message.hash) - if hasattr(self, "reticulum") and self.reticulum - else None, - "snr": self.reticulum.get_packet_snr(lxmf_message.hash) - if hasattr(self, "reticulum") and self.reticulum - else None, - "q": self.reticulum.get_packet_q(lxmf_message.hash) - if hasattr(self, "reticulum") and self.reticulum - else None, - } - - self.database.telemetry.upsert_telemetry( - destination_hash=source_hash, - timestamp=timestamp, - data=telemetry_data, - received_from=self.local_lxmf_destination.hexhash, - physical_link=physical_link, - ) - - # broadcast telemetry update via websocket - AsyncUtils.run_async( - self.websocket_broadcast( - json.dumps( - { - "type": "lxmf.telemetry", - "destination_hash": source_hash, - "timestamp": timestamp, - "telemetry": unpacked, - }, - ), - ), - ) + # Telemetry stream (multiple entries) + if ( + hasattr(LXMF, "FIELD_TELEMETRY_STREAM") + and LXMF.FIELD_TELEMETRY_STREAM in message_fields + ): + stream = message_fields[LXMF.FIELD_TELEMETRY_STREAM] + if isinstance(stream, (list, tuple)): + for entry in stream: + if isinstance(entry, (list, tuple)) and len(entry) >= 3: + entry_source = ( + entry[0].hex() + if isinstance(entry[0], bytes) + else entry[0] + ) + entry_timestamp = entry[1] + entry_data = entry[2] + self.process_incoming_telemetry( + entry_source, + entry_data, + lxmf_message, + timestamp_override=entry_timestamp, + context=ctx, + ) except Exception as e: print(f"Failed to handle telemetry in LXMF message: {e}") @@ -8346,30 +10465,80 @@ class ReticulumMeshChat: icon_name = icon_appearance[0] foreground_colour = "#" + icon_appearance[1].hex() background_colour = "#" + icon_appearance[2].hex() - self.update_lxmf_user_icon( - lxmf_message.source_hash.hex(), - icon_name, - foreground_colour, - background_colour, + + local_hash = ( + ctx.local_lxmf_destination.hexhash + if ctx.local_lxmf_destination + else None ) + source_hash = lxmf_message.source_hash.hex() + + # ignore our own icon and empty payloads to avoid overwriting peers with our appearance + if (source_hash and local_hash and source_hash == local_hash) or ( + not icon_name or not foreground_colour or not background_colour + ): + pass + else: + local_icon_name = ctx.config.lxmf_user_icon_name.get() + local_icon_fg = ( + ctx.config.lxmf_user_icon_foreground_colour.get() + ) + local_icon_bg = ( + ctx.config.lxmf_user_icon_background_colour.get() + ) + + # if incoming icon matches our own, skip storing and clear any mistaken stored copy + # for now, but this will need to be updated later if two users do have the same icon + # FIXME + if ( + local_icon_name + and local_icon_fg + and local_icon_bg + and icon_name == local_icon_name + and foreground_colour == local_icon_fg + and background_colour == local_icon_bg + ): + ctx.database.misc.delete_user_icon(source_hash) + else: + self.update_lxmf_user_icon( + source_hash, + icon_name, + foreground_colour, + background_colour, + context=ctx, + ) except Exception as e: print("failed to update lxmf user icon from lxmf message") print(e) # find message from database - db_lxmf_message = self.database.messages.get_lxmf_message_by_hash( + db_lxmf_message = ctx.database.messages.get_lxmf_message_by_hash( lxmf_message.hash.hex(), ) if not db_lxmf_message: return + # get sender name for notification + sender_name = ctx.database.announces.get_custom_display_name(source_hash) + if not sender_name: + announce = ctx.database.announces.get_announce_by_hash(source_hash) + if announce and announce["app_data"]: + sender_name = parse_lxmf_display_name( + app_data_base64=announce["app_data"], + default_value=None, + ) + + if not sender_name: + sender_name = source_hash[:8] + # send received lxmf message data to all websocket clients AsyncUtils.run_async( self.websocket_broadcast( json.dumps( { "type": "lxmf.delivery", - "lxmf_message": self.convert_db_lxmf_message_to_dict( + "remote_identity_name": sender_name, + "lxmf_message": convert_db_lxmf_message_to_dict( db_lxmf_message, include_attachments=False, ), @@ -8383,8 +10552,12 @@ class ReticulumMeshChat: print(f"lxmf_delivery error: {e}") # handles lxmf message forwarding logic - def handle_forwarding(self, lxmf_message: LXMF.LXMessage): + def handle_forwarding(self, lxmf_message: LXMF.LXMessage, context=None): try: + ctx = context or self.current_context + if not ctx: + return + source_hash = lxmf_message.source_hash.hex() destination_hash = lxmf_message.destination_hash.hex() @@ -8403,13 +10576,14 @@ class ReticulumMeshChat: audio_field = LxmfAudioField(val[0], val[1]) if LXMF.FIELD_FILE_ATTACHMENTS in lxmf_fields: - attachments = [] - for val in lxmf_fields[LXMF.FIELD_FILE_ATTACHMENTS]: - attachments.append(LxmfFileAttachment(val[0], val[1])) + attachments = [ + LxmfFileAttachment(val[0], val[1]) + for val in lxmf_fields[LXMF.FIELD_FILE_ATTACHMENTS] + ] file_attachments_field = LxmfFileAttachmentsField(attachments) # check if this message is for an alias identity (REPLY PATH) - mapping = self.database.messages.get_forwarding_mapping( + mapping = ctx.database.messages.get_forwarding_mapping( alias_hash=destination_hash, ) @@ -8428,13 +10602,14 @@ class ReticulumMeshChat: image_field=image_field, audio_field=audio_field, file_attachments_field=file_attachments_field, + context=ctx, ), ) return # check if this message matches a forwarding rule (FORWARD PATH) # we check for rules that apply to the destination of this message - rules = self.database.misc.get_forwarding_rules( + rules = ctx.database.misc.get_forwarding_rules( identity_hash=destination_hash, active_only=True, ) @@ -8448,7 +10623,7 @@ class ReticulumMeshChat: continue # find or create mapping for this (Source, Final Recipient) pair - mapping = self.forwarding_manager.get_or_create_mapping( + mapping = ctx.forwarding_manager.get_or_create_mapping( source_hash, rule["forward_to_hash"], destination_hash, @@ -8469,6 +10644,7 @@ class ReticulumMeshChat: image_field=image_field, audio_field=audio_field, file_attachments_field=file_attachments_field, + context=ctx, ), ) except Exception as e: @@ -8478,9 +10654,9 @@ class ReticulumMeshChat: traceback.print_exc() # handle delivery status update for an outbound lxmf message - def on_lxmf_sending_state_updated(self, lxmf_message): + def on_lxmf_sending_state_updated(self, lxmf_message, context=None): # upsert lxmf message to database - self.db_upsert_lxmf_message(lxmf_message) + self.db_upsert_lxmf_message(lxmf_message, context=context) # send lxmf message state to all websocket clients AsyncUtils.run_async( @@ -8488,9 +10664,10 @@ class ReticulumMeshChat: json.dumps( { "type": "lxmf_message_state_updated", - "lxmf_message": self.convert_lxmf_message_to_dict( + "lxmf_message": convert_lxmf_message_to_dict( lxmf_message, include_attachments=False, + reticulum=self.reticulum, ), }, ), @@ -8498,20 +10675,28 @@ class ReticulumMeshChat: ) # handle delivery failed for an outbound lxmf message - def on_lxmf_sending_failed(self, lxmf_message): + def on_lxmf_sending_failed(self, lxmf_message, context=None): # check if this failed message should fall back to sending via a propagation node if ( lxmf_message.state == LXMF.LXMessage.FAILED and hasattr(lxmf_message, "try_propagation_on_fail") and lxmf_message.try_propagation_on_fail ): - self.send_failed_message_via_propagation_node(lxmf_message) + self.send_failed_message_via_propagation_node(lxmf_message, context=context) # update state self.on_lxmf_sending_state_updated(lxmf_message) # sends a previously failed message via a propagation node - def send_failed_message_via_propagation_node(self, lxmf_message: LXMF.LXMessage): + def send_failed_message_via_propagation_node( + self, + lxmf_message: LXMF.LXMessage, + context=None, + ): + ctx = context or self.current_context + if not ctx: + return + # reset internal message state lxmf_message.packed = None lxmf_message.delivery_attempts = 0 @@ -8524,12 +10709,12 @@ class ReticulumMeshChat: # resend message source_hash = lxmf_message.source_hash.hex() - router = self.message_router + router = ctx.message_router if ( - self.forwarding_manager - and source_hash in self.forwarding_manager.forwarding_routers + ctx.forwarding_manager + and source_hash in ctx.forwarding_manager.forwarding_routers ): - router = self.forwarding_manager.forwarding_routers[source_hash] + router = ctx.forwarding_manager.forwarding_routers[source_hash] router.handle_outbound(lxmf_message) # upserts the provided lxmf message to the database @@ -8537,11 +10722,27 @@ class ReticulumMeshChat: self, lxmf_message: LXMF.LXMessage, is_spam: bool = False, + context=None, ): + ctx = context or self.current_context + if not ctx: + return + # convert lxmf message to dict - lxmf_message_dict = self.convert_lxmf_message_to_dict(lxmf_message) + lxmf_message_dict = convert_lxmf_message_to_dict( + lxmf_message, + reticulum=self.reticulum, + ) lxmf_message_dict["is_spam"] = 1 if is_spam else 0 - self.database.messages.upsert_lxmf_message(lxmf_message_dict) + + # calculate peer hash + local_hash = ctx.local_lxmf_destination.hexhash + if lxmf_message_dict["source_hash"] == local_hash: + lxmf_message_dict["peer_hash"] = lxmf_message_dict["destination_hash"] + else: + lxmf_message_dict["peer_hash"] = lxmf_message_dict["source_hash"] + + ctx.database.messages.upsert_lxmf_message(lxmf_message_dict) # upserts the provided announce to the database # handle sending an lxmf message to reticulum @@ -8558,7 +10759,12 @@ class ReticulumMeshChat: title: str = "", sender_identity_hash: str = None, no_display: bool = False, + context=None, ) -> LXMF.LXMessage: + ctx = context or self.current_context + if not ctx: + raise RuntimeError("No identity context available for sending message") + # convert destination hash to bytes destination_hash_bytes = bytes.fromhex(destination_hash) @@ -8607,7 +10813,7 @@ class ReticulumMeshChat: # send messages over a direct link by default desired_delivery_method = LXMF.LXMessage.DIRECT if ( - not self.message_router.delivery_link_available(destination_hash_bytes) + not ctx.message_router.delivery_link_available(destination_hash_bytes) and RNS.Identity.current_ratchet_id(destination_hash_bytes) is not None ): # since there's no link established to the destination, it's faster to send opportunistically @@ -8617,14 +10823,14 @@ class ReticulumMeshChat: desired_delivery_method = LXMF.LXMessage.OPPORTUNISTIC # determine which identity to send from - source_destination = self.local_lxmf_destination + source_destination = ctx.local_lxmf_destination if sender_identity_hash is not None: if ( - self.forwarding_manager + ctx.forwarding_manager and sender_identity_hash - in self.forwarding_manager.forwarding_destinations + in ctx.forwarding_manager.forwarding_destinations ): - source_destination = self.forwarding_manager.forwarding_destinations[ + source_destination = ctx.forwarding_manager.forwarding_destinations[ sender_identity_hash ] else: @@ -8641,7 +10847,7 @@ class ReticulumMeshChat: desired_method=desired_delivery_method, ) lxmf_message.try_propagation_on_fail = ( - self.config.auto_send_failed_messages_to_propagation_node.get() + ctx.config.auto_send_failed_messages_to_propagation_node.get() ) lxmf_message.fields = {} @@ -8679,46 +10885,61 @@ class ReticulumMeshChat: if commands is not None: lxmf_message.fields[LXMF.FIELD_COMMANDS] = commands - # add icon appearance if configured - # fixme: we could save a tiny amount of bandwidth here, but this requires more effort... - # we could keep track of when the icon appearance was last sent to this destination, and when it last changed - # we could save 6 bytes for the 2x colours, and also however long the icon name is, but not today! - lxmf_user_icon_name = self.config.lxmf_user_icon_name.get() - lxmf_user_icon_foreground_colour = ( - self.config.lxmf_user_icon_foreground_colour.get() - ) - lxmf_user_icon_background_colour = ( - self.config.lxmf_user_icon_background_colour.get() - ) - if ( - lxmf_user_icon_name is not None - and lxmf_user_icon_foreground_colour is not None - and lxmf_user_icon_background_colour is not None - ): - lxmf_message.fields[LXMF.FIELD_ICON_APPEARANCE] = [ - lxmf_user_icon_name, - ColourUtils.hex_colour_to_byte_array(lxmf_user_icon_foreground_colour), - ColourUtils.hex_colour_to_byte_array(lxmf_user_icon_background_colour), - ] + # add icon appearance if configured and not already sent to this destination + current_icon_hash = self.get_current_icon_hash() + if current_icon_hash is not None: + last_sent_icon_hash = self.database.misc.get_last_sent_icon_hash( + destination_hash, + ) + + if last_sent_icon_hash != current_icon_hash: + lxmf_user_icon_name = self.config.lxmf_user_icon_name.get() + lxmf_user_icon_foreground_colour = ( + self.config.lxmf_user_icon_foreground_colour.get() + ) + lxmf_user_icon_background_colour = ( + self.config.lxmf_user_icon_background_colour.get() + ) + + lxmf_message.fields[LXMF.FIELD_ICON_APPEARANCE] = [ + lxmf_user_icon_name, + ColourUtils.hex_colour_to_byte_array( + lxmf_user_icon_foreground_colour, + ), + ColourUtils.hex_colour_to_byte_array( + lxmf_user_icon_background_colour, + ), + ] + + # update last sent icon hash for this destination + ctx.database.misc.update_last_sent_icon_hash( + destination_hash, + current_icon_hash, + ) # register delivery callbacks - lxmf_message.register_delivery_callback(self.on_lxmf_sending_state_updated) - lxmf_message.register_failed_callback(self.on_lxmf_sending_failed) + lxmf_message.register_delivery_callback( + lambda msg: self.on_lxmf_sending_state_updated(msg, context=ctx), + ) + lxmf_message.register_failed_callback( + lambda msg: self.on_lxmf_sending_failed(msg, context=ctx), + ) # determine which router to use - router = self.message_router + router = ctx.message_router if ( sender_identity_hash is not None - and sender_identity_hash in self.forwarding_manager.forwarding_routers + and ctx.forwarding_manager + and sender_identity_hash in ctx.forwarding_manager.forwarding_routers ): - router = self.forwarding_manager.forwarding_routers[sender_identity_hash] + router = ctx.forwarding_manager.forwarding_routers[sender_identity_hash] # send lxmf message to be routed to destination router.handle_outbound(lxmf_message) # upsert lxmf message to database if not no_display: - self.db_upsert_lxmf_message(lxmf_message) + self.db_upsert_lxmf_message(lxmf_message, context=ctx) # tell all websocket clients that old failed message was deleted so it can remove from ui if not no_display: @@ -8726,9 +10947,10 @@ class ReticulumMeshChat: json.dumps( { "type": "lxmf_message_created", - "lxmf_message": self.convert_lxmf_message_to_dict( + "lxmf_message": convert_lxmf_message_to_dict( lxmf_message, include_attachments=False, + reticulum=self.reticulum, ), }, ), @@ -8738,10 +10960,88 @@ class ReticulumMeshChat: # otherwise other incoming websocket packets will not be processed until sending is complete # which results in the next message not showing up until the first message is finished if not no_display: - AsyncUtils.run_async(self.handle_lxmf_message_progress(lxmf_message)) + AsyncUtils.run_async( + self.handle_lxmf_message_progress(lxmf_message, context=ctx), + ) return lxmf_message + # get hash of current icon appearance configuration + def get_current_icon_hash(self, context=None): + ctx = context or self.current_context + if not ctx: + return None + + name = ctx.config.lxmf_user_icon_name.get() + fg = ctx.config.lxmf_user_icon_foreground_colour.get() + bg = ctx.config.lxmf_user_icon_background_colour.get() + + if not all([name, fg, bg]): + return None + + data = f"{name}|{fg}|{bg}" + return hashlib.sha256(data.encode()).hexdigest() + + def process_incoming_telemetry( + self, + source_hash, + telemetry_data, + lxmf_message, + timestamp_override=None, + context=None, + ): + ctx = context or self.current_context + if not ctx: + return + + try: + unpacked = Telemeter.from_packed(telemetry_data) + if unpacked: + timestamp = timestamp_override or ( + unpacked["time"]["utc"] if "time" in unpacked else int(time.time()) + ) + + # physical link info + physical_link = { + "rssi": self.reticulum.get_packet_rssi(lxmf_message.hash) + if hasattr(self, "reticulum") and self.reticulum + else None, + "snr": self.reticulum.get_packet_snr(lxmf_message.hash) + if hasattr(self, "reticulum") and self.reticulum + else None, + "q": self.reticulum.get_packet_q(lxmf_message.hash) + if hasattr(self, "reticulum") and self.reticulum + else None, + } + + ctx.database.telemetry.upsert_telemetry( + destination_hash=source_hash, + timestamp=timestamp, + data=telemetry_data, + received_from=ctx.local_lxmf_destination.hexhash, + physical_link=physical_link, + ) + + # broadcast telemetry update via websocket + AsyncUtils.run_async( + self.websocket_broadcast( + json.dumps( + { + "type": "lxmf.telemetry", + "destination_hash": source_hash, + "timestamp": timestamp, + "telemetry": unpacked, + "physical_link": physical_link, + "is_tracking": ctx.database.telemetry.is_tracking( + source_hash, + ), + }, + ), + ), + ) + except Exception as e: + print(f"Error processing incoming telemetry: {e}") + def handle_telemetry_request(self, to_addr_hash: str): # get our location from config lat = self.database.config.get("map_default_lat") @@ -8766,40 +11066,43 @@ class ReticulumMeshChat: telemetry_data = Telemeter.pack(location=location) - # send as an LXMF message with no content, only telemetry field - # use no_display=True to avoid showing in chat UI AsyncUtils.run_async( self.send_message( destination_hash=to_addr_hash, content="", telemetry_data=telemetry_data, delivery_method="opportunistic", - no_display=True, + no_display=False, ), ) except Exception as e: print(f"Failed to respond to telemetry request: {e}") # updates lxmf message in database and broadcasts to websocket until it's delivered, or it fails - async def handle_lxmf_message_progress(self, lxmf_message): + async def handle_lxmf_message_progress(self, lxmf_message, context=None): # FIXME: there's no register_progress_callback on the lxmf message, so manually send progress until delivered, propagated or failed # we also can't use on_lxmf_sending_state_updated method to do this, because of async/await issues... + ctx = context or self.current_context + if not ctx: + return + should_update_message = True while should_update_message: # wait 1 second between sending updates await asyncio.sleep(1) # upsert lxmf message to database (as we want to update the progress in database too) - self.db_upsert_lxmf_message(lxmf_message) + self.db_upsert_lxmf_message(lxmf_message, context=ctx) # send update to websocket clients await self.websocket_broadcast( json.dumps( { "type": "lxmf_message_state_updated", - "lxmf_message": self.convert_lxmf_message_to_dict( + "lxmf_message": convert_lxmf_message_to_dict( lxmf_message, include_attachments=False, + reticulum=self.reticulum, ), }, ), @@ -8827,10 +11130,14 @@ class ReticulumMeshChat: announced_identity, app_data, announce_packet_hash, + context=None, ): + ctx = context or self.current_context + if not ctx or not ctx.running or not ctx.announce_manager or not ctx.database: + return # check if source is blocked - drop announce and path if blocked identity_hash = announced_identity.hash.hex() - if self.is_destination_blocked(identity_hash): + if self.is_destination_blocked(identity_hash, context=ctx): print(f"Dropping telephone announce from blocked source: {identity_hash}") if hasattr(self, "reticulum") and self.reticulum: self.reticulum.drop_path(destination_hash) @@ -8840,14 +11147,24 @@ class ReticulumMeshChat: print( "Received an announce from " + RNS.prettyhexrep(destination_hash) - + " for [lxst.telephony]", + + " for [lxst.telephony]" + + ( + f" ({display_name})" + if ( + display_name := parse_lxmf_display_name( + app_data, + None, + ) + ) + else "" + ), ) # track announce timestamp self.announce_timestamps.append(time.time()) # upsert announce to database - self.announce_manager.upsert_announce( + ctx.announce_manager.upsert_announce( self.reticulum, announced_identity, destination_hash, @@ -8857,7 +11174,7 @@ class ReticulumMeshChat: ) # find announce from database - announce = self.database.announces.get_announce_by_hash(destination_hash.hex()) + announce = ctx.database.announces.get_announce_by_hash(destination_hash.hex()) if not announce: return @@ -8882,7 +11199,12 @@ class ReticulumMeshChat: announced_identity, app_data, announce_packet_hash, + context=None, ): + ctx = context or self.current_context + if not ctx or not ctx.running or not ctx.announce_manager or not ctx.database: + return + # check if announced identity or its hash is missing if not announced_identity or not announced_identity.hash: print( @@ -8892,7 +11214,7 @@ class ReticulumMeshChat: # check if source is blocked - drop announce and path if blocked identity_hash = announced_identity.hash.hex() - if self.is_destination_blocked(identity_hash): + if self.is_destination_blocked(identity_hash, context=ctx): print(f"Dropping announce from blocked source: {identity_hash}") if hasattr(self, "reticulum") and self.reticulum: self.reticulum.drop_path(destination_hash) @@ -8909,7 +11231,7 @@ class ReticulumMeshChat: self.announce_timestamps.append(time.time()) # upsert announce to database - self.announce_manager.upsert_announce( + ctx.announce_manager.upsert_announce( self.reticulum, announced_identity, destination_hash, @@ -8919,7 +11241,7 @@ class ReticulumMeshChat: ) # find announce from database - announce = self.database.announces.get_announce_by_hash(destination_hash.hex()) + announce = ctx.database.announces.get_announce_by_hash(destination_hash.hex()) if not announce: return @@ -8936,9 +11258,12 @@ class ReticulumMeshChat: ) # resend all failed messages that were intended for this destination - if self.config.auto_resend_failed_messages_when_announce_received.get(): + if ctx.config.auto_resend_failed_messages_when_announce_received.get(): AsyncUtils.run_async( - self.resend_failed_messages_for_destination(destination_hash.hex()), + self.resend_failed_messages_for_destination( + destination_hash.hex(), + context=ctx, + ), ) # handle an announce received from reticulum, for an lxmf propagation node address @@ -8950,7 +11275,12 @@ class ReticulumMeshChat: announced_identity, app_data, announce_packet_hash, + context=None, ): + ctx = context or self.current_context + if not ctx or not ctx.running or not ctx.announce_manager or not ctx.database: + return + # log received announce print( "Received an announce from " @@ -8962,7 +11292,7 @@ class ReticulumMeshChat: self.announce_timestamps.append(time.time()) # upsert announce to database - self.announce_manager.upsert_announce( + ctx.announce_manager.upsert_announce( self.reticulum, announced_identity, destination_hash, @@ -8972,7 +11302,7 @@ class ReticulumMeshChat: ) # find announce from database - announce = self.database.announces.get_announce_by_hash(destination_hash.hex()) + announce = ctx.database.announces.get_announce_by_hash(destination_hash.hex()) if not announce: return @@ -8989,9 +11319,17 @@ class ReticulumMeshChat: ) # resends all messages that previously failed to send to the provided destination hash - async def resend_failed_messages_for_destination(self, destination_hash: str): + async def resend_failed_messages_for_destination( + self, + destination_hash: str, + context=None, + ): + ctx = context or self.current_context + if not ctx: + return + # get messages that failed to send to this destination - failed_messages = self.database.messages.get_failed_messages_for_destination( + failed_messages = ctx.database.messages.get_failed_messages_for_destination( destination_hash, ) @@ -9030,7 +11368,7 @@ class ReticulumMeshChat: file_attachments_field = LxmfFileAttachmentsField(file_attachments) # don't resend message with attachments if not allowed - if not self.config.allow_auto_resending_failed_messages_with_attachments.get(): + if not ctx.config.allow_auto_resending_failed_messages_with_attachments.get(): if ( image_field is not None or audio_field is not None @@ -9048,10 +11386,11 @@ class ReticulumMeshChat: image_field=image_field, audio_field=audio_field, file_attachments_field=file_attachments_field, + context=ctx, ) # remove original failed message from database - self.database.messages.delete_lxmf_message_by_hash( + ctx.database.messages.delete_lxmf_message_by_hash( failed_message["hash"], ) @@ -9077,10 +11416,15 @@ class ReticulumMeshChat: announced_identity, app_data, announce_packet_hash, + context=None, ): + ctx = context or self.current_context + if not ctx or not ctx.running or not ctx.announce_manager or not ctx.database: + return + # check if source is blocked - drop announce and path if blocked identity_hash = announced_identity.hash.hex() - if self.is_destination_blocked(identity_hash): + if self.is_destination_blocked(identity_hash, context=ctx): print(f"Dropping announce from blocked source: {identity_hash}") if hasattr(self, "reticulum") and self.reticulum: self.reticulum.drop_path(destination_hash) @@ -9097,7 +11441,7 @@ class ReticulumMeshChat: self.announce_timestamps.append(time.time()) # upsert announce to database - self.announce_manager.upsert_announce( + ctx.announce_manager.upsert_announce( self.reticulum, announced_identity, destination_hash, @@ -9106,6 +11450,23 @@ class ReticulumMeshChat: announce_packet_hash, ) + # find announce from database + announce = ctx.database.announces.get_announce_by_hash(destination_hash.hex()) + if not announce: + return + + # send database announce to all websocket clients + AsyncUtils.run_async( + self.websocket_broadcast( + json.dumps( + { + "type": "announce", + "announce": self.convert_db_announce_to_dict(announce), + }, + ), + ), + ) + # find announce from database announce = self.database.announces.get_announce_by_hash(destination_hash.hex()) if announce is None: @@ -9127,8 +11488,11 @@ class ReticulumMeshChat: self.queue_crawler_task(destination_hash.hex(), "/page/index.mu") # queues a crawler task for the provided destination and path - def queue_crawler_task(self, destination_hash: str, page_path: str): - self.database.misc.upsert_crawl_task(destination_hash, page_path) + def queue_crawler_task(self, destination_hash: str, page_path: str, context=None): + ctx = context or self.current_context + if not ctx: + return + ctx.database.misc.upsert_crawl_task(destination_hash, page_path) # gets the custom display name a user has set for the provided destination hash def get_custom_destination_display_name(self, destination_hash: str): @@ -9148,17 +11512,13 @@ class ReticulumMeshChat: destination_hash, default_name: str | None = "Anonymous Peer", ): - # get lxmf.delivery announce from database for the provided destination hash - results = self.database.announces.get_announces(aspect="lxmf.delivery") - lxmf_announce = next( - (a for a in results if a["destination_hash"] == destination_hash), - None, - ) + # Optimized to fetch only the needed announce + lxmf_announce = self.database.announces.get_announce_by_hash(destination_hash) # if app data is available in database, it should be base64 encoded text that was announced # we will return the parsed lxmf display name as the conversation name if lxmf_announce is not None and lxmf_announce["app_data"] is not None: - return ReticulumMeshChat.parse_lxmf_display_name( + return parse_lxmf_display_name( app_data_base64=lxmf_announce["app_data"], ) @@ -9166,75 +11526,6 @@ class ReticulumMeshChat: return default_name # reads the lxmf display name from the provided base64 app data - @staticmethod - def parse_lxmf_display_name( - app_data_base64: str | None, - default_value: str | None = "Anonymous Peer", - ): - if app_data_base64 is None: - return default_value - - try: - app_data_bytes = base64.b64decode(app_data_base64) - display_name = LXMF.display_name_from_app_data(app_data_bytes) - if display_name is not None: - return display_name - except Exception as e: - print(f"Failed to parse LXMF display name: {e}") - - return default_value - - # reads the lxmf stamp cost from the provided base64 app data - @staticmethod - def parse_lxmf_stamp_cost(app_data_base64: str | None): - if app_data_base64 is None: - return None - - try: - app_data_bytes = base64.b64decode(app_data_base64) - return LXMF.stamp_cost_from_app_data(app_data_bytes) - except Exception as e: - print(f"Failed to parse LXMF stamp cost: {e}") - return None - - # reads the nomadnetwork node display name from the provided base64 app data - @staticmethod - def parse_nomadnetwork_node_display_name( - app_data_base64: str | None, - default_value: str | None = "Anonymous Node", - ): - if app_data_base64 is None: - return default_value - - try: - app_data_bytes = base64.b64decode(app_data_base64) - return app_data_bytes.decode("utf-8") - except Exception as e: - print(f"Failed to parse NomadNetwork display name: {e}") - return default_value - - # parses lxmf propagation node app data - @staticmethod - def parse_lxmf_propagation_node_app_data(app_data_base64: str | None): - if app_data_base64 is None: - return None - - try: - app_data_bytes = base64.b64decode(app_data_base64) - data = msgpack.unpackb(app_data_bytes) - - # ensure data is a list and has enough elements - if not isinstance(data, list) or len(data) < 4: - return None - - return { - "enabled": bool(data[2]) if data[2] is not None else False, - "timebase": int(data[1]) if data[1] is not None else 0, - "per_transfer_limit": int(data[3]) if data[3] is not None else 0, - } - except Exception as e: - print(f"Failed to parse LXMF propagation node app data: {e}") - return None # returns true if the conversation has messages newer than the last read at timestamp @staticmethod @@ -9256,276 +11547,22 @@ class ReticulumMeshChat: return None +def env_bool(env_name, default=False): + val = os.environ.get(env_name) + if val is None: + return default + return val.lower() in ("true", "1", "yes", "on") + + # class to manage config stored in database # FIXME: we should probably set this as an instance variable of ReticulumMeshChat so it has a proper home, and pass it in to the constructor? -nomadnet_cached_links = {} - - -class NomadnetDownloader: - def __init__( - self, - destination_hash: bytes, - path: str, - data: str | None, - on_download_success: Callable[[RNS.RequestReceipt], None], - on_download_failure: Callable[[str], None], - on_progress_update: Callable[[float], None], - timeout: int | None = None, - ): - self.app_name = "nomadnetwork" - self.aspects = "node" - self.destination_hash = destination_hash - self.path = path - self.data = data - self.timeout = timeout - self._download_success_callback = on_download_success - self._download_failure_callback = on_download_failure - self.on_progress_update = on_progress_update - self.request_receipt = None - self.is_cancelled = False - self.link = None - - # cancel the download - def cancel(self): - self.is_cancelled = True - - # cancel the request if it exists - if self.request_receipt is not None: - try: - self.request_receipt.cancel() - except Exception as e: - print(f"Failed to cancel request: {e}") - - # clean up the link if we created it - if self.link is not None: - try: - self.link.teardown() - except Exception as e: - print(f"Failed to teardown link: {e}") - - # notify that download was cancelled - self._download_failure_callback("cancelled") - - # setup link to destination and request download - async def download( - self, - path_lookup_timeout: int = 15, - link_establishment_timeout: int = 15, - ): - # check if cancelled before starting - if self.is_cancelled: - return - - # use existing established link if it's active - if self.destination_hash in nomadnet_cached_links: - link = nomadnet_cached_links[self.destination_hash] - if link.status is RNS.Link.ACTIVE: - print("[NomadnetDownloader] using existing link for request") - self.link_established(link) - return - - # determine when to timeout - timeout_after_seconds = time.time() + path_lookup_timeout - - # check if we have a path to the destination - if not RNS.Transport.has_path(self.destination_hash): - # we don't have a path, so we need to request it - RNS.Transport.request_path(self.destination_hash) - - # wait until we have a path, or give up after the configured timeout - while ( - not RNS.Transport.has_path(self.destination_hash) - and time.time() < timeout_after_seconds - ): - # check if cancelled during path lookup - if self.is_cancelled: - return - await asyncio.sleep(0.1) - - # if we still don't have a path, we can't establish a link, so bail out - if not RNS.Transport.has_path(self.destination_hash): - self._download_failure_callback("Could not find path to destination.") - return - - # check if cancelled before establishing link - if self.is_cancelled: - return - - # create destination to nomadnet node - identity = RNS.Identity.recall(self.destination_hash) - destination = RNS.Destination( - identity, - RNS.Destination.OUT, - RNS.Destination.SINGLE, - self.app_name, - self.aspects, - ) - - # create link to destination - print("[NomadnetDownloader] establishing new link for request") - link = RNS.Link(destination, established_callback=self.link_established) - self.link = link - - # determine when to timeout - timeout_after_seconds = time.time() + link_establishment_timeout - - # wait until we have established a link, or give up after the configured timeout - while ( - link.status is not RNS.Link.ACTIVE and time.time() < timeout_after_seconds - ): - # check if cancelled during link establishment - if self.is_cancelled: - return - await asyncio.sleep(0.1) - - # if we still haven't established a link, bail out - if link.status is not RNS.Link.ACTIVE: - self._download_failure_callback("Could not establish link to destination.") - - # link to destination was established, we should now request the download - def link_established(self, link): - # check if cancelled before requesting - if self.is_cancelled: - return - - # cache link for using in future requests - nomadnet_cached_links[self.destination_hash] = link - - # request download over link - self.request_receipt = link.request( - self.path, - data=self.data, - response_callback=self.on_response, - failed_callback=self.on_failed, - progress_callback=self.on_progress, - timeout=self.timeout, - ) - - # handle successful download - def on_response(self, request_receipt: RNS.RequestReceipt): - self._download_success_callback(request_receipt) - - # handle failure - def on_failed(self, request_receipt=None): - self._download_failure_callback("request_failed") - - # handle download progress - def on_progress(self, request_receipt): - self.on_progress_update(request_receipt.progress) - - -class NomadnetPageDownloader(NomadnetDownloader): - def __init__( - self, - destination_hash: bytes, - page_path: str, - data: str | None, - on_page_download_success: Callable[[str], None], - on_page_download_failure: Callable[[str], None], - on_progress_update: Callable[[float], None], - timeout: int | None = None, - ): - self.on_page_download_success = on_page_download_success - self.on_page_download_failure = on_page_download_failure - super().__init__( - destination_hash, - page_path, - data, - self.on_download_success, - self.on_download_failure, - on_progress_update, - timeout, - ) - - # page download was successful, decode the response and send to provided callback - def on_download_success(self, request_receipt: RNS.RequestReceipt): - micron_markup_response = request_receipt.response.decode("utf-8") - self.on_page_download_success(micron_markup_response) - - # page download failed, send error to provided callback - def on_download_failure(self, failure_reason): - self.on_page_download_failure(failure_reason) - - -class NomadnetFileDownloader(NomadnetDownloader): - def __init__( - self, - destination_hash: bytes, - page_path: str, - on_file_download_success: Callable[[str, bytes], None], - on_file_download_failure: Callable[[str], None], - on_progress_update: Callable[[float], None], - timeout: int | None = None, - ): - self.on_file_download_success = on_file_download_success - self.on_file_download_failure = on_file_download_failure - super().__init__( - destination_hash, - page_path, - None, - self.on_download_success, - self.on_download_failure, - on_progress_update, - timeout, - ) - - # file download was successful, decode the response and send to provided callback - def on_download_success(self, request_receipt: RNS.RequestReceipt): - # get response - response = request_receipt.response - - # handle buffered reader response - if isinstance(response, io.BufferedReader): - # get file name from metadata - file_name = "downloaded_file" - metadata = request_receipt.metadata - if metadata is not None and "name" in metadata: - file_path = metadata["name"].decode("utf-8") - file_name = os.path.basename(file_path) - - # get file data - file_data: bytes = response.read() - - self.on_file_download_success(file_name, file_data) - return - - # check for list response with bytes in position 0, and metadata dict in position 1 - # e.g: [file_bytes, {name: "filename.ext"}] - if isinstance(response, list) and isinstance(response[1], dict): - file_data: bytes = response[0] - metadata: dict = response[1] - - # get file name from metadata - file_name = "downloaded_file" - if metadata is not None and "name" in metadata: - file_path = metadata["name"].decode("utf-8") - file_name = os.path.basename(file_path) - - self.on_file_download_success(file_name, file_data) - return - - # try using original response format - # unsure if this is actually used anymore now that a buffered reader is provided - # have left here just in case... - try: - file_name: str = response[0] - file_data: bytes = response[1] - self.on_file_download_success(file_name, file_data) - except Exception: - self.on_download_failure("unsupported_response") - - # page download failed, send error to provided callback - def on_download_failure(self, failure_reason): - self.on_file_download_failure(failure_reason) - - def main(): - # parse command line args - def env_bool(env_name, default=False): - val = os.environ.get(env_name) - if val is None: - return default - return val.lower() in ("true", "1", "yes", "on") + # apply asyncio 3.13 patch if needed + AsyncUtils.apply_asyncio_313_patch() + + # Initialize crash recovery system early to catch startup errors + recovery = CrashRecovery() + recovery.install() parser = argparse.ArgumentParser(description="ReticulumMeshChat") parser.add_argument( @@ -9594,6 +11631,12 @@ def main(): default=env_bool("MESHCHAT_NO_HTTPS", False), help="Disable HTTPS and use HTTP instead. Can also be set via MESHCHAT_NO_HTTPS environment variable.", ) + parser.add_argument( + "--no-crash-recovery", + action="store_true", + default=env_bool("MESHCHAT_NO_CRASH_RECOVERY", False), + help="Disable the crash recovery and diagnostic system. Can also be set via MESHCHAT_NO_CRASH_RECOVERY environment variable.", + ) parser.add_argument( "--backup-db", type=str, @@ -9616,6 +11659,24 @@ def main(): default=os.environ.get("MESHCHAT_STORAGE_DIR"), help="Path to a directory for storing databases and config files (default: ./storage). Can also be set via MESHCHAT_STORAGE_DIR environment variable.", ) + parser.add_argument( + "--public-dir", + type=str, + default=os.environ.get("MESHCHAT_PUBLIC_DIR"), + help="Path to the directory containing the frontend static files (default: bundled public folder). Can also be set via MESHCHAT_PUBLIC_DIR environment variable.", + ) + parser.add_argument( + "--gitea-base-url", + type=str, + default=os.environ.get("MESHCHAT_GITEA_BASE_URL"), + help="Base URL for Gitea instance (default: https://git.quad4.io). Can also be set via MESHCHAT_GITEA_BASE_URL environment variable.", + ) + parser.add_argument( + "--docs-download-urls", + type=str, + default=os.environ.get("MESHCHAT_DOCS_DOWNLOAD_URLS"), + help="Comma-separated list of URLs to download documentation from. Can also be set via MESHCHAT_DOCS_DOWNLOAD_URLS environment variable.", + ) parser.add_argument( "--test-exception-message", type=str, @@ -9625,8 +11686,26 @@ def main(): "args", nargs=argparse.REMAINDER, ) # allow unknown command line args + parser.add_argument( + "--emergency", + action="store_true", + help="Start in emergency mode (no database, LXMF and peer announces only). Can also be set via MESHCHAT_EMERGENCY environment variable.", + default=env_bool("MESHCHAT_EMERGENCY", False), + ) + + parser.add_argument( + "--restore-from-snapshot", + type=str, + help="Restore the database from a specific snapshot name or path on startup.", + default=os.environ.get("MESHCHAT_RESTORE_SNAPSHOT"), + ) + args = parser.parse_args() + # Disable crash recovery if requested via flag + if args.no_crash_recovery: + recovery.disable() + # check if we want to test exception messages if args.test_exception_message is not None: raise Exception(args.test_exception_message) @@ -9721,6 +11800,18 @@ def main(): auto_recover=args.auto_recover, identity_file_path=identity_file_path, auth_enabled=args.auth, + public_dir=args.public_dir, + emergency=args.emergency, + gitea_base_url=args.gitea_base_url, + docs_download_urls=args.docs_download_urls, + ) + + # update recovery with known paths + recovery.update_paths( + storage_dir=reticulum_meshchat.storage_dir, + database_path=reticulum_meshchat.database_path, + public_dir=reticulum_meshchat.public_dir_override or get_file_path("public"), + reticulum_config_dir=reticulum_meshchat.reticulum_config_dir, ) if args.backup_db: @@ -9734,6 +11825,29 @@ def main(): print(f"Integrity check: {result['integrity_check']}") return + if args.restore_from_snapshot: + snapshot_path = args.restore_from_snapshot + if not os.path.exists(snapshot_path): + # Try in storage_dir/snapshots + potential_path = os.path.join( + reticulum_meshchat.storage_dir, + "snapshots", + snapshot_path, + ) + if os.path.exists(potential_path): + snapshot_path = potential_path + elif os.path.exists(potential_path + ".zip"): + snapshot_path = potential_path + ".zip" + + if os.path.exists(snapshot_path): + print(f"Restoring database from snapshot: {snapshot_path}") + result = reticulum_meshchat.restore_database(snapshot_path) + print( + f"Snapshot restoration complete. Integrity check: {result['integrity_check']}", + ) + else: + print(f"Error: Snapshot not found at {snapshot_path}") + enable_https = not args.no_https reticulum_meshchat.run( args.host, diff --git a/meshchatx/src/backend/announce_manager.py b/meshchatx/src/backend/announce_manager.py index e51d5ff..173ccad 100644 --- a/meshchatx/src/backend/announce_manager.py +++ b/meshchatx/src/backend/announce_manager.py @@ -49,27 +49,43 @@ class AnnounceManager: destination_hash=None, query=None, blocked_identity_hashes=None, + limit=None, + offset=0, ): - sql = "SELECT * FROM announces WHERE 1=1" + sql = """ + SELECT a.*, c.custom_image as contact_image + FROM announces a + LEFT JOIN contacts c ON ( + a.identity_hash = c.remote_identity_hash OR + a.destination_hash = c.lxmf_address OR + a.destination_hash = c.lxst_address + ) + WHERE 1=1 + """ params = [] if aspect: - sql += " AND aspect = ?" + sql += " AND a.aspect = ?" params.append(aspect) if identity_hash: - sql += " AND identity_hash = ?" + sql += " AND a.identity_hash = ?" params.append(identity_hash) if destination_hash: - sql += " AND destination_hash = ?" + sql += " AND a.destination_hash = ?" params.append(destination_hash) if query: like_term = f"%{query}%" - sql += " AND (destination_hash LIKE ? OR identity_hash LIKE ?)" + sql += " AND (a.destination_hash LIKE ? OR a.identity_hash LIKE ?)" params.extend([like_term, like_term]) if blocked_identity_hashes: placeholders = ", ".join(["?"] * len(blocked_identity_hashes)) - sql += f" AND identity_hash NOT IN ({placeholders})" + sql += f" AND a.identity_hash NOT IN ({placeholders})" params.extend(blocked_identity_hashes) - sql += " ORDER BY updated_at DESC" + sql += " ORDER BY a.updated_at DESC" + + if limit is not None: + sql += " LIMIT ? OFFSET ?" + params.extend([limit, offset]) + return self.db.provider.fetchall(sql, params) diff --git a/meshchatx/src/backend/async_utils.py b/meshchatx/src/backend/async_utils.py index 200dfc8..fc053dc 100644 --- a/meshchatx/src/backend/async_utils.py +++ b/meshchatx/src/backend/async_utils.py @@ -1,4 +1,5 @@ import asyncio +import sys from collections.abc import Coroutine @@ -6,6 +7,44 @@ class AsyncUtils: # remember main loop main_loop: asyncio.AbstractEventLoop | None = None + @staticmethod + def apply_asyncio_313_patch(): + """Apply a patch for asyncio on Python 3.13 to avoid a bug in sendfile with SSL. + See: https://github.com/python/cpython/issues/124448 + And: https://github.com/aio-libs/aiohttp/issues/8863 + """ + if sys.version_info >= (3, 13): + import asyncio.base_events + + # We need to patch the loop's sendfile to raise NotImplementedError for SSL transports. + # This will force aiohttp to use its own fallback which works correctly. + + original_sendfile = asyncio.base_events.BaseEventLoop.sendfile + + async def patched_sendfile( + self, + transport, + file, + offset=0, + count=None, + *, + fallback=True, + ): + if transport.get_extra_info("sslcontext"): + raise NotImplementedError( + "sendfile is broken on SSL transports in Python 3.13", + ) + return await original_sendfile( + self, + transport, + file, + offset, + count, + fallback=fallback, + ) + + asyncio.base_events.BaseEventLoop.sendfile = patched_sendfile + @staticmethod def set_main_loop(loop: asyncio.AbstractEventLoop): AsyncUtils.main_loop = loop diff --git a/meshchatx/src/backend/auto_propagation_manager.py b/meshchatx/src/backend/auto_propagation_manager.py new file mode 100644 index 0000000..e552759 --- /dev/null +++ b/meshchatx/src/backend/auto_propagation_manager.py @@ -0,0 +1,124 @@ +import asyncio +import time + +import RNS + +from meshchatx.src.backend.meshchat_utils import parse_lxmf_propagation_node_app_data + + +class AutoPropagationManager: + def __init__(self, app, context): + self.app = app + self.context = context + self.config = context.config + self.database = context.database + self.running = False + self._last_check = 0 + self._check_interval = 300 # 5 minutes + + def stop(self): + self.running = False + + async def _run(self): + # Wait a bit after startup to allow discovers to come in + await asyncio.sleep(10) + self.running = True + + while self.running and self.context.running: + try: + if self.config.lxmf_preferred_propagation_node_auto_select.get(): + await self.check_and_update_propagation_node() + except asyncio.CancelledError: + break + except Exception as e: + print( + f"Error in AutoPropagationManager for {self.context.identity_hash}: {e}", + ) + + await asyncio.sleep(self._check_interval) + + async def check_and_update_propagation_node(self): + # Get all propagation node announces + announces = self.database.announces.get_announces(aspect="lxmf.propagation") + + nodes_with_hops = [] + for announce in announces: + dest_hash_hex = announce["destination_hash"] + dest_hash = bytes.fromhex(dest_hash_hex) + + # Check if propagation is enabled for this node + node_data = parse_lxmf_propagation_node_app_data(announce["app_data"]) + if not node_data or not node_data.get("enabled", False): + continue + + if RNS.Transport.has_path(dest_hash): + hops = RNS.Transport.hops_to(dest_hash) + nodes_with_hops.append((hops, dest_hash_hex)) + + # Sort by hops (lowest first) + nodes_with_hops.sort() + + current_node = ( + self.config.lxmf_preferred_propagation_node_destination_hash.get() + ) + + if not nodes_with_hops: + return + + # Try nodes in order of hops until we find a reachable one + for hops, node_hex in nodes_with_hops: + # If current node is already the best and we have it, check if we should keep it + if node_hex == current_node: + # We could probe it to be sure, but for now let's assume it's fine if it's the best + return + + # Before switching to a new "best" node, try to probe it to ensure it's actually reachable + try: + dest_hash = bytes.fromhex(node_hex) + # We use a short timeout for the probe + if await self.probe_node(dest_hash): + print( + f"Auto-propagation: Switching to better node {node_hex} ({hops} hops) for {self.context.identity_hash}", + ) + self.app.set_active_propagation_node(node_hex, context=self.context) + self.config.lxmf_preferred_propagation_node_destination_hash.set( + node_hex, + ) + return + print( + f"Auto-propagation: Node {node_hex} announced but probe failed, trying next...", + ) + except Exception as e: + print(f"Auto-propagation: Error probing node {node_hex}: {e}") + + async def probe_node(self, destination_hash): + """Probes a destination to see if it's reachable.""" + try: + # We use the app's probe handler if available + if ( + hasattr(self.context, "rnprobe_handler") + and self.context.rnprobe_handler + ): + # Re-using the logic from RNProbeHandler but simplified + if not RNS.Transport.has_path(destination_hash): + RNS.Transport.request_path(destination_hash) + + # Wait a bit for path + timeout = 5 + start = time.time() + while ( + not RNS.Transport.has_path(destination_hash) + and time.time() - start < timeout + ): + await asyncio.sleep(0.5) + + if not RNS.Transport.has_path(destination_hash): + return False + + # If we have a path, it's a good sign. + # For propagation nodes, having a path is often enough to try using it. + return True + + return RNS.Transport.has_path(destination_hash) + except Exception: + return False diff --git a/meshchatx/src/backend/bot_handler.py b/meshchatx/src/backend/bot_handler.py new file mode 100644 index 0000000..ee1baf0 --- /dev/null +++ b/meshchatx/src/backend/bot_handler.py @@ -0,0 +1,341 @@ +import json +import logging +import os +import shutil +import subprocess +import sys +import time +import uuid + +import RNS + +logger = logging.getLogger("meshchatx.bots") + + +class BotHandler: + def __init__(self, identity_path, config_manager=None): + self.identity_path = os.path.abspath(identity_path) + self.config_manager = config_manager + self.bots_dir = os.path.join(self.identity_path, "bots") + os.makedirs(self.bots_dir, exist_ok=True) + self.running_bots = {} + self.state_file = os.path.join(self.bots_dir, "bots_state.json") + self.bots_state: list[dict] = [] + self._load_state() + self.runner_path = os.path.join( + os.path.dirname(__file__), + "bot_process.py", + ) + + def _load_state(self): + try: + with open(self.state_file, encoding="utf-8") as f: + self.bots_state = json.load(f) + # Ensure all storage paths are absolute + for entry in self.bots_state: + if "storage_dir" in entry: + entry["storage_dir"] = os.path.abspath(entry["storage_dir"]) + except FileNotFoundError: + self.bots_state = [] + except Exception: + self.bots_state = [] + + def _save_state(self): + try: + with open(self.state_file, "w", encoding="utf-8") as f: + json.dump(self.bots_state, f, indent=2) + except Exception: + pass + + def get_available_templates(self): + return [ + { + "id": "echo", + "name": "Echo Bot", + "description": "Repeats any message it receives.", + }, + { + "id": "note", + "name": "Note Bot", + "description": "Store and retrieve notes using JSON storage.", + }, + { + "id": "reminder", + "name": "Reminder Bot", + "description": "Set and receive reminders using SQLite storage.", + }, + ] + + def restore_enabled_bots(self): + for entry in list(self.bots_state): + if entry.get("enabled"): + try: + self.start_bot( + template_id=entry["template_id"], + name=entry["name"], + bot_id=entry["id"], + storage_dir=entry["storage_dir"], + ) + except Exception as exc: + logger.warning("Failed to restore bot %s: %s", entry.get("id"), exc) + + def get_status(self): + bots: list[dict] = [] + + for entry in self.bots_state: + bot_id = entry.get("id") + template = entry.get("template_id") or entry.get("template") + name = entry.get("name") or "Unknown" + pid = entry.get("pid") + + running = False + if bot_id in self.running_bots: + running = True + elif pid: + running = self._is_pid_alive(pid) + + address_pretty = None + address_full = None + + # Try running instance first + instance = self.running_bots.get(bot_id, {}).get("instance") + if ( + instance + and getattr(instance, "bot", None) + and getattr(instance.bot, "local", None) + ): + try: + address_pretty = RNS.prettyhexrep(instance.bot.local.hash) + address_full = RNS.hexrep(instance.bot.local.hash, delimit=False) + except Exception: + pass + + # Fallback to identity file on disk + if address_full is None: + identity = self._load_identity_for_bot(bot_id) + if identity: + try: + destination = RNS.Destination(identity, "lxmf", "delivery") + address_full = destination.hash.hex() + address_pretty = RNS.prettyhexrep(destination.hash) + except Exception: + pass + + bots.append( + { + "id": bot_id, + "template": template, + "template_id": template, + "name": name, + "address": address_pretty or "Unknown", + "full_address": address_full, + "running": running, + "pid": pid, + "storage_dir": entry.get("storage_dir"), + }, + ) + + return { + "has_lxmfy": True, + "detection_error": None, + "running_bots": [b for b in bots if b["running"]], + "bots": bots, + } + + def start_bot(self, template_id, name=None, bot_id=None, storage_dir=None): + # Reuse existing entry or create new + entry = None + if bot_id: + for e in self.bots_state: + if e.get("id") == bot_id: + entry = e + break + if entry is None: + bot_id = bot_id or uuid.uuid4().hex + bot_storage_dir = storage_dir or os.path.join(self.bots_dir, bot_id) + bot_storage_dir = os.path.abspath(bot_storage_dir) + entry = { + "id": bot_id, + "template_id": template_id, + "name": name or f"{template_id.title()} Bot", + "storage_dir": bot_storage_dir, + "enabled": True, + "pid": None, + } + self.bots_state.append(entry) + else: + bot_storage_dir = entry["storage_dir"] + entry["template_id"] = template_id + entry["name"] = name or entry.get("name") or f"{template_id.title()} Bot" + entry["enabled"] = True + + os.makedirs(bot_storage_dir, exist_ok=True) + + cmd = [ + sys.executable, + self.runner_path, + "--template", + template_id, + "--name", + entry["name"], + "--storage", + bot_storage_dir, + ] + + proc = subprocess.Popen(cmd, cwd=bot_storage_dir) # noqa: S603 + entry["pid"] = proc.pid + self._save_state() + + self.running_bots[bot_id] = { + "instance": None, + "thread": None, + "stop_event": None, + "template": template_id, + "pid": proc.pid, + } + logger.info(f"Started bot {bot_id} (template: {template_id}) pid={proc.pid}") + return bot_id + + def stop_bot(self, bot_id): + entry = None + for e in self.bots_state: + if e.get("id") == bot_id: + entry = e + break + if entry is None: + return False + + pid = entry.get("pid") + if pid: + try: + if sys.platform.startswith("win"): + subprocess.run( + ["taskkill", "/PID", str(pid), "/T", "/F"], + check=False, + timeout=5, + ) + else: + os.kill(pid, 15) + # brief wait + time.sleep(0.5) + # optional force kill if still alive + try: + os.kill(pid, 0) + os.kill(pid, 9) + except OSError: + pass + except Exception as exc: + logger.warning( + "Failed to terminate bot %s pid %s: %s", + bot_id, + pid, + exc, + ) + + entry["pid"] = None + entry["enabled"] = False + self._save_state() + if bot_id in self.running_bots: + del self.running_bots[bot_id] + logger.info("Stopped bot %s", bot_id) + return True + + def restart_bot(self, bot_id): + entry = None + for e in self.bots_state: + if e.get("id") == bot_id: + entry = e + break + if entry is None: + raise ValueError(f"Unknown bot: {bot_id}") + self.stop_bot(bot_id) + return self.start_bot( + template_id=entry["template_id"], + name=entry["name"], + bot_id=bot_id, + storage_dir=entry["storage_dir"], + ) + + def delete_bot(self, bot_id): + # Stop it first + self.stop_bot(bot_id) + + # Remove from state + entry = None + for i, e in enumerate(self.bots_state): + if e.get("id") == bot_id: + entry = e + del self.bots_state[i] + break + + if entry: + # Delete storage dir + storage_dir = entry.get("storage_dir") + if storage_dir and os.path.exists(storage_dir): + try: + shutil.rmtree(storage_dir) + except Exception as exc: + logger.warning( + "Failed to delete storage dir for bot %s: %s", + bot_id, + exc, + ) + + self._save_state() + logger.info("Deleted bot %s", bot_id) + return True + return False + + def get_bot_identity_path(self, bot_id): + entry = None + for e in self.bots_state: + if e.get("id") == bot_id: + entry = e + break + + if not entry: + return None + + storage_dir = entry.get("storage_dir") + if not storage_dir: + return None + + # LXMFy stores identity in the 'config' subdirectory by default + id_path = os.path.join(storage_dir, "config", "identity") + if os.path.exists(id_path): + return id_path + + # Fallback to direct identity file if it was moved or configured differently + id_path_alt = os.path.join(storage_dir, "identity") + if os.path.exists(id_path_alt): + return id_path_alt + + # LXMFy may nest inside config/lxmf + id_path_lxmf = os.path.join(storage_dir, "config", "lxmf", "identity") + if os.path.exists(id_path_lxmf): + return id_path_lxmf + + return None + + def _load_identity_for_bot(self, bot_id): + identity_path = self.get_bot_identity_path(bot_id) + if not identity_path: + return None + try: + return RNS.Identity.from_file(identity_path) + except Exception: + return None + + @staticmethod + def _is_pid_alive(pid): + if not pid: + return False + try: + os.kill(pid, 0) + return True + except OSError: + return False + + def stop_all(self): + for bot_id in list(self.running_bots.keys()): + self.stop_bot(bot_id) diff --git a/meshchatx/src/backend/bot_process.py b/meshchatx/src/backend/bot_process.py new file mode 100644 index 0000000..91f53ed --- /dev/null +++ b/meshchatx/src/backend/bot_process.py @@ -0,0 +1,45 @@ +import argparse +import os + +from meshchatx.src.backend.bot_templates import ( + EchoBotTemplate, + NoteBotTemplate, + ReminderBotTemplate, +) + +TEMPLATE_MAP = { + "echo": EchoBotTemplate, + "note": NoteBotTemplate, + "reminder": ReminderBotTemplate, +} + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--template", required=True, choices=TEMPLATE_MAP.keys()) + parser.add_argument("--name", required=True) + parser.add_argument("--storage", required=True) + args = parser.parse_args() + + os.makedirs(args.storage, exist_ok=True) + os.chdir(args.storage) + + BotCls = TEMPLATE_MAP[args.template] + # LXMFy hardcodes its config directory to os.path.join(os.getcwd(), 'config'). + # By chdir'ing into args.storage, we ensure 'config' and data are kept within that folder. + bot_instance = BotCls(name=args.name, storage_path=args.storage, test_mode=False) + + # Optional immediate announce for reachability + try: + if hasattr(bot_instance.bot, "announce_enabled"): + bot_instance.bot.announce_enabled = True + if hasattr(bot_instance.bot, "_announce"): + bot_instance.bot._announce() + except Exception: + pass + + bot_instance.run() + + +if __name__ == "__main__": + main() diff --git a/meshchatx/src/backend/bot_templates.py b/meshchatx/src/backend/bot_templates.py new file mode 100644 index 0000000..5814f2d --- /dev/null +++ b/meshchatx/src/backend/bot_templates.py @@ -0,0 +1,265 @@ +import re +import time +from datetime import datetime, timedelta + +from lxmfy import IconAppearance, LXMFBot, pack_icon_appearance_field + +HAS_LXMFY = True + + +class StoppableBot: + def __init__(self): + self._stop_event = None + + def set_stop_event(self, stop_event): + self._stop_event = stop_event + + def should_stop(self): + return self._stop_event and self._stop_event.is_set() + + +class EchoBotTemplate(StoppableBot): + def __init__(self, name="Echo Bot", storage_path=None, test_mode=False): + super().__init__() + + self.bot = LXMFBot( + name=name, + announce=600, + command_prefix="", + first_message_enabled=True, + test_mode=test_mode, + storage_path=storage_path, + ) + self.setup_commands() + self.setup_message_handlers() + + icon_data = IconAppearance( + icon_name="forum", + fg_color=b"\xad\xd8\xe6", + bg_color=b"\x3b\x59\x98", + ) + self.icon_lxmf_field = pack_icon_appearance_field(icon_data) + + def setup_message_handlers(self): + @self.bot.on_message() + def echo_non_command_messages(sender, message): + if self.should_stop(): + return True + content = message.content.decode("utf-8").strip() + if not content: + return False + + command_name = content.split()[0] + if command_name in self.bot.commands: + return False + + self.bot.send( + sender, + content, + lxmf_fields=self.icon_lxmf_field, + ) + return False + + def setup_commands(self): + @self.bot.command(name="echo", description="Echo back your message") + def echo(ctx): + if self.should_stop(): + return + if ctx.args: + ctx.reply(" ".join(ctx.args), lxmf_fields=self.icon_lxmf_field) + else: + ctx.reply("Usage: echo ", lxmf_fields=self.icon_lxmf_field) + + @self.bot.on_first_message() + def welcome(sender, message): + if self.should_stop(): + return True + content = message.content.decode("utf-8").strip() + self.bot.send( + sender, + f"Hi! I'm an echo bot, You said: {content}\n\n" + "Try: echo to make me repeat things!", + lxmf_fields=self.icon_lxmf_field, + ) + return True + + def run(self): + self.bot.scheduler.start() + try: + while not self.should_stop(): + for _ in range(self.bot.queue.qsize()): + lxm = self.bot.queue.get() + if self.bot.router: + self.bot.router.handle_outbound(lxm) + time.sleep(1) + finally: + self.bot.cleanup() + + +class NoteBotTemplate(StoppableBot): + def __init__(self, name="Note Bot", storage_path=None, test_mode=False): + super().__init__() + + self.bot = LXMFBot( + name=name, + announce=600, + command_prefix="/", + storage_type="json", + storage_path=storage_path or "data/notes", + test_mode=test_mode, + ) + self.setup_commands() + + def setup_commands(self): + @self.bot.command(name="note", description="Save a note") + def save_note(ctx): + if self.should_stop(): + return + if not ctx.args: + ctx.reply("Usage: /note ") + return + + note = { + "text": " ".join(ctx.args), + "timestamp": datetime.now().isoformat(), + "tags": [w[1:] for w in ctx.args if w.startswith("#")], + } + + notes = self.bot.storage.get(f"notes:{ctx.sender}", []) + notes.append(note) + self.bot.storage.set(f"notes:{ctx.sender}", notes) + ctx.reply("Note saved!") + + @self.bot.command(name="notes", description="List your notes") + def list_notes(ctx): + if self.should_stop(): + return + notes = self.bot.storage.get(f"notes:{ctx.sender}", []) + if not notes: + ctx.reply("You haven't saved any notes yet!") + return + + if not ctx.args: + response = "Your Notes:\n" + for i, note in enumerate(notes[-10:], 1): + tags = ( + " ".join(f"#{tag}" for tag in note["tags"]) + if note["tags"] + else "" + ) + response += f"{i}. {note['text']} {tags}\n" + if len(notes) > 10: + response += f"\nShowing last 10 of {len(notes)} notes. Use /notes all to see all." + ctx.reply(response) + elif ctx.args[0] == "all": + response = "All Your Notes:\n" + for i, note in enumerate(notes, 1): + tags = ( + " ".join(f"#{tag}" for tag in note["tags"]) + if note["tags"] + else "" + ) + response += f"{i}. {note['text']} {tags}\n" + ctx.reply(response) + + def run(self): + self.bot.scheduler.start() + try: + while not self.should_stop(): + for _ in range(self.bot.queue.qsize()): + lxm = self.bot.queue.get() + if self.bot.router: + self.bot.router.handle_outbound(lxm) + time.sleep(1) + finally: + self.bot.cleanup() + + +class ReminderBotTemplate(StoppableBot): + def __init__(self, name="Reminder Bot", storage_path=None, test_mode=False): + super().__init__() + + self.bot = LXMFBot( + name=name, + announce=600, + command_prefix="/", + storage_type="sqlite", + storage_path=storage_path or "data/reminders.db", + test_mode=test_mode, + ) + self.setup_commands() + self.bot.scheduler.add_task( + "check_reminders", + self._check_reminders, + "*/1 * * * *", + ) + + def setup_commands(self): + @self.bot.command(name="remind", description="Set a reminder") + def remind(ctx): + if self.should_stop(): + return + if not ctx.args or len(ctx.args) < 2: + ctx.reply( + "Usage: /remind
@@ -132,6 +149,7 @@ export default { }, }, }, + emits: ["notifications-cleared"], data() { return { isDropdownOpen: false, @@ -139,9 +157,17 @@ export default { notifications: [], unreadCount: 0, reloadInterval: null, + dropdownPosition: { top: 0, left: 0 }, }; }, - computed: {}, + computed: { + dropdownStyle() { + return { + top: `${this.dropdownPosition.top}px`, + left: `${this.dropdownPosition.left}px`, + }; + }, + }, beforeUnmount() { if (this.reloadInterval) { clearInterval(this.reloadInterval); @@ -158,13 +184,25 @@ export default { }, 5000); }, methods: { - async toggleDropdown() { + async toggleDropdown(event) { this.isDropdownOpen = !this.isDropdownOpen; if (this.isDropdownOpen) { + this.updateDropdownPosition(event); await this.loadNotifications(); await this.markNotificationsAsViewed(); } }, + updateDropdownPosition(event) { + const button = event.currentTarget; + const rect = button.getBoundingClientRect(); + const isMobile = window.innerWidth < 640; + const dropdownWidth = isMobile ? 320 : 384; // 80 (320px) or 96 (384px) + + this.dropdownPosition = { + top: rect.bottom + 8, + left: Math.max(16, rect.right - dropdownWidth), + }; + }, closeDropdown() { this.isDropdownOpen = false; }, @@ -206,6 +244,37 @@ export default { console.error("Failed to mark notifications as viewed", e); } }, + async clearAllNotifications() { + try { + await window.axios.post("/api/v1/notifications/mark-as-viewed", { + destination_hashes: [], + notification_ids: [], + }); + + const response = await window.axios.get("/api/v1/lxmf/conversations"); + const conversations = response.data.conversations || []; + + for (const conversation of conversations) { + if (conversation.is_unread) { + try { + await window.axios.get( + `/api/v1/lxmf/conversations/${conversation.destination_hash}/mark-as-read` + ); + } catch (e) { + console.error(`Failed to mark conversation as read: ${conversation.destination_hash}`, e); + } + } + } + + const GlobalState = (await import("../js/GlobalState")).default; + GlobalState.unreadConversationsCount = 0; + + await this.loadNotifications(); + this.$emit("notifications-cleared"); + } catch (e) { + console.error("Failed to clear notifications", e); + } + }, onNotificationClick(notification) { this.closeDropdown(); if (notification.type === "lxmf_message") { @@ -218,6 +287,11 @@ export default { name: "call", query: { tab: "history" }, }); + } else if (notification.type === "telephone_voicemail") { + this.$router.push({ + name: "call", + query: { tab: "voicemail" }, + }); } }, formatTimeAgo(datetimeString) { diff --git a/meshchatx/src/frontend/components/Toast.vue b/meshchatx/src/frontend/components/Toast.vue index 1cc77f9..d5c7192 100644 --- a/meshchatx/src/frontend/components/Toast.vue +++ b/meshchatx/src/frontend/components/Toast.vue @@ -24,12 +24,17 @@ icon-name="alert" class="h-6 w-6 text-amber-500" /> +
- {{ toast.message }} + {{ $t(toast.message) }}
@@ -60,33 +65,68 @@ export default { }; }, mounted() { - GlobalEmitter.on("toast", (toast) => { + this.toastHandler = (toast) => { this.add(toast); - }); + }; + GlobalEmitter.on("toast", this.toastHandler); }, beforeUnmount() { - GlobalEmitter.off("toast"); + GlobalEmitter.off("toast", this.toastHandler); }, methods: { add(toast) { + // Check if a toast with the same key already exists + if (toast.key) { + const existingIndex = this.toasts.findIndex((t) => t.key === toast.key); + if (existingIndex !== -1) { + const existingToast = this.toasts[existingIndex]; + + // Clear existing timeout if it exists + if (existingToast.timer) { + clearTimeout(existingToast.timer); + } + + // Update existing toast + existingToast.message = toast.message; + existingToast.type = toast.type || "info"; + existingToast.duration = toast.duration !== undefined ? toast.duration : 5000; + + if (existingToast.duration > 0) { + existingToast.timer = setTimeout(() => { + this.remove(existingToast.id); + }, existingToast.duration); + } else { + existingToast.timer = null; + } + return; + } + } + const id = this.counter++; const newToast = { id, + key: toast.key, message: toast.message, type: toast.type || "info", - duration: toast.duration || 5000, + duration: toast.duration !== undefined ? toast.duration : 5000, + timer: null, }; - this.toasts.push(newToast); if (newToast.duration > 0) { - setTimeout(() => { + newToast.timer = setTimeout(() => { this.remove(id); }, newToast.duration); } + + this.toasts.push(newToast); }, remove(id) { const index = this.toasts.findIndex((t) => t.id === id); if (index !== -1) { + const toast = this.toasts[index]; + if (toast.timer) { + clearTimeout(toast.timer); + } this.toasts.splice(index, 1); } }, diff --git a/meshchatx/src/frontend/components/TutorialModal.vue b/meshchatx/src/frontend/components/TutorialModal.vue new file mode 100644 index 0000000..b4f9b8f --- /dev/null +++ b/meshchatx/src/frontend/components/TutorialModal.vue @@ -0,0 +1,1752 @@ + + + + + diff --git a/meshchatx/src/frontend/components/about/AboutPage.vue b/meshchatx/src/frontend/components/about/AboutPage.vue index 363662f..00343b3 100644 --- a/meshchatx/src/frontend/components/about/AboutPage.vue +++ b/meshchatx/src/frontend/components/about/AboutPage.vue @@ -2,466 +2,896 @@
-
-
-
-
-
-
- {{ $t("about.title") }} +
+
+ +
+
+ +
+
+
-
Reticulum MeshChatX
-
- {{ $t("about.version", { version: appInfo.version }) }} • - {{ $t("about.rns_version", { version: appInfo.rns_version }) }} • - {{ $t("about.lxmf_version", { version: appInfo.lxmf_version }) }} • - {{ $t("about.python_version", { version: appInfo.python_version }) }} +
+
+ MeshChatX +
+
+ {{ $t("about.version", { version: appInfo.version }) }} +
-
- + + +
-
-
-
{{ $t("about.config_path") }}
-
{{ appInfo.reticulum_config_path }}
- + +
+
+ A secure, resilient, and beautiful communications platform powered by the + Reticulum Network Stack.
-
-
{{ $t("about.database_path") }}
-
{{ appInfo.database_path }}
- -
-
-
{{ $t("about.database_size") }}
-
- {{ - formatBytes( - appInfo.database_files - ? appInfo.database_files.total_bytes - : appInfo.database_file_size - ) - }} + + +
+
+
+ Contact Developer +
+
-
- Main {{ formatBytes(appInfo.database_files.main_bytes) }} • WAL - {{ formatBytes(appInfo.database_files.wal_bytes) }} + + + +
+
+
+ LXMF Address +
+
+ 7cc8d66b4f6a0e0e49d34af7f6077b5a + +
+
+
+
+ Alternate +
+
+ 43d3309adf27fc446556121b553b56a6 + +
+
+
+ + Send to propagation node if you cant reach me! +
+
+
+
+ +
+
+
+ Database Size +
+
+ {{ + formatBytes( + appInfo.database_files + ? appInfo.database_files.total_bytes + : appInfo.database_file_size + ) + }} +
-
-
-
-
- {{ $t("about.database_health") }} -
-
- {{ $t("about.database_health_description") }} -
-
-
- - - -
-
-
{{ databaseActionMessage }}
-
{{ databaseActionError }}
-
- {{ $t("about.running_checks") }} -
-
-
-
{{ $t("about.integrity") }}
-
{{ databaseHealth.quick_check }}
-
-
-
{{ $t("about.journal_mode") }}
-
{{ databaseHealth.journal_mode }}
-
-
-
{{ $t("about.wal_autocheckpoint") }}
-
- {{ - databaseHealth.wal_autocheckpoint !== null && - databaseHealth.wal_autocheckpoint !== undefined - ? databaseHealth.wal_autocheckpoint - : "—" - }} + + Security & Integrity +
+
+ + + {{ + appInfo.integrity_issues.length === 0 + ? $t("about.secured") + : $t("about.tampering_detected") + }} + +
-
-
{{ $t("about.page_size") }}
-
{{ formatBytes(databaseHealth.page_size) }}
-
-
-
{{ $t("about.pages_free") }}
-
- {{ formatNumber(databaseHealth.page_count) }} / - {{ formatNumber(databaseHealth.freelist_pages) }} -
-
-
-
{{ $t("about.free_space_estimate") }}
-
{{ formatBytes(databaseHealth.estimated_free_bytes) }}
-
-
-
- Health data will appear after the first refresh. -
-
-
Last recovery steps
-
    -
  • - {{ action.step }}: - {{ formatRecoveryResult(action.result) }} -
  • -
-
-
-
Backups
- -
{{ backupMessage }}
-
{{ backupError }}
-
Restore
-
- - + + Technical Issues Detected +
+
    +
  • + + {{ issue }} +
  • +
-
- Selected: {{ restoreFileName }} +
+ + {{ $t("about.no_integrity_violations") }}
-
{{ restoreMessage }}
-
{{ restoreError }}
-
-
Identity Backup & Restore
-
- Never share this identity. It grants full control. Clear your clipboard after copying. +
+ + +
+
+ + Environment Information +
+
+
+
Reticulum Config
+
+ {{ appInfo.reticulum_config_path }} +
+ +
+
+
Database Path
+
+ {{ appInfo.database_path }} +
+ +
+
+
+
+ Identity Hash + {{ + config.identity_hash + }} +
+
+ LXMF Address + {{ + config.lxmf_address_hash + }} +
+
+
+ Python + v{{ appInfo.python_version }} +
+
+ LXMF + v{{ appInfo.lxmf_version }} +
+
+ RNS + v{{ appInfo.rns_version }} +
+
+
+
+ + +
+
+ + Dependency Chain +
+
+
+
+
+ +
+
+
MeshChatX
+
+ v{{ appInfo.version }} +
+
+
+
+
+
+ LXMFy +
+
+
+ LXMF Bot framework +
+
+ v{{ (appInfo.dependencies && appInfo.dependencies.lxmfy) || "unknown" }} +
+
+
+
+
+
+ LXMF +
+
+
+ Lightweight Extensible Message Format +
+
+ v{{ appInfo.lxmf_version }} +
+
+
+
+
+
+ RNS +
+
+
+ Reticulum Network Stack +
+
+
+ v{{ appInfo.rns_version }} +
+
+ {{ + appInfo.is_connected_to_shared_instance + ? `Shared Instance: ${appInfo.shared_instance_address || "unknown"}` + : "Main Instance" + }} +
+
+
+
+
+ +
+
+
+ Core Runtime +
+
+
+ LXST Engine + v{{ appInfo.lxst_version }} +
+
+ Electron + v{{ electronVersion }} +
+
+ Chrome + v{{ chromeVersion }} +
+
+ Node.js + v{{ nodeVersion }} +
+
+
+ +
+
+ Backend Stack +
+
+
+ {{ name.replace("_", " ") }} + v{{ version }} +
+
+
+
+
+
+ + +
+
+
+ + Database Health & Maintenance
-
-
- {{ identityBackupMessage }} -
-
{{ identityBackupError }}
-
- {{ identityBase32Message }} -
-
{{ identityBase32Error }}
-
Restore from file
-
-
-
- Selected: {{ identityRestoreFileName }} -
-
Restore from base32
- - -
- {{ identityRestoreMessage }} -
-
- {{ identityRestoreError }} -
-
-
-
- -
-
-
- -
-
- {{ $t("about.system_resources") }} +
+ Integrity
-
- - {{ $t("about.live") }} +
+ {{ databaseHealth.quick_check }}
-
-
-
-
{{ $t("about.memory_rss") }}
-
{{ formatBytes(appInfo.memory_usage.rss) }}
-
-
-
{{ $t("about.virtual_memory") }}
-
{{ formatBytes(appInfo.memory_usage.vms) }}
-
-
-
- -
-
- -
-
- {{ $t("about.network_stats") }} -
-
- - {{ $t("about.live") }} -
-
-
-
-
-
{{ $t("about.sent") }}
-
{{ formatBytes(appInfo.network_stats.bytes_sent) }}
-
-
-
{{ $t("about.received") }}
-
{{ formatBytes(appInfo.network_stats.bytes_recv) }}
-
-
-
-
-
{{ $t("about.packets_sent") }}
-
{{ formatNumber(appInfo.network_stats.packets_sent) }}
-
-
-
{{ $t("about.packets_received") }}
-
{{ formatNumber(appInfo.network_stats.packets_recv) }}
-
-
-
- -
-
- -
-
- {{ $t("about.reticulum_stats") }} -
-
- - {{ $t("about.live") }} -
-
-
-
-
-
{{ $t("about.total_paths") }}
-
{{ formatNumber(appInfo.reticulum_stats.total_paths) }}
-
-
-
{{ $t("about.announces_per_second") }}
-
- {{ formatNumber(appInfo.reticulum_stats.announces_per_second) }} -
-
-
-
{{ $t("about.announces_per_minute") }}
-
- {{ formatNumber(appInfo.reticulum_stats.announces_per_minute) }} -
-
-
-
{{ $t("about.announces_per_hour") }}
-
- {{ formatNumber(appInfo.reticulum_stats.announces_per_hour) }} -
-
-
-
- -
-
- -
-
- {{ $t("about.download_activity") }} -
-
- - {{ $t("about.live") }} -
-
-
-
- - {{ formatBytesPerSecond(appInfo.download_stats.avg_download_speed_bps) }} - - {{ $t("about.no_downloads_yet") }} -
-
-
- -
-
- {{ $t("about.runtime_status") }} -
-
- - - {{ - appInfo.is_connected_to_shared_instance - ? $t("about.shared_instance") - : $t("about.standalone_instance") - }} - - - - {{ - appInfo.is_transport_enabled - ? $t("about.transport_enabled") - : $t("about.transport_disabled") - }} - -
-
- -
-
- {{ $t("about.identity_addresses") }} -
-
-
-
{{ $t("app.identity_hash") }}
-
{{ config.identity_hash }}
- -
-
-
{{ $t("app.lxmf_address") }}
-
{{ config.lxmf_address_hash }}
-
+
+ {{ databaseHealth.journal_mode }} +
+
+
- - {{ $t("app.copy") }} - -
-
-
{{ $t("app.propagation_node") }}
-
- {{ config.lxmf_local_propagation_node_address_hash || "—" }} +
+ Page Count +
+
+ {{ databaseHealth.page_count }} +
+
+
+
+ Free Space +
+
+ {{ formatBytes(databaseHealth.estimated_free_bytes) }} +
-
-
{{ $t("about.telephone_address") }}
-
{{ config.telephone_address_hash || "—" }}
+ +
+ +
+
+
+ + Database Backups +
+
+ Full snapshots of your communications database. +
+
+ +
+ + +
+
+
+
+ + Local Snapshots +
+
+ Create point-in-time restore points on disk. +
+
+
+ + +
+
+ +
+
+
+
+ {{ snapshot.name }} + {{ formatBytes(snapshot.size) }} • + {{ Utils.formatTimeAgo(snapshot.created_at) }} +
+
+ + + +
+
+
+ + +
+
+ Page {{ Math.floor(snapshotsOffset / snapshotsLimit) + 1 }} of + {{ Math.ceil(snapshotsTotal / snapshotsLimit) }} +
+
+ + +
+
+
+
+ + +
+
+
+
+ + Automatic Backups +
+
+ Automated daily snapshots of your database. +
+
+
+ +
+
+
+
+ {{ backup.name }} + {{ formatBytes(backup.size) }} • + {{ Utils.formatTimeAgo(backup.created_at) }} +
+
+ + + +
+
+
+ + +
+
+ Page {{ Math.floor(autoBackupsOffset / autoBackupsLimit) + 1 }} of + {{ Math.ceil(autoBackupsTotal / autoBackupsLimit) }} +
+
+ + +
+
+
+
+ + +
+
+ +
+
Identity Key Control
+
+ Critical Security Warning +
+
+
+ +
+ + +
+ +
+
+ Restore Identity +
+
+ + +
+ — or — +
+ +
+ + +
+ + +
+
+
+
@@ -473,15 +903,15 @@ + + diff --git a/meshchatx/src/frontend/components/archives/ArchiveSidebar.vue b/meshchatx/src/frontend/components/archives/ArchiveSidebar.vue new file mode 100644 index 0000000..3885bcf --- /dev/null +++ b/meshchatx/src/frontend/components/archives/ArchiveSidebar.vue @@ -0,0 +1,111 @@ + + + diff --git a/meshchatx/src/frontend/components/archives/ArchivesPage.vue b/meshchatx/src/frontend/components/archives/ArchivesPage.vue index 918cde8..26affce 100644 --- a/meshchatx/src/frontend/components/archives/ArchivesPage.vue +++ b/meshchatx/src/frontend/components/archives/ArchivesPage.vue @@ -1,186 +1,197 @@