diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..7b85193f853fdd3076baae94a70ffb8fd10f5513 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,97 @@ +# Python cache files +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Exception: Keep SageAttention and SpargeAttn build directories for Docker +!SageAttention/ +!SpargeAttn/ +!docker/ + +# But exclude their build artifacts +SageAttention/build/ +SageAttention/*.egg-info/ +SageAttention/**/__pycache__/ +SpargeAttn/build/ +SpargeAttn/*.egg-info/ +SpargeAttn/**/__pycache__/ + +# Virtual environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Git +.git/ +.gitignore + +# Docker files (not needed in the image, but Dockerfile itself is needed for the build context) +.dockerignore + +# Documentation (not needed in runtime, but docker/ scripts are needed for build) +*.md +!docker/ +docs/ +!frontend/dist/ +!frontend/dist/** + +# Large model files (these should be downloaded at runtime) +*.safetensors +*.ckpt +*.pt +*.pth +*.bin +*.gguf + +# Logs +*.log +logs/ + +# Temporary files +tmp/ +temp/ +*.tmp + +# Generated images (these will be created at runtime) +output/ + +# Large dependencies that will be installed via pip +stable_fast-*.whl diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..dfe0770424b2a19faf507a501ebfc23be8f54e7b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.github/instructions/memory.instruction.md b/.github/instructions/memory.instruction.md new file mode 100644 index 0000000000000000000000000000000000000000..df9b8699dcfc9471019e3a99a80ced33d705f911 --- /dev/null +++ b/.github/instructions/memory.instruction.md @@ -0,0 +1,46 @@ +--- +applyTo: '**' +--- + +# User Memory + +## User Preferences +- Programming languages: +- Code style preferences: +- Development environment: +- Communication style: + +## Project Context +- Current project type: +- Tech stack: +- Architecture patterns: +- Key requirements: + +## Coding Patterns +- Preferred patterns and practices +- Code organization preferences +- Testing approaches +- Documentation style + +## Context7 Research History +- Libraries researched on Context7 +- Best practices discovered +- Implementation patterns used +- Version-specific findings + +- 2026-02-11: Searched Context7 for pytest; no libraries found. Reviewed Context7 MCP docs (all-clients, adding-libraries, troubleshooting, api-guide, developer guide) to satisfy research requirements for this task. + +## Conversation History +- 2026-02-11: Requested DifferentialDiffusion class excerpt with line numbers from src/AutoDetailer/ADetailer.py. +- 2026-02-11: Fixing ADetailer SDXL mask behavior by applying denoise_mask blending in KSamplerX0Inpaint; will add tests and validate with manual image generation. +- 2026-02-11: Added denoise_mask resizing to latent resolution to avoid shape mismatch; generated SDXL baseline and ADetailer outputs for manual verification. +- 2026-02-11: Normalized ADetailer noise masks to [0,1], aligned SDXL crop conditioning to crop-local sizes, and added unit tests plus manual SDXL ADetailer generation and image stats verification. +- 2026-02-11: Began implementation of mask-aware regression test for ADetailer SDXL noise masking. +- 2026-02-11: Added deterministic unit test that stubs sampling and verifies noise is localized to resized mask region in enhance_detail. +- Important decisions made +- Recurring questions or topics +- Solutions that worked well +- Things to avoid or that didn't work + +## Notes +- 2026-02-11: pytest -q tests/unit/test_adetailer_noise_mask.py passed (4 tests). diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..78cd83aeb46cf7698d244150bdde115e5a20e0ba --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,73 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.10', '3.14'] + fail-fast: false + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Cache pip dependencies + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip-${{ matrix.python-version }}- + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu + pip install "numpy<2.0.0" + pip install pytest pytest-cov + pip install -r requirements.txt + + - name: Run tests + run: | + # Run tests file-by-file for isolation to prevent mock leaks between suites. + # We handle exit code 5 (no tests collected) which happens when a file + # only contains 'slow' or 'gpu' tests that are filtered out. + failed=0 + for f in $(find tests -type f -name "test_*.py"); do + echo "Running tests in $f..." + if pytest -v -m "not gpu and not slow" --tb=short "$f"; then + echo "Successfully ran tests in $f" + else + status=$? + if [ $status -eq 5 ]; then + echo "No tests matching filter in $f (exit code 5), continuing..." + else + echo "Error: tests in $f failed with exit code $status" + failed=1 + fi + fi + done + if [ $failed -ne 0 ]; then + echo "One or more test suites failed." + exit 1 + fi + + - name: Upload coverage report + if: matrix.python-version == '3.10' + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: htmlcov/ + if-no-files-found: ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b759e0f49adbc6877c3e069b5d5866e90638c373 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.pyc +*.pth +*.pt +*.safetensors +*.png +stable_fast-*.whl +.venv +node_modules/ +frontend/node_modules/ +*.log +.history_backups +include/last_seed.txt +include/settings_store.json +docs/ai/ diff --git a/.python-version b/.python-version new file mode 100644 index 0000000000000000000000000000000000000000..e4fba2183587225f216eeada4c78dfab6b2e65f5 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..77ccd77856c3ba8138826af7e6bb26be4b6a0a48 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,218 @@ +FROM node:22-bookworm-slim AS frontend-builder + +WORKDIR /frontend + +COPY frontend/package.json frontend/package-lock.json ./ +RUN npm ci + +COPY frontend/ ./ +RUN npm run build + + +FROM nvidia/cuda:12.8.0-devel-ubuntu22.04 + +ENV DEBIAN_FRONTEND=noninteractive +ENV PYTHONUNBUFFERED=1 +ENV PYTHONDONTWRITEBYTECODE=1 +ENV CUDA_HOME=/usr/local/cuda +ENV PATH=${CUDA_HOME}/bin:${PATH} +ENV LD_LIBRARY_PATH=${CUDA_HOME}/lib64:${LD_LIBRARY_PATH} +ENV TORCH_CUDA_ARCH_LIST="8.0;8.6;8.9;9.0;12.0" + +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + apt-get update && apt-get install -y \ + python3.10 \ + python3.10-dev \ + python3.10-venv \ + python3-pip \ + python3-tk \ + git \ + wget \ + curl \ + build-essential \ + libgl1-mesa-glx \ + libglib2.0-0 \ + libsm6 \ + libxext6 \ + libxrender-dev \ + libgomp1 \ + software-properties-common \ + ninja-build \ + && rm -rf /var/lib/apt/lists/* + +RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1 + +WORKDIR /app + +COPY requirements.txt ./ + +RUN --mount=type=cache,target=/root/.cache/pip python3 -m pip install --upgrade pip +RUN --mount=type=cache,target=/root/.cache/pip python3 -m pip install uv + +RUN --mount=type=cache,target=/root/.cache/uv /bin/sh -c 'set -e; \ + python3 -m uv pip install --system --index-url https://download.pytorch.org/whl/cu128 \ + torch torchvision "triton>=2.1.0"; \ + if echo "${TORCH_CUDA_ARCH_LIST}" | grep -q "12\.0"; then \ + echo "Detected compute capability 12.0 (RTX 50 series). Skipping xformers install."; \ + else \ + python3 -m uv pip install --system xformers; \ + fi' + +RUN --mount=type=cache,target=/root/.cache/uv python3 -m uv pip install --system "numpy<2.0.0" +RUN --mount=type=cache,target=/root/.cache/uv python3 -m uv pip install --system -r requirements.txt + +ARG TORCH_CUDA_ARCH_LIST="8.0;8.6;8.9;9.0;12.0" +ENV TORCH_CUDA_ARCH_LIST=${TORCH_CUDA_ARCH_LIST} + +ARG INSTALL_STABLE_FAST=0 +ENV INSTALL_STABLE_FAST=${INSTALL_STABLE_FAST} + +ARG INSTALL_OLLAMA=0 +ENV INSTALL_OLLAMA=${INSTALL_OLLAMA} + +ARG INSTALL_SAGEATTENTION=0 +ENV INSTALL_SAGEATTENTION=${INSTALL_SAGEATTENTION} + +ARG INSTALL_SPARGEATTN=0 +ENV INSTALL_SPARGEATTN=${INSTALL_SPARGEATTN} + +RUN --mount=type=cache,target=/root/.cache/pip \ + --mount=type=cache,target=/build-cache/stablefast,sharing=locked /bin/sh -c ' \ + if [ "${INSTALL_STABLE_FAST}" = "1" ]; then \ + echo "Installing stable-fast for CUDA architectures: ${TORCH_CUDA_ARCH_LIST}"; \ + export TORCH_CUDA_ARCH_LIST="${TORCH_CUDA_ARCH_LIST}"; \ + export FORCE_CUDA=1; \ + mkdir -p /build-cache/stablefast; \ + python3 -m pip wheel --no-build-isolation --wheel-dir /build-cache/stablefast \ + git+https://github.com/chengzeyi/stable-fast.git@main#egg=stable-fast; \ + python3 -m pip install --no-build-isolation --no-index --find-links /build-cache/stablefast stable-fast; \ + else \ + echo "Skipping stable-fast installation (INSTALL_STABLE_FAST=${INSTALL_STABLE_FAST})"; \ + fi' + +RUN --mount=type=cache,target=/build-cache/ollama,sharing=locked /bin/sh -c ' \ + if [ "${INSTALL_OLLAMA}" = "1" ]; then \ + echo "Installing Ollama and pulling qwen3:0.6b"; \ + mkdir -p /build-cache/ollama; \ + curl -fsSL https://ollama.com/install.sh -o /build-cache/ollama/install.sh; \ + sh /build-cache/ollama/install.sh; \ + export OLLAMA_HOME=/build-cache/ollama; \ + ollama serve >/tmp/ollama.log 2>&1 & \ + OLLAMA_PID=$!; \ + attempts=0; \ + until curl -fsS http://127.0.0.1:11434/api/version >/dev/null 2>&1; do \ + attempts=$((attempts + 1)); \ + if [ ${attempts} -gt 20 ]; then \ + echo "Ollama failed to start"; \ + kill ${OLLAMA_PID} >/dev/null 2>&1 || true; \ + exit 1; \ + fi; \ + sleep 1; \ + done; \ + ollama pull qwen3:0.6b; \ + kill ${OLLAMA_PID} >/dev/null 2>&1 || true; \ + wait ${OLLAMA_PID} 2>/dev/null || true; \ + else \ + echo "Skipping Ollama installation (INSTALL_OLLAMA=${INSTALL_OLLAMA})"; \ + fi' + +COPY . . +COPY --from=frontend-builder /frontend/dist ./frontend/dist + +RUN --mount=type=cache,target=/root/.cache/torch_extensions,sharing=locked \ + --mount=type=cache,target=/build-cache/sageattention,sharing=locked /bin/sh -c ' \ + if [ "${INSTALL_SAGEATTENTION}" = "1" ]; then \ + if [ -d "SageAttention" ]; then \ + echo "Found SageAttention - applying patch"; \ + cd SageAttention; \ + python3 ../docker/patch_sageattention.py; \ + python3 -m pip wheel --no-build-isolation --wheel-dir /build-cache/sageattention .; \ + python3 -m pip install --no-index /build-cache/sageattention/*.whl; \ + cd ..; \ + rm -rf SageAttention/build SageAttention/*.egg-info; \ + else \ + echo "SageAttention directory not found - cloning and applying patch"; \ + git clone --depth 1 https://github.com/thu-ml/SageAttention /tmp/SageAttention; \ + cd /tmp/SageAttention; \ + python3 /app/docker/patch_sageattention.py; \ + python3 -m pip wheel --no-build-isolation --wheel-dir /build-cache/sageattention .; \ + python3 -m pip install --no-index /build-cache/sageattention/*.whl; \ + rm -rf /tmp/SageAttention/build /tmp/SageAttention/*.egg-info; \ + rm -rf /tmp/SageAttention; \ + fi; \ + else \ + echo "Skipping SageAttention installation (INSTALL_SAGEATTENTION=${INSTALL_SAGEATTENTION})"; \ + fi' + +RUN --mount=type=cache,target=/root/.cache/torch_extensions,sharing=locked \ + --mount=type=cache,target=/build-cache/spargeattn,sharing=locked /bin/sh -c ' \ + if [ "${INSTALL_SPARGEATTN}" = "1" ]; then \ + if [ -d "SpargeAttn" ]; then \ + cd SpargeAttn; \ + if echo "${TORCH_CUDA_ARCH_LIST}" | grep -qE "(8\.0|8\.6|8\.7|8\.9|9\.0)"; then \ + echo "Building SpargeAttn for supported architectures: ${TORCH_CUDA_ARCH_LIST}"; \ + python3 -m pip wheel --no-build-isolation --wheel-dir /build-cache/spargeattn .; \ + python3 -m pip install --no-index /build-cache/spargeattn/*.whl; \ + rm -rf build *.egg-info; \ + else \ + echo "Skipping SpargeAttn - architecture ${TORCH_CUDA_ARCH_LIST} not supported (requires 8.0-9.0)"; \ + fi; \ + cd ..; \ + else \ + echo "SpargeAttn directory not found - cloning and attempting build if supported"; \ + git clone --depth 1 https://github.com/thu-ml/SpargeAttn /tmp/SpargeAttn; \ + cd /tmp/SpargeAttn; \ + if echo "${TORCH_CUDA_ARCH_LIST}" | grep -qE "(8\.0|8\.6|8\.7|8\.9|9\.0)"; then \ + echo "Building cloned SpargeAttn for supported architectures: ${TORCH_CUDA_ARCH_LIST}"; \ + python3 -m pip wheel --no-build-isolation --wheel-dir /build-cache/spargeattn .; \ + python3 -m pip install --no-index /build-cache/spargeattn/*.whl; \ + rm -rf build *.egg-info; \ + else \ + echo "Skipping cloned SpargeAttn - architecture ${TORCH_CUDA_ARCH_LIST} not supported (requires 8.0-9.0)"; \ + fi; \ + cd /app; \ + rm -rf /tmp/SpargeAttn; \ + fi; \ + else \ + echo "Skipping SpargeAttn installation (INSTALL_SPARGEATTN=${INSTALL_SPARGEATTN})"; \ + fi' + +RUN mkdir -p ./output/classic \ + ./output/Flux \ + ./output/HiresFix \ + ./output/Img2Img \ + ./output/Adetailer \ + ./include/checkpoints \ + ./include/clip \ + ./include/embeddings \ + ./include/ESRGAN \ + ./include/loras \ + ./include/sd1_tokenizer \ + ./include/text_encoder \ + ./include/unet \ + ./include/vae \ + ./include/vae_approx \ + ./include/yolos + +RUN echo "42" > ./include/last_seed.txt +RUN echo "A beautiful landscape" > ./include/prompt.txt + +EXPOSE 7860 + +ENV PORT=7860 + +HEALTHCHECK --interval=30s --timeout=30s --start-period=60s --retries=3 \ + CMD curl -f http://localhost:${PORT}/health || exit 1 + +CMD if [ "${INSTALL_OLLAMA}" = "1" ]; then \ + echo "Starting Ollama server"; \ + ollama serve >/tmp/ollama_runtime.log 2>&1 & \ + for attempt in $(seq 1 20); do \ + if curl -fsS http://127.0.0.1:11434/api/version >/dev/null 2>&1; then \ + break; \ + fi; \ + sleep 1; \ + done; \ + fi; \ + exec python3 server.py --host 0.0.0.0 --port "${PORT}" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..f288702d2fa16d3cdf0035b15a9fcbc552cd88e7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..98d67abc37e9dec91e1453e252fd197afaf691d6 --- /dev/null +++ b/README.md @@ -0,0 +1,297 @@ +--- +title: LightDiffusion-Next +emoji: 🚀 +colorFrom: blue +colorTo: gray +sdk: gradio +sdk_version: 5.33.2 +app_file: app.py +python_version: 3.10.13 +--- + +
+ +# Say hi to LightDiffusion-Next 👋 + +[![demo platform](https://img.shields.io/badge/Play%20with%20LightDiffusion%21-LightDiffusion%20demo%20platform-lightblue)](https://huggingface.co/spaces/Aatricks/LightDiffusion-Next)  + +**LightDiffusion-Next** is the fastest AI-powered image generation WebUI, combining speed, precision, and flexibility in one cohesive tool. +
+
+ + Logo + + +
+
+ +--- + +As a refactored and improved version of the original [LightDiffusion repository](https://github.com/Aatrick/LightDiffusion), this project enhances usability, maintainability, and functionality while introducing a host of new features to streamline your creative workflows. + + +## Motivation: + +**LightDiffusion** was originally meant to be made in Rust, but due to the lack of support for the Rust language in the AI community, it was made in Python with the goal of being the simplest and fastest AI image generation tool. + +That's when the first version of LightDiffusion was born which only counted [3000 lines of code](https://github.com/LightDiffusion/LightDiffusion-original), only using Pytorch. With time, the [project](https://github.com/Aatrick/LightDiffusion) grew and became more complex, and the need for a refactor was evident. This is where **LightDiffusion-Next** comes in, with a more modular and maintainable codebase, and a plethora of new features and optimizations. + +📚 Learn more in the [official documentation](https://aatricks.github.io/LightDiffusion-Next/) + +For a source-based breakdown of the optimization stack, see the [Implemented Optimizations Report](https://aatricks.github.io/LightDiffusion-Next/implemented-optimizations-report/). + +--- + +## 🌟 Highlights + +![image](https://github.com/user-attachments/assets/b994fe0d-3a2e-44ff-93a4-46919cf865e3) + +**LightDiffusion-Next** offers a powerful suite of tools to cater to creators at every level. At its core, it supports **Text-to-Image** (Txt2Img) and **Image-to-Image** (Img2Img) generation, offering a variety of upscale methods and samplers, to make it easier to create stunning images with minimal effort. + +Advanced users can take advantage of features like **attention syntax**, **Hires-Fix** or **ADetailer**. These tools provide better quality and flexibility for generating complex and high-resolution outputs. + +**LightDiffusion-Next** is fine-tuned for **performance**. Features such as **Xformers** acceleration, **BFloat16** precision support, **WaveSpeed** dynamic caching, **Multi-scale diffusion**, and **Stable-Fast** model compilation (which offers up to a 70% speed boost) ensure smooth and efficient operation, even on demanding workloads. + +--- + +## ✨ Feature Showcase + +Here’s what makes LightDiffusion-Next stand out: + +- **Speed and Efficiency**: + Enjoy industry-leading performance with built-in Xformers, Pytorch, Wavespeed and Stable-Fast optimizations, Multi-scale diffusion, deepcache, AYS (Align Your Steps) scheduler, and automatic prompt caching achieving 30% up to 200% faster speeds compared to the rest of the AI image generation backends in SD1.5 and Flux. + +- **Automatic Detailing**: + Effortlessly enhance faces and body details with AI-driven tools based on the [Impact Pack](https://github.com/ltdrdata/ComfyUI-Impact-Pack). + +- **State Preservation**: + Save and resume your progress with saved states, ensuring seamless transitions between sessions. + +- **Integration-Ready**: + Collaborate and create directly in Discord with [Boubou](https://github.com/Aatrick/Boubou), or preview images dynamically with the optional **TAESD preview mode**. + +- **Image Previewing**: + Get a real-time preview of your generated images with TAESD, allowing for user-friendly and interactive workflows. + +- **Image Upscaling**: + Enhance your images with advanced upscaling options like UltimateSDUpscaling, ensuring high-quality results every time. + +- **Prompt Refinement**: + Use the optional Ollama-powered prompt enhancer (defaults to `qwen3:0.6b`) to refine your prompts and generate more accurate and detailed outputs. + +- **LoRa and Textual Inversion Embeddings**: + Leverage LoRa and textual inversion embeddings for highly customized and nuanced results, adding a new dimension to your creative process. + +- **Low-End Device Support**: + Run LightDiffusion-Next on low-end devices with as little as 2GB of VRAM or even no GPU, ensuring accessibility for all users. + +- **CFG++**: + Uses samplers modified to use CFG++ for better quality results compared to traditional methods. + +- **Newelle Extension**: + LightDiffusion-Next is also available as a backend to the [Newelle LightDiffusion extension](https://github.com/Aatricks/Newelle-Light-Diffusion) permitting to generate images inline during conversations with llms. + +--- + +## ⚡ Performance Benchmarks + +**LightDiffusion-Next** dominates in performance: + +| **Tool** | **Speed (it/s)** | +|------------------------------------|------------------| +| **LightDiffusion with Stable-Fast** | 2.8 | +| **LightDiffusion** | 1.9 | +| **ComfyUI** | 1.4 | +| **SDForge** | 1.3 | +| **SDWebUI** | 0.9 | + +(All benchmarks are based on a 1024x1024 resolution with a batch size of 1 using BFloat16 precision without tweaking installations. Made with a 3060 mobile GPU using SD1.5.) + +With its unmatched speed and efficiency, LightDiffusion-Next sets the benchmark for AI image generation tools. + +--- + +## 🛠 Installation + +> [!NOTE] +> **Platform Support:** LightDiffusion-Next supports NVIDIA GPUs (CUDA), AMD GPUs (ROCm), and Apple Silicon (Metal/MPS). For AMD and Apple Silicon setup instructions, see the [ROCm and Metal/MPS Support Guide](https://aatrick.github.io/LightDiffusion/rocm-metal-support/). + +> [!WARNING] +> **Disclaimer:** On Linux, the fastest way to get started is with the Docker setup below. Windows users often encounter an `EOF` build error when using Docker; if that happens, set up a local virtual environment instead and install SageAttention inside it. + +> [!NOTE] +> You will need to download the [flux vae](https://huggingface.co/black-forest-labs/FLUX.1-schnell/blob/main/ae.safetensors) separately given its gated repo on Huggingface. Drop it in the `/include/vae` folder. + +### Quick Start + +1. Download a release or clone this repository. +2. Run `run.bat` in a terminal. +3. The modern React frontend will launch automatically at `http://localhost:5173` (proxied to the FastAPI backend at `http://localhost:7861`). + +**Recommended Launch Command:** +```bash +# Start both backend and frontend development server +python server.py --frontend +``` + +**Production-style local run:** +```bash +# Serve the built React UI from FastAPI on a single port +python server.py --port 7860 +``` + +**ZeroGPU / Gradio launch:** +```bash +# Launch the Hugging Face ZeroGPU-compatible Gradio UI +python app.py +``` + +### 🌌 Flux Support + +LightDiffusion-Next now features first-class support for **Flux2 Klein**. To get started, you need to download the required model components (Diffusion Model, Text Encoder, and VAE). + +We provide a convenient script to handle this automatically: +```bash +python download_flux.py +``` +This will download approximately 16GB of weights into the `include/` directory. + +### 🤗 ZeroGPU / Gradio Space + +This repository now includes a Gradio `app.py` entrypoint for Hugging Face +**ZeroGPU**. ZeroGPU is only supported for Gradio SDK Spaces, and the +GPU-bound generation function is wrapped with `@spaces.GPU`. + +Recommended defaults for ZeroGPU: +- keep `Keep Models Loaded` disabled +- use 512x512 or 768x768 resolutions +- generate 1 image at a time +- prefer 10-25 steps with `ays` + +### 🐳 Docker Setup + +Run LightDiffusion-Next in a containerized environment with GPU acceleration. +The Docker path remains available for local or dedicated GPU deployments and +serves the built React frontend from the FastAPI backend on port `7860`. + +> [!IMPORTANT] +> Confirm you have Docker Desktop configured with the NVIDIA Container Toolkit and at least 12-16GB of memory. Builds expect an NVIDIA GPU with compute capability 8.0 or higher and CUDA 12.0+ support for SageAttention/SpargeAttn. + +**Quick Start with Docker:** +```bash +# Build and run with docker-compose +docker-compose up --build + +# Or build and run manually +docker build -t lightdiffusion-next . +docker run --gpus all -p 7860:7860 -e PORT=7860 -v ./output:/app/output lightdiffusion-next +``` + +**Custom GPU Architecture (Optional):** +```bash +# For faster builds, specify your GPU architecture (e.g., RTX 5060 = 12.0) +docker-compose build --build-arg TORCH_CUDA_ARCH_LIST="12.0" + +# Default builds for: 8.0 (A100), 8.6 (RTX 30xx), 8.9 (RTX 40xx), 9.0 (H100), 12.0 (RTX 50xx) +``` + +**Built-in Optimizations:** +The Docker image can optionally build the following acceleration paths: +- ✨ **SageAttention** - 15% speedup with INT8 quantization (all supported GPUs) +- 🚀 **SpargeAttn** - 40-60% speedup with sparse attention (compute 8.0-9.0 only) +- ⚡ **Stable-Fast** - Optional UNet compilation for up to 70% faster SD1.5 inference + +Control them through build arguments (defaults shown below): + +```bash +docker-compose build \ + --build-arg TORCH_CUDA_ARCH_LIST="8.0;8.6;8.9;9.0;12.0" \ + --build-arg INSTALL_SAGEATTENTION=0 \ + --build-arg INSTALL_SPARGEATTN=0 \ + --build-arg INSTALL_STABLE_FAST=1 \ + --build-arg INSTALL_OLLAMA=0 +``` + +Set `INSTALL_STABLE_FAST=1` to enable stable-fast, `INSTALL_SAGEATTENTION=1` +or `INSTALL_SPARGEATTN=1` to opt into the heavier attention-kernel builds, and +`INSTALL_OLLAMA=1` to bake in the prompt enhancer runtime. + +> [!NOTE] +> RTX 50 series (compute 12.0) GPUs currently use SageAttention when the SageAttention kernel is installed. SpargeAttn remains limited to earlier supported architectures. + +**Access the Web Interface:** +- **FastAPI + React UI**: `http://localhost:7860` + +**Volume Mounts:** +- `./output:/app/output` - Persist generated images +- `./checkpoints:/app/include/checkpoints` - Store model files +- `./loras:/app/include/loras` - Store LoRA files +- `./embeddings:/app/include/embeddings` - Store embeddings + +### Advanced Setup + +- **Install from Source**: + Install dependencies via: + ```bash + pip install -r requirements.txt + ``` + Add your SD1/1.5 safetensors model to the `checkpoints` directory, then launch the application. + +- **⚡Stable-Fast Optimization**: + Follow [this guide](https://github.com/chengzeyi/stable-fast?tab=readme-ov-file#installation) to enable Stable-Fast mode for optimal performance. + In Docker environments, set `INSTALL_STABLE_FAST=1` to compile it during the image build or `INSTALL_STABLE_FAST=0` (default) to skip. + +- **🚀 SageAttention & SpargeAttn Acceleration**: + Boost inference speed by up to 60% with advanced attention backends: + + **Prerequisites:** + - [CUDA toolkit](https://developer.nvidia.com/cuda-toolkit-archive) installed with version compatible with your PyTorch installation + + **SageAttention (15% speedup, Windows compatible):** + ```bash + cd SageAttention + pip install -e . --no-build-isolation + ``` + + **SpargeAttn (40-60% total speedup, requires WSL2/Linux):** +> [!CAUTION] +> SpargeAttn cannot be built with the default Windows linker. Use WSL2 or a native Linux environment and set the correct `TORCH_CUDA_ARCH_LIST` before installation. + ```bash + # On WSL2 or Linux only (Windows linker has path length limitations) + cd SpargeAttn + export TORCH_CUDA_ARCH_LIST="9.0" # Or your GPU architecture (8.0, 8.6, 8.9, 9.0) + pip install -e . --no-build-isolation + ``` + + **Priority System:** SpargeAttn > SageAttention > PyTorch SDPA + - Both are automatically detected and used when available + - Graceful fallback for unsupported head dimensions + +- **🦙 Prompt Enhancer**: + Turn on the Ollama-backed enhancer to automatically restructure prompts. By default the app targets `qwen3:0.6b`: + ```bash + # Local install + pip install ollama + curl -fsSL https://ollama.com/install.sh | sh + + # Start the Ollama daemon (keep this terminal open) + ollama serve + + # New terminal: pull the default prompt enhancer model + ollama pull qwen3:0.6b + export PROMPT_ENHANCER_MODEL=qwen3:0.6b + ``` + In Docker builds, set `--build-arg INSTALL_OLLAMA=1` (or update `docker-compose.yml`) to install Ollama and pre-pull the model automatically. You can override the runtime model/prefix with the `PROMPT_ENHANCER_MODEL` and `PROMPT_ENHANCER_PREFIX` environment variables. See the [Ollama guide](https://github.com/ollama/ollama?tab=readme-ov-file) for details. + +- **🤖 Discord Integration**: + Set up the Discord bot by following the [Boubou installation guide](https://github.com/Aatrick/Boubou). + +### Third-Party Licenses +- This project distributes builds that depend on third-party open source components. For attribution details and the full license text, refer to `THIRD_PARTY_LICENSES.md`. + +--- + +🎨 Enjoy exploring the powerful features of LightDiffusion-Next! + +> [!TIP] +> ⭐ If this project helps you, please give it a star! It helps others discover it too. diff --git a/THIRD_PARTY_LICENSES.md b/THIRD_PARTY_LICENSES.md new file mode 100644 index 0000000000000000000000000000000000000000..2ea2b1db2f2d4d26e10218b5ea96e81e0ec90bb9 --- /dev/null +++ b/THIRD_PARTY_LICENSES.md @@ -0,0 +1,948 @@ +# Third-Party Notices + +This project depends on the following third-party components. The notices below satisfy the attribution requirements of their respective licenses. + +## SageAttention (thu-ml/SageAttention) +- Source: https://github.com/thu-ml/SageAttention +- License: Apache License 2.0 (see full text below) +- Notes: LightDiffusion-Next applies a build-time patch (`docker/sageattention_setup.patch`) to SageAttention's `setup.py` to honor the `TORCH_CUDA_ARCH_LIST` environment variable during compilation. + +## SpargeAttn (thu-ml/SpargeAttn) +- Source: https://github.com/thu-ml/SpargeAttn +- License: Apache License 2.0 (see full text below) +- Notes: Used as provided, without local source modifications. + +## ComfyUI (comfyanonymous/ComfyUI) +- Source: https://github.com/comfyanonymous/ComfyUI +- License: GNU General Public License v3.0 (full text distributed in the repository root `LICENSE`) +- Notes: Provides the node-graph runtime and execution engine extended by LightDiffusion-Next. + +## ComfyUI Ultimate SD Upscale (ssitu/ComfyUI_UltimateSDUpscale) +- Source: https://github.com/ssitu/ComfyUI_UltimateSDUpscale +- License: GNU General Public License v3.0 (full text distributed in the repository root `LICENSE`) +- Notes: LightDiffusion-Next adapts the Ultimate SD Upscale script to integrate with its sampler interface. + +## ADetailer (Bing-su/adetailer) +- Source: https://github.com/Bing-su/adetailer +- License: GNU Affero General Public License v3.0 (see full text below) +- Notes: Supplies detector-driven post-processing for face, hand, and subject refinements. No local source code changes are applied. + +## Stable Fast (chengzeyi/stable-fast) +- Source: https://github.com/chengzeyi/stable-fast +- License: MIT License (see full text below) +- Notes: Imported as a wheel distribution to enable graph compilation speedups for Stable Diffusion pipelines. + +## ComfyUI-GGUF (city96/comfyui-gguf) +- Source: https://github.com/city96/comfyui-gguf +- License: Apache License 2.0 (see full text below) +- Notes: Provides GGUF model loader nodes used by LightDiffusion-Next without modification. + +## WaveSpeed (ComfyUI-WaveSpeed) +- Source: https://github.com/Fannovel16/ComfyUI-WaveSpeed (original project reference) +- License: MIT License (see full text below) +- Notes: LightDiffusion-Next vendors the WaveSpeed caching utilities as-is for first-block cache optimisations. + +--- + +## Apache License + +``` +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all +other entities that control, are controlled by, or are under common +control with that entity. For the purposes of this definition, +"control" means (i) the power, direct or indirect, to cause the +direction or management of such entity, whether by contract or +otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation +source, and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or +Object form, made available under the License, as indicated by a +copyright notice that is included in or attached to the work +(an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object +form, that is based on (or derived from) the Work and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. For the purposes +of this License, Derivative Works shall not include works that remain +separable from, or merely link (or bind by name) to the interfaces of, +the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including +the original version of the Work and any modifications or additions +to that Work or Derivative Works thereof, that is intentionally +submitted to Licensor for inclusion in the Work by the copyright owner +or by an individual or Legal Entity authorized to submit on behalf of +the copyright owner. For the purposes of this definition, "submitted" +means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, +and issue tracking systems that are managed by, or on behalf of, the +Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise +designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work, +where such license applies only to those patent claims licensable +by such Contributor that are necessarily infringed by their +Contribution(s) alone or by combination of their Contribution(s) +with the Work to which such Contribution(s) was submitted. If You +institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work +or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses +granted to You under this License for that Work shall terminate +as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You +meet the following conditions: + +(a) You must give any other recipients of the Work or +Derivative Works a copy of this License; and + +(b) You must cause any modified files to carry prominent notices +stating that You changed the files; and + +(c) You must retain, in the Source form of any Derivative Works +that You distribute, all copyright, patent, trademark, and +attribution notices from the Source form of the Work, +excluding those notices that do not pertain to any part of +the Derivative Works; and + +(d) If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must +include a readable copy of the attribution notices contained +within such NOTICE file, excluding those notices that do not +pertain to any part of the Derivative Works, in at least one +of the following places: within a NOTICE text file distributed +as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, +within a display generated by the Derivative Works, if and +wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and +do not modify the License. You may add Your own attribution +notices within Derivative Works that You distribute, alongside +or as an addendum to the NOTICE text from the Work, provided +that such additional attribution notices cannot be construed +as modifying the License. + +You may add Your own copyright statement to Your modifications and +may provide additional or different license terms and conditions +for use, reproduction, or distribution of Your modifications, or +for any such Derivative Works as a whole, provided Your use, +reproduction, and distribution of the Work otherwise complies with +the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following +boilerplate notice, with the fields enclosed by brackets "[]" +replaced with your own identifying information. (Don't include +the brackets!) The text should be enclosed in the appropriate +comment syntax for the file format. We also recommend that a +file or class name and description of purpose be included on the +same "printed page" as the copyright notice for easier +identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +``` + +--- + +## MIT License (Stable Fast) + +``` +MIT License + +Copyright (c) 2023 C + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + +--- + +## GNU Affero General Public License v3.0 (ADetailer) + +``` + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further + restrictions" within the meaning of section 10. If the Program as you + received it, or any part of it, contains a notice stating that it is + governed by this License along with a term that is a further + restriction, you may remove that term. If a license document contains + a further restriction but permits relicensing or conveying under this + License, you may add to a covered work material governed by the terms + of that license document, provided that the further restriction does + not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you + must place, in the relevant source files, a statement of the + additional terms that apply to those files, or a notice indicating + where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the + form of a separately written license, or stated as exceptions; + the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly + provided under this License. Any attempt otherwise to propagate or + modify it is void, and will automatically terminate your rights under + this License (including any patent licenses granted under the third + paragraph of section 11). + + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the copyright + holder fails to notify you of the violation by some reasonable means + prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from that + copyright holder, and you cure the violation prior to 30 days after + your receipt of the notice. + + Termination of your rights under this section does not terminate the + licenses of parties who have received copies or rights from you under + this License. If your rights have been terminated and not permanently + reinstated, you do not qualify to receive new licenses for the same + material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or + run a copy of the Program. Ancillary propagation of a covered work + occurring solely as a consequence of using peer-to-peer transmission + to receive a copy likewise does not require acceptance. However, + nothing other than this License grants you permission to propagate or + modify any covered work. These actions infringe copyright if you do + not accept this License. Therefore, by modifying or propagating a + covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically + receives a license from the original licensors, to run, modify and + propagate that work, subject to this License. You are not responsible + for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an + organization, or substantially all assets of one, or subdividing an + organization, or merging organizations. If propagation of a covered + work results from an entity transaction, each party to that + transaction who receives a copy of the work also receives whatever + licenses to the work the party's predecessor in interest had or could + give under the previous paragraph, plus a right to possession of the + Corresponding Source of the work from the predecessor in interest, if + the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the + rights granted or affirmed under this License. For example, you may + not impose a license fee, royalty, or other charge for exercise of + rights granted under this License, and you may not initiate litigation + (including a cross-claim or counterclaim in a lawsuit) alleging that + any patent claim is infringed by making, using, selling, offering for + sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this + License of the Program or a work on which the Program is based. The + work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims + owned or controlled by the contributor, whether already acquired or + hereafter acquired, that would be infringed by some manner, permitted + by this License, of making, using, or selling its contributor version, + but do not include claims that would be infringed only as a + consequence of further modification of the contributor version. For + purposes of this definition, "control" includes the right to grant + patent sublicenses in a manner consistent with the requirements of + this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free + patent license under the contributor's essential patent claims, to + make, use, sell, offer for sale, import and otherwise run, modify and + propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express + agreement or commitment, however denominated, not to enforce a patent + (such as an express permission to practice a patent or covenant not to + sue for patent infringement). To "grant" such a patent license to a + party means to make such an agreement or commitment not to enforce a + patent against the party. + + If you convey a covered work, knowingly relying on a patent license, + and the Corresponding Source of the work is not available for anyone + to copy, free of charge and under the terms of this License, through a + publicly available network server or other readily accessible means, + then you must either (1) cause the Corresponding Source to be so + available, or (2) arrange to deprive yourself of the benefit of the + patent license for this particular work, or (3) arrange, in a manner + consistent with the requirements of this License, to extend the patent + license to downstream recipients. "Knowingly relying" means you have + actual knowledge that, but for the patent license, your conveying the + covered work in a country, or your recipient's use of the covered work + in a country, would infringe one or more identifiable patents in that + country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or + arrangement, you convey, or propagate by procuring conveyance of, a + covered work, and grant a patent license to some of the parties + receiving the covered work authorizing them to use, propagate, modify + or convey a specific copy of the covered work, then the patent license + you grant is automatically extended to all recipients of the covered + work and works based on it. + + A patent license is "discriminatory" if it does not include within + the scope of its coverage, prohibits the exercise of, or is + conditioned on the non-exercise of one or more of the rights that are + specifically granted under this License. You may not convey a covered + work if you are a party to an arrangement with a third party that is + in the business of distributing software, under which you make payment + to the third party based on the extent of your activity of conveying + the work, and under which the third party grants, to any of the + parties who would receive the covered work from you, a discriminatory + patent license (a) in connection with copies of the covered work + conveyed by you (or copies made from those copies), or (b) primarily + for and in connection with specific products or compilations that + contain the covered work, unless you entered into that arrangement, + or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting + any implied license or other defenses to infringement that may + otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot convey a + covered work so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you may + not convey it at all. For example, if you agree to terms that obligate you + to collect a royalty for further conveying from those to whom you convey + the Program, the only way you could satisfy both those terms and this + License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the + Program, your modified version must prominently offer all users + interacting with it remotely through a computer network (if your version + supports such interaction) an opportunity to receive the Corresponding + Source of your version by providing access to the Corresponding Source + from a network server at no charge, through some standard or customary + means of facilitating copying of software. This Corresponding Source + shall include the Corresponding Source for any work covered by version 3 + of the GNU General Public License that is incorporated pursuant to the + following paragraph. + + Notwithstanding any other provision of this License, you have + permission to link or combine any covered work with a work licensed + under version 3 of the GNU General Public License into a single + combined work, and to convey the resulting work. The terms of this + License will continue to apply to the part which is the covered work, + but the work with which it is combined will remain governed by version + 3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of + the GNU Affero General Public License from time to time. Such new versions + will be similar in spirit to the present version, but may differ in detail to + address new problems or concerns. + + Each version is given a distinguishing version number. If the + Program specifies that a certain numbered version of the GNU Affero General + Public License "or any later version" applies to it, you have the + option of following the terms and conditions either of that numbered + version or of any later version published by the Free Software + Foundation. If the Program does not specify a version number of the + GNU Affero General Public License, you may choose any version ever published + by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future + versions of the GNU Affero General Public License can be used, that proxy's + public statement of acceptance of a version permanently authorizes you + to choose that version for the Program. + + Later license versions may give you additional or different + permissions. However, no additional obligations are imposed on any + author or copyright holder as a result of your choosing to follow a + later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY + APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT + HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY + OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM + IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF + ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS + THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY + GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE + USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD + PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), + EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF + SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided + above cannot be given local legal effect according to their terms, + reviewing courts shall apply local law that most closely approximates + an absolute waiver of all civil liability in connection with the + Program, unless a warranty or assumption of liability accompanies a + copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + state the exclusion of warranty; and each file should have at least + the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer + network, you should also make sure that it provides a way for users to + get its source. For example, if your program is a web application, its + interface could display a "Source" link that leads users to an archive + of the code. There are many ways you could offer source, and different + solutions will be better for different programs; see section 13 for the + specific requirements. + + You should also get your employer (if you work as a programmer) or school, + if any, to sign a "copyright disclaimer" for the program, if necessary. + For more information on this, and how to apply and follow the GNU AGPL, see + . + + ``` diff --git a/app.py b/app.py new file mode 100644 index 0000000000000000000000000000000000000000..e0d305b42080070ec4048f8687a4ba3bf2f80e5d --- /dev/null +++ b/app.py @@ -0,0 +1,367 @@ +from __future__ import annotations + +import glob +import os +import time +import uuid +from typing import Any, Optional + +import gradio as gr +import spaces +from PIL import Image + +from src.Core.Models.ModelFactory import list_available_models +from src.Device.ModelCache import get_model_cache +from src.user import app_instance +from src.user.pipeline import pipeline + + +SCHEDULER_CHOICES = [ + "ays", + "ays_sd15", + "ays_sdxl", + "karras", + "normal", + "simple", + "beta", +] + +SAMPLER_CHOICES = [ + "dpmpp_sde_cfgpp", + "dpmpp_2m_cfgpp", + "euler", + "euler_ancestral", + "dpmpp_sde", + "dpmpp_2m", + "euler_cfgpp", + "euler_ancestral_cfgpp", +] + + +def _list_model_mapping() -> list[tuple[str, str]]: + return list_available_models(return_mapping=True) + + +def _model_choices() -> list[str]: + return [name for name, _ in _list_model_mapping()] + + +def _resolve_model_path(display_name: Optional[str]) -> Optional[str]: + if not display_name: + return None + + for name, path in _list_model_mapping(): + if name == display_name: + return path + return None + + +def _load_recent_images( + prefix: Optional[str] = None, + started_at: Optional[float] = None, + limit: int = 12, +) -> list[Image.Image]: + files: list[str] = [] + for ext in ("*.png", "*.jpg", "*.jpeg", "*.webp"): + files.extend(glob.glob(os.path.join(".", "output", "**", ext), recursive=True)) + + filtered: list[str] = [] + for path in files: + basename = os.path.basename(path) + if prefix and prefix not in basename: + continue + if started_at is not None: + try: + if os.path.getmtime(path) < (started_at - 1.0): + continue + except OSError: + continue + filtered.append(path) + + filtered.sort(key=lambda p: os.path.getmtime(p), reverse=True) + + images: list[Image.Image] = [] + for path in filtered[:limit]: + try: + with Image.open(path) as img: + images.append(img.copy()) + except Exception: + continue + return images + + +def _refresh_history() -> tuple[list[Image.Image], str]: + images = _load_recent_images(limit=48) + if not images: + return [], "No generated images found yet." + return images, f"Loaded {len(images)} recent images from `output/`." + + +def _interrupt_generation() -> str: + app_instance.app.request_interrupt() + return "Interrupt requested. The current generation will stop at the next safe check." + + +@spaces.GPU(duration=240) +def _run_generation( + prompt: str, + negative_prompt: str, + width: int, + height: int, + num_images: int, + batch_size: int, + scheduler: str, + sampler: str, + steps: int, + guidance_scale: float, + model_name: Optional[str], + hires_fix: bool, + adetailer: bool, + enhance_prompt: bool, + img2img_enabled: bool, + img2img_image: Optional[str], + img2img_denoise: float, + stable_fast: bool, + reuse_seed: bool, + enable_multiscale: bool, + multiscale_intermittent: bool, + multiscale_factor: float, + multiscale_fullres_start: int, + multiscale_fullres_end: int, + keep_models_loaded: bool, + progress: gr.Progress = gr.Progress(track_tqdm=False), +) -> tuple[list[Image.Image], str, dict[str, Any], list[Image.Image]]: + if not prompt.strip(): + raise gr.Error("Prompt is required.") + + if img2img_enabled and not img2img_image: + raise gr.Error("Upload an input image or disable Img2Img.") + + request_prefix = f"LD-GRADIO-{uuid.uuid4().hex[:8]}" + started_at = time.time() + + app = app_instance.app + app.clear_interrupt() + app.cleanup_all_previews() + app.previewer_var.set(True) + + try: + try: + get_model_cache().set_keep_models_loaded(bool(keep_models_loaded)) + except Exception: + pass + + model_path = _resolve_model_path(model_name) + + def _progress_callback(args: dict[str, Any]) -> None: + step = int(args.get("i", 0)) + total = int(args.get("total_steps", steps)) + if total > 0: + progress( + min((step + 1) / total, 1.0), + desc=f"Sampling step {step + 1}/{total}", + ) + + progress(0, desc="Preparing generation") + + result = pipeline( + prompt=prompt, + negative_prompt=negative_prompt, + w=int(width), + h=int(height), + number=int(num_images), + batch=int(batch_size), + scheduler=scheduler, + sampler=sampler, + steps=int(steps), + cfg_scale=float(guidance_scale), + hires_fix=bool(hires_fix), + adetailer=bool(adetailer), + enhance_prompt=bool(enhance_prompt), + img2img=bool(img2img_enabled), + img2img_image=img2img_image if img2img_enabled else None, + img2img_denoise=float(img2img_denoise), + stable_fast=bool(stable_fast), + reuse_seed=bool(reuse_seed), + autohdr=True, + realistic_model=False, + model_path=model_path, + enable_multiscale=bool(enable_multiscale), + multiscale_intermittent_fullres=bool(multiscale_intermittent), + multiscale_factor=float(multiscale_factor), + multiscale_fullres_start=int(multiscale_fullres_start), + multiscale_fullres_end=int(multiscale_fullres_end), + request_filename_prefix=request_prefix, + callback=_progress_callback, + ) + + progress(1, desc="Generation complete") + + final_images = _load_recent_images( + prefix=request_prefix, + started_at=started_at, + limit=max(1, int(num_images)), + ) + if not final_images and adetailer: + final_images = _load_recent_images( + started_at=started_at, + limit=max(1, int(num_images)), + ) + + preview_images = list(app.preview_images[:4]) if app.preview_images else [] + + if not final_images: + raise gr.Error("Generation completed but no output images were found in `output/`.") + + used_prompt = result.get("used_prompt", prompt) if isinstance(result, dict) else prompt + metadata = { + "request_prefix": request_prefix, + "model_name": model_name or "auto/default", + "used_prompt": used_prompt, + "enhancement_applied": bool(result.get("enhancement_applied")) if isinstance(result, dict) else False, + "img2img_enabled": bool(img2img_enabled), + "adetailer": bool(adetailer), + "hires_fix": bool(hires_fix), + } + status = f"Generated {len(final_images)} image(s) using `{sampler}` + `{scheduler}`." + return final_images, status, metadata, preview_images + finally: + app.clear_interrupt() + + +def _build_demo() -> gr.Blocks: + default_models = _model_choices() + default_model = default_models[0] if default_models else None + + with gr.Blocks(title="LightDiffusion-Next ZeroGPU") as demo: + gr.Markdown( + """ + # LightDiffusion-Next + ZeroGPU-compatible Gradio UI. The generation function is wrapped with `@spaces.GPU` + so Hugging Face can allocate a GPU only while inference is running. + """ + ) + + with gr.Row(): + with gr.Column(scale=2): + prompt = gr.Textbox(label="Prompt", lines=5, placeholder="Describe the image you want to generate") + negative_prompt = gr.Textbox( + label="Negative Prompt", + lines=3, + value="(worst quality, low quality:1.4), (zombie, sketch, interlocked fingers, comic), (embedding:EasyNegative), (embedding:badhandv4)", + ) + + with gr.Row(): + width = gr.Slider(256, 1536, value=512, step=64, label="Width") + height = gr.Slider(256, 1536, value=512, step=64, label="Height") + + with gr.Row(): + num_images = gr.Slider(1, 4, value=1, step=1, label="Images") + batch_size = gr.Slider(1, 4, value=1, step=1, label="Batch Size") + + with gr.Row(): + scheduler = gr.Dropdown(SCHEDULER_CHOICES, value="ays", label="Scheduler") + sampler = gr.Dropdown(SAMPLER_CHOICES, value="dpmpp_sde_cfgpp", label="Sampler") + + with gr.Row(): + steps = gr.Slider(1, 50, value=20, step=1, label="Steps") + guidance_scale = gr.Slider(1.0, 15.0, value=7.0, step=0.1, label="CFG") + + model_name = gr.Dropdown( + choices=default_models, + value=default_model, + allow_custom_value=False, + label="Model", + ) + + with gr.Accordion("Advanced", open=False): + with gr.Row(): + hires_fix = gr.Checkbox(label="HiresFix", value=False) + adetailer = gr.Checkbox(label="ADetailer", value=False) + enhance_prompt = gr.Checkbox(label="Enhance Prompt", value=False) + stable_fast = gr.Checkbox(label="Stable-Fast", value=False) + with gr.Row(): + reuse_seed = gr.Checkbox(label="Reuse Last Seed", value=False) + enable_multiscale = gr.Checkbox(label="Multiscale", value=False) + multiscale_intermittent = gr.Checkbox(label="Intermittent Fullres", value=True) + keep_models_loaded = gr.Checkbox(label="Keep Models Loaded", value=False) + with gr.Row(): + multiscale_factor = gr.Slider(0.25, 1.0, value=0.5, step=0.05, label="Multiscale Factor") + multiscale_fullres_start = gr.Slider(1, 20, value=10, step=1, label="Fullres Start") + multiscale_fullres_end = gr.Slider(1, 20, value=8, step=1, label="Fullres End") + + with gr.Accordion("Img2Img", open=False): + img2img_enabled = gr.Checkbox(label="Enable Img2Img", value=False) + img2img_image = gr.Image(label="Input Image", type="filepath") + img2img_denoise = gr.Slider(0.0, 1.0, value=0.75, step=0.01, label="Denoise Strength") + + with gr.Row(): + generate_button = gr.Button("Generate", variant="primary") + interrupt_button = gr.Button("Interrupt", variant="stop") + refresh_models_button = gr.Button("Refresh Models") + + with gr.Column(scale=3): + status = gr.Markdown("Ready.") + gallery = gr.Gallery(label="Generated Images", columns=2, height="auto") + metadata = gr.JSON(label="Generation Metadata") + preview_gallery = gr.Gallery(label="Last Preview Frames", columns=4, height="auto") + + with gr.Tab("History"): + history_status = gr.Markdown("No generated images loaded yet.") + history_gallery = gr.Gallery(label="Recent Output Images", columns=4, height="auto") + refresh_history = gr.Button("Refresh History") + + refresh_models_button.click( + fn=lambda: gr.update( + choices=_model_choices(), + value=(_model_choices()[0] if _model_choices() else None), + ), + outputs=model_name, + queue=False, + ) + + interrupt_button.click(_interrupt_generation, outputs=status, queue=False) + refresh_history.click(_refresh_history, outputs=[history_gallery, history_status], queue=False) + demo.load(_refresh_history, outputs=[history_gallery, history_status], queue=False) + + generate_button.click( + _run_generation, + inputs=[ + prompt, + negative_prompt, + width, + height, + num_images, + batch_size, + scheduler, + sampler, + steps, + guidance_scale, + model_name, + hires_fix, + adetailer, + enhance_prompt, + img2img_enabled, + img2img_image, + img2img_denoise, + stable_fast, + reuse_seed, + enable_multiscale, + multiscale_intermittent, + multiscale_factor, + multiscale_fullres_start, + multiscale_fullres_end, + keep_models_loaded, + ], + outputs=[gallery, status, metadata, preview_gallery], + ) + + return demo + + +demo = _build_demo() +demo.queue(default_concurrency_limit=1) + + +if __name__ == "__main__": + demo.launch() diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..079115daeb1dfb258237c6c3b2998833710712a1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,41 @@ +services: + lightdiffusion: + build: + context: . + dockerfile: Dockerfile + args: + # Specify target GPU architectures for CUDA extension builds + # 8.0: A100, 8.6: RTX 30xx, 8.9: RTX 40xx, 9.0: H100, 12.0: RTX 50xx (Blackwell) + # Customize based on your GPU: TORCH_CUDA_ARCH_LIST: "12.0" for RTX 50xx only + TORCH_CUDA_ARCH_LIST: "8.0;8.6;8.9;9.0;12.0" + INSTALL_STABLE_FAST: "0" + INSTALL_OLLAMA: "0" + INSTALL_SAGEATTENTION: "0" + INSTALL_SPARGEATTN: "0" + ports: + - "7860:7860" # FastAPI backend serving the built React UI + volumes: + # Mount output directory to persist generated images + - ./output:/app/output + # Mount checkpoints directory for model files + - ./include/checkpoints:/app/include/checkpoints + # Mount other model directories + - ./include/loras:/app/include/loras + - ./include/embeddings:/app/include/embeddings + - ./include/ESRGAN:/app/include/ESRGAN + - ./include/yolos:/app/include/yolos + environment: + - PORT=7860 + - CUDA_VISIBLE_DEVICES=0 + - CUDA_HOME=/usr/local/cuda + - PROMPT_ENHANCER_MODEL=qwen3:0.6b + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: 1 + capabilities: [ gpu ] + restart: unless-stopped + stdin_open: true + tty: true diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000000000000000000000000000000000000..05b0b521f08ccd55a72ca3298eef2b76cceecb6a --- /dev/null +++ b/docker/README.md @@ -0,0 +1,46 @@ +# Docker Build Scripts + +This directory contains helper scripts used during the Docker image build process. + +## Files + +### patch_sageattention.py +**Purpose**: Patches the SageAttention setup.py to support building without GPU present. + +**What it does**: +- Adds support for the `TORCH_CUDA_ARCH_LIST` environment variable to SageAttention +- Allows specifying target GPU architectures via environment variable +- Enables building Docker images on machines without NVIDIA GPUs + +**Usage** (automatically called during Docker build): +```bash +cd SageAttention +python3 ../docker/patch_sageattention.py +``` + +**Why it's needed**: +SageAttention's original setup.py tries to detect GPU hardware during build time using `torch.cuda.device_count()`. This fails in Docker builds because: +1. Docker builds don't have GPU access by default (even with `--gpus all`) +2. GPU access during build is not guaranteed across all Docker configurations +3. Build machines may not have the same GPU as the target runtime machine + +The patch adds a check for `TORCH_CUDA_ARCH_LIST` environment variable before attempting hardware detection, allowing explicit specification of target architectures. + +### sageattention_setup.patch (not used) +Legacy patch file - kept for reference. The Python script approach is preferred. + +## How the Build Process Works + +1. **Environment Setup**: `TORCH_CUDA_ARCH_LIST` is set in Dockerfile via ARG/ENV +2. **Patch Application**: `patch_sageattention.py` modifies SageAttention's setup.py +3. **Extension Build**: Modified setup.py reads `TORCH_CUDA_ARCH_LIST` and compiles for specified architectures +4. **SpargeAttn Build**: Already supports `TORCH_CUDA_ARCH_LIST` natively, no patch needed + +## Maintenance + +If SageAttention is updated, one may need to: +1. Check if the patch still applies correctly +2. Update the target line in `patch_sageattention.py` if the setup.py structure changes +3. Test the build process with the new version + +The patch is designed to be non-intrusive and should work across most SageAttention versions that follow the same setup.py structure. diff --git a/docker/patch_sageattention.py b/docker/patch_sageattention.py new file mode 100644 index 0000000000000000000000000000000000000000..15edb2801fd7a62b39fbc3ecd471c5a61f0b144a --- /dev/null +++ b/docker/patch_sageattention.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +""" +Patch for SageAttention setup.py to support TORCH_CUDA_ARCH_LIST environment variable. +This allows building without GPUs present during build time. +""" + +import sys + +setup_py_path = "setup.py" + +# Read the original setup.py +with open(setup_py_path, 'r') as f: + content = f.read() + +# Find the line where compute_capabilities is initialized +target_line = "compute_capabilities = set()" + +if target_line not in content: + print("ERROR: Could not find target line in setup.py") + sys.exit(1) + +# Add our patch right after compute_capabilities initialization +patch_code = ''' +# Check for TORCH_CUDA_ARCH_LIST environment variable first (Docker build support) +env_arch_list = os.environ.get("TORCH_CUDA_ARCH_LIST", None) +if env_arch_list: + print(f"Using TORCH_CUDA_ARCH_LIST from environment: {env_arch_list}") + arch_list = env_arch_list.replace(" ", ";").split(";") + for arch in arch_list: + arch = arch.strip() + if not arch: + continue + if arch.endswith("+PTX"): + arch = arch[:-4].strip() + if arch: + compute_capabilities.add(arch) +''' + +# Insert the patch +content = content.replace( + target_line, + target_line + patch_code +) + +# Write back +with open(setup_py_path, 'w') as f: + f.write(content) + +print("✓ Successfully patched setup.py to support TORCH_CUDA_ARCH_LIST") diff --git a/docker/sageattention_setup.patch b/docker/sageattention_setup.patch new file mode 100644 index 0000000000000000000000000000000000000000..b74ca5f463388cf8824c31a6cce3d3eab73f0c99 --- /dev/null +++ b/docker/sageattention_setup.patch @@ -0,0 +1,24 @@ +--- setup.py.orig 2024-10-02 00:00:00.000000000 +0000 ++++ setup.py 2024-10-02 00:00:00.000000000 +0000 +@@ -66,6 +66,17 @@ + nvcc_cuda_version = parse(output[release_idx].split(",")[0]) + return nvcc_cuda_version + ++# Check for TORCH_CUDA_ARCH_LIST environment variable first ++import os ++env_arch_list = os.environ.get("TORCH_CUDA_ARCH_LIST", None) ++if env_arch_list: ++ print(f"Using TORCH_CUDA_ARCH_LIST from environment: {env_arch_list}") ++ arch_list = env_arch_list.replace(" ", ";").split(";") ++ for arch in arch_list: ++ arch = arch.strip() ++ if not arch: ++ continue ++ if arch.endswith("+PTX"): ++ arch = arch[:-4].strip() ++ if arch: ++ compute_capabilities.add(arch) ++ + # Iterate over all GPUs on the current machine. Also you can modify this part to specify the architecture if you want to build for specific GPU architectures. + compute_capabilities = set() + device_count = torch.cuda.device_count() diff --git a/docs/advanced-cfg-optimizations.md b/docs/advanced-cfg-optimizations.md new file mode 100644 index 0000000000000000000000000000000000000000..93ed16881f796e6f29e93197610690e1e0d32288 --- /dev/null +++ b/docs/advanced-cfg-optimizations.md @@ -0,0 +1,262 @@ +# Advanced CFG Optimizations + +## Overview + +This document describes three advanced optimizations for Classifier-Free Guidance (CFG) that improve both quality and performance in LightDiffusion-Next: + +1. **Batched CFG Computation** - Speed optimization +2. **Dynamic CFG Rescaling** - Quality optimization +3. **Adaptive Noise Scheduling** - Quality & speed optimization + +## 1. Batched CFG Computation + +### What It Does + +Instead of running two separate forward passes for conditional and unconditional predictions, this optimization can combine them into a single batched forward pass. + +**Before:** +```python +# Two separate forward passes +cond_pred = model(x, timestep, cond) # Pass 1 +uncond_pred = model(x, timestep, uncond) # Pass 2 +result = uncond_pred + cfg_scale * (cond_pred - uncond_pred) +``` + +**After:** +```python +# Single batched forward pass +both_preds = model(x, timestep, [cond, uncond]) # Single pass +cond_pred, uncond_pred = both_preds[0], both_preds[1] +result = uncond_pred + cfg_scale * (cond_pred - uncond_pred) +``` + +### Performance Impact + +- **Speed**: ~1.8-2x faster CFG computation +- **Memory**: Same or slightly less (batch processing) +- **Quality**: Identical to baseline + +### Usage + +```python +from src.sample import sampling + +samples = sampling.sample1( + model=model, + noise=noise, + steps=20, + cfg=7.5, + # ... other params ... + batched_cfg=True, # Joint cond/uncond batching (default: True) +) +``` + +In the current implementation, the heavy lifting still happens in the central conditioning packing path. `batched_cfg` controls whether conditional and unconditional branches are packed together into the same forward pass when possible. Conditioning chunks within each branch are still packed by the shared batching logic. + +### When to Use + +- **Usually recommended** - This reduces duplicate cond/uncond forward passes when memory allows +- Particularly beneficial for high-resolution images or batch generation +- Compatible with all samplers and schedulers + +--- + +## 2. Dynamic CFG Rescaling + +### What It Does + +Dynamically adjusts the CFG scale based on prediction statistics to prevent over-saturation while maintaining prompt adherence. + +### The Problem + +High CFG values (7-12) improve prompt following but can cause: +- Over-saturated colors +- Over-sharpened edges ("halo effect") +- Loss of fine details +- Unnatural, "CG-like" appearance + +### The Solution + +Dynamic CFG rescaling analyzes the guidance vector (difference between conditional and unconditional predictions) and adjusts the CFG scale to keep it within an optimal range. + +**Two Methods:** + +#### Variance Method (Recommended) +```python +guidance_std = std(cond_pred - uncond_pred) +adjusted_cfg = cfg_scale * (target_scale / (1 + guidance_std)) +``` + +Best for: General use, prevents over-saturation + +#### Range Method +```python +guidance_range = percentile(guidance, 95) - percentile(guidance, 5) +adjusted_cfg = cfg_scale * (target_scale / guidance_range) +``` + +Best for: Extreme cases, outlier filtering + +### Performance Impact + +- **Speed**: Minimal overhead (~2-5%) +- **Quality**: Improved color balance, reduced artifacts +- **Prompt Adherence**: Maintained or improved + +### Usage + +```python +samples = sampling.sample1( + model=model, + # ... other params ... + dynamic_cfg_rescaling=True, # Enable dynamic rescaling + dynamic_cfg_method="variance", # Method: "variance" or "range" + dynamic_cfg_percentile=95, # Percentile for range method + dynamic_cfg_target_scale=1.0, # Target normalization scale +) +``` + +### When to Use + +- High CFG values (>7.5) +- Detailed prompts that might cause over-saturation +- Photorealistic generations +- Portraits and faces + +### When to Avoid + +- Very low CFG (<3.0) - minimal benefit +- Artistic/stylized generations where saturation is desired +- When using CFG-free sampling (already handles this differently) + +--- + +## 3. Adaptive Noise Scheduling + +### What It Does + +Dynamically adjusts the noise schedule based on content complexity during generation. + +### The Problem + +Traditional fixed noise schedules apply the same denoising steps to all regions: +- Complex scenes (detailed textures) may need more steps in certain regions +- Simple scenes (smooth gradients) can use fewer steps +- This wastes computation or undersamples complexity + +### The Solution + +Analyzes the complexity of intermediate predictions and adjusts subsequent noise levels accordingly. + +**Two Methods:** + +#### Complexity Method (Recommended) +```python +complexity = variance(denoised, spatial_dims) +# High variance = complex details = maintain fine noise steps +# Low variance = simple areas = can skip intermediate steps +``` + +Best for: General content-aware optimization + +#### Attention Method +```python +complexity = mean(|gradient(denoised)|) +# High gradients = edges/details = need more precision +# Low gradients = smooth areas = can denoise faster +``` + +Best for: Edge-focused content (architecture, technical drawings) + +### Performance Impact + +- **Speed**: 10-20% faster for simple scenes, same for complex +- **Quality**: Adaptive - maintains quality where needed +- **Prompt Adherence**: Unchanged + +### Usage + +```python +samples = sampling.sample1( + model=model, + # ... other params ... + adaptive_noise_enabled=True, # Enable adaptive scheduling + adaptive_noise_method="complexity", # Method: "complexity" or "attention" +) +``` + +### When to Use + +- Mixed complexity scenes (e.g., detailed subject + simple background) +- Long sampling runs (50+ steps) - more opportunity to optimize +- Batch generation with varying prompt complexity + +### When to Avoid + +- Very short sampling runs (<10 steps) - overhead > benefit +- Uniformly complex scenes - no simplification possible +- When exact step-by-step reproducibility is critical + +--- + +## Combining Optimizations + +All three optimizations can be used together: + +```python +samples = sampling.sample1( + model=model, + noise=noise, + steps=20, + cfg=7.5, + sampler_name="dpmpp_sde_cfgpp", + scheduler="ays", + positive=positive_cond, + negative=negative_cond, + latent_image=latent, + # All optimizations enabled + batched_cfg=True, + dynamic_cfg_rescaling=True, + dynamic_cfg_method="variance", + dynamic_cfg_target_scale=1.0, + adaptive_noise_enabled=True, + adaptive_noise_method="complexity", +) +``` + +**Expected Results:** +- Better color balance and detail preservation +- Reduced over-saturation artifacts +- Maintained or improved prompt adherence + +## Troubleshooting + +### Batched CFG Issues + +**Problem**: Memory errors with batched CFG +**Solution**: System may not have enough VRAM for joint cond/uncond batching. Disable it with `batched_cfg=False`, which keeps the conditioning path active but runs the two branches separately. + +### Dynamic CFG Issues + +**Problem**: Images too flat/desaturated +**Solution**: Increase `dynamic_cfg_target_scale` (try 1.5 or 2.0) + +**Problem**: Still over-saturated +**Solution**: Switch to `dynamic_cfg_method="range"` and lower `dynamic_cfg_percentile` + +### Adaptive Noise Issues + +**Problem**: Inconsistent results +**Solution**: Adaptive scheduling makes slight changes based on content. Disable for exact reproducibility. + +**Problem**: No speed improvement +**Solution**: Works best with simple scenes. Complex scenes won't see speedup (but won't be slower either). + +--- + +## Credits + +Implemented for LightDiffusion-Next by combining insights from: +- CFG++ dynamic rescaling techniques +- ComfyUI batched computation patterns +- Stable Diffusion WebUI adaptive scheduling diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000000000000000000000000000000000000..71f6fbc55b9d85c240a435deb96ea3838233db91 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,152 @@ +# REST API & Automation (Quick Reference) + +LightDiffusion-Next ships with a FastAPI service (`server.py`) that sits in front of the shared pipeline. It batches compatible requests, streams telemetry and exposes health probes so you can plug the system into automation workflows, bots or orchestrators. + +## Common endpoints + +| Method | Path | Description | +| --- | --- | --- | +| `GET` | `/health` | Lightweight readiness probe. Returns `{ "status": "ok" }` when the server is reachable. | +| `GET` | `/api/telemetry` | Queue and VRAM telemetry: batching stats, pending requests, cache state, uptime. | +| `POST` | `/api/generate` | Submit a generation job. Requests are buffered, batched when signatures match and resolved asynchronously. | + +The service listens on port `7861` by default. Launch it with: + +```fish +uvicorn server:app --host 0.0.0.0 --port 7861 +``` + +## Payload schema (`/api/generate`) + +```json +{ + "prompt": "string", + "negative_prompt": "string", + "width": 512, + "height": 512, + "num_images": 1, + "batch_size": 1, + "scheduler": "ays", + "sampler": "dpmpp_sde_cfgpp", + "steps": 20, + "hires_fix": false, + "adetailer": false, + "enhance_prompt": false, + "img2img_enabled": false, + "img2img_image": null, + "stable_fast": false, + "reuse_seed": false, + "flux_enabled": false, + "realistic_model": false, + "multiscale_enabled": true, + "multiscale_intermittent": true, + "multiscale_factor": 0.5, + "multiscale_fullres_start": 10, + "multiscale_fullres_end": 8, + "keep_models_loaded": true, + "enable_preview": false, + "preview_fidelity": "balanced", + "guidance_scale": null, + "seed": null +} +``` + +Not all fields are required—only `prompt`, `width`, `height` and `num_images` are strictly necessary. Any unknown keys are ignored, making the endpoint forward-compatible with UI features. + +### Response format + +Successful requests return either: + +```json +{ "image": "" } +``` + +or, if multiple images were requested: + +```json +{ "images": ["", ""] } +``` + +Base64 strings represent PNG files with embedded metadata identical to the Streamlit UI output. Decode and write them to disk. + +### Img2Img uploads + +When `img2img_enabled` is `true`, `img2img_image` may be provided as any of the following: + +- A local file path (e.g., `"tests/test.png"`) +- A data URL (e.g., `"data:image/png;base64,<...>"`) +- A raw Base64-encoded PNG string + +The server will decode data URLs and raw Base64 strings and save them to the system temporary directory before processing (default max upload size: 10 MB). Keep payloads under a few megabytes to avoid HTTP timeouts. + +## Telemetry shape (`/api/telemetry`) + +The telemetry endpoint returns operational stats that help with autoscaling or queue dashboards. Example snippet: + +```json +{ + "uptime_seconds": 1234.56, + "pending_count": 2, + "pending_by_signature": { + "(False, 512, 512, True, False, False, True, True, 0.5, 10, 8, False, True, False)": 2 + }, + "pending_preview": [ + {"request_id": "a1b2c3d4", "waiting_s": 0.42, "prompt_preview": "a cinematic robot..."} + ], + "max_batch_size": 4, + "max_images_per_group": 256, + "batch_timeout": 0.5, + "batches_processed": 12, + "items_processed": 24, + "requests_processed": 12, + "avg_processed_wait_s": 0.31, + "pending_avg_wait_s": 0.12, + "memory_info": { + "vram_allocated_mb": 5623, + "vram_reserved_mb": 6144, + "system_ram_mb": 12345 + }, + "loaded_models_count": 2, + "loaded_models": ["SD15 UNet", "SD15 VAE"], + "pipeline_import_ok": true, + "pipeline_import_error": null +} +``` + +Use this data to spot batching mismatches (different signatures cannot be coalesced), monitor VRAM usage or expose metrics to Prometheus/Grafana. + +## Queue tuning knobs + +The queue accepts a few environment variables that influence behaviour: + +| Variable | Default | Effect | +| --- | --- | --- | +| `LD_MAX_BATCH_SIZE` | `4` | Maximum items processed together when signatures match. | +| `LD_BATCH_TIMEOUT` | `0.5` | Seconds to wait before flushing a batch. | +| `LD_BATCH_WAIT_SINGLETONS` | `0` | If `1`, single jobs wait the timeout hoping for companions. Set to `0` to process singletons immediately. | +| `LD_MAX_IMAGES_PER_GROUP` | `256` | Maximum combined images processed in a single pipeline run when coalescing multiple requests. Groups larger than this are processed sequentially in smaller chunks to avoid memory and disk pressure. | +| `LD_MAX_IMAGES_PER_SAVE` | `16` | Maximum images allowed in a single `save_images` call. If exceeded, the save is aborted to avoid creating many tile files; change with `LD_MAX_IMAGES_PER_SAVE` if needed. | +| `LD_SERVER_LOGLEVEL` | `DEBUG` | Logging verbosity for `logs/server.log`. | + +## Deploying behind a reverse proxy + +When hosting remotely: + +- Front the FastAPI app with Nginx/Caddy and increase client body size if you accept Img2Img uploads. +- Expose `/health` for liveness checks and `/api/telemetry` for readiness/autoscaling gates. +- Mount `./include`, `./output` and `~/.cache/torch_extensions` as volumes so workers share models, outputs and compiled kernels. + +## Testing the service quickly + +```fish +# Send a simple generation job +curl -X POST http://localhost:7861/api/generate \ + -H "Content-Type: application/json" \ + -d '{"prompt": "painted nebula over distant mountains", "width": 512, "height": 512, "num_images": 1}' \ + | jq -r '.image' | base64 -d > nebula.png + +# Inspect queue state +curl http://localhost:7861/api/telemetry | jq +``` + +That’s it! Check the [Troubleshooting guide](quirks.md) if the service reports missing models or the queue appears stalled. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000000000000000000000000000000000000..a9ef7b1d8cef72b740cab13db9d79226aeadd86a --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,73 @@ +# Architecture + +LightDiffusion-Next is split into three cooperating layers: UX surfaces, a FastAPI gateway and a modular inference core. Requests move through these layers, picking up metadata and transformations before image tensors ever touch the GPU. This page decomposes the system and highlights the extension points you are most likely to touch. + +## Layers in detail + +### UX layer (`streamlit_app.py`, `app.py`, `ui/*`) + +- Streamlit exposes rich controls, preset management and history in `ui/settings.py` and `ui/history.py`. +- Gradio powers Spaces deployments (`app.py`). It streams previews via generators and mirrors the Streamlit control surface. +- Both UIs instantiate a shared `AppInstance` which holds the pipeline, preview queues and cached settings. + +### FastAPI gateway (`server.py`) + +- Implements `/api/generate`, `/api/telemetry`, `/api/interrogate` and health probes. +- `GenerationBuffer` batches jobs with compatible shapes, models and LoRA overlays to maximize GPU utilization. +- Telemetry exposes queue lengths, average latency, VRAM usage and cached model fingerprints. +- Server-side logging includes per-request identifiers and request tracebacks in `logs/server.log`. + +### Pipeline core (`src/user/pipeline.py`) + +This module orchestrates conditioning, diffusion, optional refinements and output serialization. + +- **Model resolution** — `src/FileManaging/Loader` locates checkpoints, VAE, CLIP weights and LoRAs. Stable-Fast backends live in `src/StableFast` and can be toggled in settings. +- **Conditioning** — Prompts are tokenized through `src/cond/cond.py`. Negative prompts, style presets and textual inversion embeddings are applied here. +- **Sampling** — `src/sample/sampling.KSampler` coordinates samplers (`ddim`, `dpmpp`, `k-diffusion`, etc.) with CFG++ and Flux schedulers. +- **Enhancements** — Multi-scale diffusion (`multiscale_presets.py`), AutoDetailer (YOLO detection + inpainting), UltimateSDUpscale and AutoHDR run after the base diffusion loop. +- **Outputs** — `src/FileManaging/ImageSaver` writes PNGs, JSON metadata and optionally sends frames to the preview queues. + +### Device and cache (`src/Device/ModelCache.py`) + +- Maintains reference-counted handles for UNet, VAE, CLIP and Flux components. +- Handles VRAM telemetry and eviction policies so the UI can show “keep loaded” toggles without manual restarts. +- Tracks whether Stable-Fast kernels, SageAttention or SD1.5 attention patches are initialized. + +### Asset management (`src/FileManaging/Downloader.py`) + +- Validates required checkpoints, VAE files, LoRAs, embeddings, YOLO detectors and Flux components at startup. +- Supports mirrored download hosts and resumable transfers for large files. +- Exposes helper methods used by the UI to fetch missing assets on demand. + +### Preview subsystem (`src/user/app_instance.py`) + +- Provides `get_latest_previews()` for UI clients, backed by a dedicated thread that consumes preview tensors straight from the pipeline. +- Supports interrupt handling by setting `app_instance.interrupt = True`, which causes the sampler to exit gracefully. + +## Request lifecycle + +1. **Submission** — A UI or REST client creates a job payload containing prompts, dimensions, sampler settings, seed and post-processing flags. +2. **Queueing & batching** — Jobs are inserted into `GenerationBuffer`. Depending on `LD_BATCH_WAIT_SINGLETONS`, single jobs may wait briefly for compatible companions to maximize GPU throughput. +3. **Model preparation** — The pipeline loads or reuses cached models, applies LoRA deltas, textual inversion embeddings and optional quantization adapters (via `src/Quantize`). +4. **Diffusion** — The sampler executes the denoising loop. Flux mode uses `src/BlackForest/Flux.py` for decoder steps; Stable-Fast kernels speed up SD1.5/SDXL. +5. **Refinement** — Optional stages (HiRes Fix, AutoDetailer, AutoHDR, UltimateSDUpscale) run sequentially per sample. +6. **Persistence** — Final images and metadata are written to `output//`. Streamlit previews receive running frames; REST clients receive base64 PNG payloads plus telemetry. + +## Filesystem overview + +- `include/checkpoints` — SD checkpoints (1.5, SDXL, Flux, etc.). +- `include/loras`, `include/embeddings` — LoRA adapters and textual inversion concepts. +- `include/clip` — Tokenizer and encoder configs. +- `include/yolos` — Object detectors for AutoDetailer. +- `include/ESRGAN` — Upscaler models for UltimateSDUpscale. +- `output/*` — Organized galleries (Classic, Flux, Img2Img, Upscale, etc.). +- `webui_settings.json` — Persisted Streamlit configuration. + +## Extending LightDiffusion-Next + +- **New samplers** — Implement in `src/sample/samplers.py` and register with `KSampler`. Add UI and REST switches via `ui/settings.py` and `GenerateRequest`. +- **Additional post-processing** — Follow the pattern in `UltimateSDUpscale` or `AutoHDR` and register the stage near the end of `pipeline()`. +- **Custom model managers** — Plug alternative download logic into `FileManaging/Downloader` or mount volumes in Docker deployments. +- **Observability** — Add metrics/log statements in `GenerationBuffer` or extend `/api/telemetry` to fit orchestrator dashboards. + +Armed with this bird’s-eye view, you can dive into the [usage guide](usage.md) for operator workflows or the upcoming [API reference](api.md) for automation hooks. \ No newline at end of file diff --git a/docs/ays-scheduler.md b/docs/ays-scheduler.md new file mode 100644 index 0000000000000000000000000000000000000000..2a6766fcb52db80fe4accb83b4df0835853e50da --- /dev/null +++ b/docs/ays-scheduler.md @@ -0,0 +1,150 @@ +## 2. AYS (Align Your Steps) Scheduler + +### What It Does + +Uses optimized timestep distributions that allow **fewer sampling steps** with **same or better quality** compared to uniform schedulers. + +### Key Insight + +Not all timesteps contribute equally to image formation. AYS pre-computes optimal sigma schedules that focus more steps on critical noise levels. + +### Research Background + +Based on "Align Your Steps: Optimizing Sampling Schedules in Diffusion Models" (2024) +- https://research.nvidia.com/labs/toronto-ai/AlignYourSteps/ +- Developed by NVIDIA researchers +- Validated across SD1.5, SDXL, and other models + +### Performance + +| Model | Normal Scheduler | AYS Scheduler | Quality | +|-------|-----------------|---------------|---------| +| SD1.5 | 20 steps | **10 steps** | Same/Better | +| SDXL | 20 steps | **10 steps** | Same/Better | +| Flux | 15 steps | **8 steps** | Same | + +### Usage + +#### Via UI (Streamlit) + +1. Open Settings → Sampling +2. Select scheduler: "AYS (Align Your Steps)" +3. Reduce steps to 10 (SD1.5/SDXL) or 8 (Flux) +4. Generate - same quality, 2x faster! + +#### Programmatically + +```python +from src.sample import ksampler_util + +# Using AYS scheduler +sigmas = ksampler_util.calculate_sigmas( + model_sampling, + scheduler_name="ays", # or "ays_sd15", "ays_sdxl", "ays_flux" + steps=10 +) +``` + +### Scheduler Variants + +- `"ays"` or `"ays_sd15"` - SD1.5 optimized (default) +- `"ays_sdxl"` - SDXL optimized +- `"ays_flux"` - Flux optimized (experimental) + +### Optimal Step Counts + +Pre-computed optimal schedules exist for: + +**SD1.5**: 4, 6, 8, 10, 12, 15, 20, 25 steps +**SDXL**: 4, 6, 8, 10, 12, 15, 20 steps +**Flux**: 4, 8, 10, 15, 20 steps + +Other step counts use interpolation (slightly less optimal but still better than uniform). + +### Recommended Settings + +#### SD1.5 Quick Generation +```yaml +scheduler: "ays" +steps: 10 # instead of 20 +sampler: "euler" or "dpmpp_2m_cfgpp" +cfg: 7.0 +``` + +#### SDXL High Quality +```yaml +scheduler: "ays_sdxl" +steps: 12 # instead of 20-25 +sampler: "dpmpp_2m_cfgpp" +cfg: 6.0 +``` + +#### Flux Fast Mode +```yaml +scheduler: "ays_flux" +steps: 8 # instead of 15 +sampler: "euler" +cfg: 3.5 +``` + +### Comparison: Uniform vs AYS + +**Uniform Distribution (normal scheduler)**: +``` +Steps: 0 4 8 12 16 20 +Sigmas evenly spaced → wastes compute on low-impact timesteps +``` + +**AYS Distribution**: +``` +Steps: 0 2 5 8 12 17 20 +Sigmas concentrated on critical noise levels → better efficiency +``` + +### Technical Details + +AYS schedules are pre-computed using optimization to minimize reconstruction error: + +```python +# Example SD1.5 10-step schedule +AYS_SD15_10 = [ + 14.6146, # High noise (early steps - image structure) + 10.4708, + 7.3688, + 4.9651, # Mid noise (detail formation) + 3.2924, + 2.1391, + 1.3633, # Low noise (fine details) + 0.8437, + 0.4898, + 0.2279, + 0.0 # Final step +] +``` + +Compare to uniform schedule: +```python +# Normal scheduler @ 10 steps +NORMAL_10 = [14.6146, 11.3, 8.7, 6.7, 5.1, 3.9, 3.0, 2.3, 1.7, 1.2, 0.0] +# More evenly spaced → less efficient +``` + +### Troubleshooting + +**Q: Images look different with AYS?** +A: Yes, they will differ slightly (different paths through noise space). Quality should be same or better. Adjust CFG if needed. + +**Q: AYS + multiscale?** +A: Works great together! AYS optimizes step distribution, multiscale optimizes spatial resolution. + +**Q: Can I use AYS with euler_ancestral?** +A: Yes! Works with all samplers (euler, euler_ancestral, dpmpp_2m_cfgpp, dpmpp_sde_cfgpp, etc.) + +**Q: How to verify it's active?** +A: Check logs for "Using AYS optimal schedule" message. + +### References + +- Original paper: https://research.nvidia.com/labs/toronto-ai/AlignYourSteps/ +- Implementation: `src/sample/ays_scheduler.py` +- Integration: `src/sample/ksampler_util.py` diff --git a/docs/cfg-free-sampling.md b/docs/cfg-free-sampling.md new file mode 100644 index 0000000000000000000000000000000000000000..075dd499faaac887ec1d51d9a71e518690ac94c3 --- /dev/null +++ b/docs/cfg-free-sampling.md @@ -0,0 +1,269 @@ +# CFG-Free Sampling + +## Overview + +CFG-Free Sampling is a **quality optimization technique** that gradually reduces Classifier-Free Guidance (CFG) to zero during the final stages of image generation. This approach leverages the observation that high CFG strength is most beneficial early in the denoising process, while later steps benefit from reduced guidance for more natural, detailed outputs. + +By intelligently transitioning from high-guidance to low-guidance sampling, CFG-Free achieves: + +- **Improved fine detail** and texture quality +- **More natural color saturation** and tonal balance +- **Reduced artifacts** from over-guidance (halos, oversaturation, unnatural sharpness) +- **Better prompt adherence** while maintaining photorealism + +This is a **training-free** technique that works with any sampler and can be combined with other optimizations. + +## How It Works + +### The CFG Problem + +Classifier-Free Guidance strengthens prompt adherence by amplifying the difference between conditional and unconditional predictions: + +$$ +\text{output} = \text{uncond\_pred} + \text{cfg\_scale} \times (\text{cond\_pred} - \text{uncond\_pred}) +$$ + +**Benefits of high CFG (7-12):** +- Strong prompt following +- Clear compositional structure +- Distinct subjects and backgrounds + +**Drawbacks of high CFG throughout generation:** +- Over-sharpened edges ("halo effect") +- Oversaturated colors +- Loss of fine detail and texture +- Unnatural, "CG-like" appearance +- Potential anatomical distortions + +### The CFG-Free Solution + +Research shows that CFG importance varies by denoising stage: + +``` +┌─────────────────────────────────────────────────────────┐ +│ Early Steps (0-70%) │ +│ High CFG is crucial: │ +│ • Establishes composition │ +│ • Defines subject placement │ +│ • Interprets prompt semantics │ +│ │ +│ CFG = 7.0 (user-configured) │ +└─────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────┐ +│ Late Steps (70-100%) │ +│ High CFG becomes detrimental: │ +│ • Composition already locked in │ +│ • Fine details being refined │ +│ • Oversaturation and artifacts emerge │ +│ │ +│ CFG = 7.0 → 0.0 (linear reduction) │ +└─────────────────────────────────────────────────────────┘ +``` + +CFG-Free gradually reduces guidance from your configured value (e.g., 7.0) to 0.0 over the final portion of generation. This preserves strong prompt adherence while allowing the model to naturally refine details without over-guidance. + +## Configuration + +### Parameters + +| Parameter | Type | Default | Range | Description | +|-----------|------|---------|-------|-------------| +| `cfg_free_enabled` | bool | `False` | - | Enable CFG-Free sampling | +| `cfg_free_start_percent` | float | `70.0` | 0-100 | Percentage of steps at which to start reducing CFG | + +### How to Choose `cfg_free_start_percent` + +The optimal starting point depends on your aesthetic goals: + +| Start % | Behavior | Best For | +|---------|----------|----------| +| **60-65%** | Aggressive reduction, maximum detail preservation | Photorealistic portraits, product photography, architectural renders | +| **70-75%** | Balanced approach (recommended) | General purpose, landscapes, character art, concept art | +| **80-85%** | Conservative reduction, maintains stronger guidance | Abstract art, heavily stylized content, complex compositions | +| **90%+** | Minimal effect, mostly for testing | Debugging, comparing with full-CFG baseline | + +**Rule of thumb:** Start with 70% for most use cases. If images appear oversaturated or have unnatural sharpness, lower it to 65%. If prompt adherence weakens, raise it to 75-80%. + +## Usage + +### Streamlit UI + +Enable in the **🎨 CFG-Free Sampling** expander: + +1. Check **Enable CFG-Free Sampling** +2. Adjust the **Start Percentage** slider (0-100%, default: 70%) +3. The info panel shows exactly when CFG reduction begins +4. Generate images — you'll see console logging confirming activation + +**Visual feedback:** +``` +✓ CFG-Free sampling ACTIVE: CFG will gradually reduce to 0 starting at 70% of steps +``` + +### REST API + +Include in your generation request: + +```bash +curl -X POST http://localhost:7861/api/generate \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "a portrait of a woman with flowing hair, soft lighting", + "negative_prompt": "blurry, low quality", + "width": 768, + "height": 1024, + "steps": 25, + "cfg_scale": 7.5, + "cfg_free_enabled": true, + "cfg_free_start_percent": 70.0 + }' +``` + +### Python API + +```python +from src.user.pipeline import pipeline + +pipeline( + prompt="a serene mountain landscape at sunset", + negative_prompt="blurry, distorted", + w=1024, + h=768, + steps=30, + sampler="dpmpp_sde_cfgpp", + scheduler="ays", + cfg_free_enabled=True, + cfg_free_start_percent=70.0, + number=1 +) +``` + +## Quality Impact Analysis + +### Visual Improvements + +CFG-Free sampling produces subtle but meaningful quality improvements: + +**Before (Standard CFG=7.5):** +- Sharper edges, sometimes with halos +- More saturated colors (can appear "painted") +- Higher contrast, more dramatic lighting +- Occasionally oversimplified textures + +**After (CFG-Free from 70%):** +- Softer, more natural edge transitions +- Improved color accuracy and tonal range +- Better fine detail in hair, fabric, skin textures +- More photorealistic lighting and shadow falloff +- Reduced artifacts around high-contrast boundaries + +**Key insight:** Prompt adherence is determined in the first 60-70% of steps. Reducing CFG afterward doesn't weaken composition, it enhances natural detail refinement. + +## Troubleshooting + +### "Images look washed out or less vibrant" + +**Cause:** CFG-Free starting too early (e.g., 50-60%) can over-reduce guidance. + +**Solutions:** +- Increase `cfg_free_start_percent` to 70-75% +- Slightly increase base `cfg_scale` to 8.0-8.5 +- Use a different sampler (try `dpmpp_sde_cfgpp` or `dpmpp_2m_cfgpp`) + +### "No visible difference from standard CFG" + +**Cause:** Differences are subtle and may be masked by: +- Very simple prompts (single subject, plain background) +- Low resolution (<512px in any dimension) +- Aggressive other optimizations obscuring quality gains + +**Solutions:** +- Test with complex prompts (portraits, detailed scenes) +- Use higher resolutions (768px+ recommended) +- Generate comparison images side-by-side with CFG-Free on/off +- Try lower `cfg_free_start_percent` (60-65%) for more noticeable effect + +### "Prompt adherence weakened" + +**Cause:** CFG-Free starting too early for your particular prompt complexity. + +**Solutions:** +- Increase `cfg_free_start_percent` to 75-80% +- Use stronger base `cfg_scale` (8.0-9.0) +- Increase step count to 30-35 for better convergence + +## Technical Details + +### Implementation + +CFG-Free is implemented in the `CFGGuider` class (`src/sample/CFG.py`): + +```python +def _update_cfg_for_sigma(self, sigma): + """Update CFG value based on current sigma and CFG-free parameters.""" + if not self.cfg_free_enabled: + return + + # Find current step position in schedule + current_step = find_closest_sigma_index(sigma, self.sigmas) + total_steps = len(self.sigmas) - 1 + progress_percent = (current_step / total_steps) * 100.0 + + if progress_percent >= self.cfg_free_start_percent: + # Linear interpolation from original CFG to 0 + cfg_free_progress = ( + (progress_percent - self.cfg_free_start_percent) / + (100.0 - self.cfg_free_start_percent) + ) + self.cfg = self.original_cfg * (1.0 - cfg_free_progress) + self.cfg = max(0.0, self.cfg) # Clamp to [0, original_cfg] +``` + +**Schedule visualization:** + +``` +CFG Scaling Over Time (start_percent=70%, original_cfg=7.5) + +Step: 0 5 10 15 20 25 30 35 40 45 50 + ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ +CFG: 7.5 7.5 7.5 7.5 7.5 7.5 7.5 5.6 3.8 1.9 0.0 + │■■■■■■■■■■■■■■■■■■■■■■■■│▓▓▓▓▓▓▓▓▓▓│░░░░│ │ │ + └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ + ←──── Full CFG ────────→←─── Gradual Reduction ───→ +``` + +### Mathematical Formulation + +Standard CFG at every step: + +$$ +\mathbf{x}_{t-1} = \mathbf{x}_t + \text{cfg\_scale} \times (\mathbf{cond} - \mathbf{uncond}) +$$ + +CFG-Free with schedule: + +$$ +\mathbf{x}_{t-1} = \mathbf{x}_t + \text{cfg}(t) \times (\mathbf{cond} - \mathbf{uncond}) +$$ + +Where: + +$$ +\text{cfg}(t) = \begin{cases} +\text{cfg\_scale} & \text{if } t < t_{\text{start}} \\ +\text{cfg\_scale} \times \left(1 - \frac{t - t_{\text{start}}}{t_{\text{total}} - t_{\text{start}}}\right) & \text{if } t \geq t_{\text{start}} +\end{cases} +$$ + +## Related Optimizations + +- **[CFG++ Samplers](optimizations.md#cfg-samplers)**: Advanced CFG implementation with momentum and multi-scale — CFG-Free complements these +- **[Multi-Scale Diffusion](optimizations.md#multi-scale)**: Resolution-based optimization — works independently of CFG-Free +- **[DeepCache](wavespeed.md#deepcache)**: Feature caching for speedup — no quality interaction with CFG-Free + +## References & Further Reading + +- Original research: CFG-Free sampling builds on insights from [Classifier-Free Guidance](https://arxiv.org/abs/2207.12598) (Ho & Salimans, 2022) +- Implementation inspired by community experiments with dynamic CFG schedules +- Mathematical framework adapted from diffusion model literature diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 0000000000000000000000000000000000000000..c0a34bc81ab786905780539c88b05a735f037dfc --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,94 @@ +# Contributing + +Thanks for helping push LightDiffusion-Next forward! This project blends a Streamlit UI, a Gradio deployment surface, a FastAPI queue and a sizeable inference stack. The guidelines below should get you productive quickly. + +## Getting your environment ready + +### Prerequisites + +- Python 3.10 (the bundled wheels and Stable-Fast extension are built against 3.10) +- NVIDIA GPU with CUDA 12.1+ drivers (for GPU development) +- Git (with LFS if you plan to version large model weights) +- `uv` or `pip` for dependency management +- Optional: Docker + NVIDIA Container Toolkit for containerized testing + +### Clone & install + +```fish +git clone https://github.com/Aatricks/LightDiffusion-Next.git +cd LightDiffusion-Next + +# Recommended: isolate dependencies +python -m venv .venv +source .venv/bin/activate + +# Install runtime dependencies +uv pip install -r requirements.txt + +# (Optional) Extras for docs and linting +uv pip install mkdocs mkdocs-material mkdocstrings-python ruff black +``` + +Populate `include/` with the checkpoints you need (SD1.5, Flux, LoRAs, embeddings). The UI will prompt you for missing assets if you skip this step. + +## Running the apps locally + +- **Streamlit UI**: `streamlit run streamlit_app.py` +- **Gradio UI**: `python app.py` +- **FastAPI backend**: `uvicorn server:app --host 0.0.0.0 --port 7861` + +All services read the same configuration and model directories. When working on the pipeline, it’s handy to keep FastAPI running for quick REST smoke tests while you iterate on the UI in a separate terminal. + +## Workflow expectations + +1. Create a branch per piece of work: `git checkout -b feature/short-summary`. +2. Keep pull requests focused—avoid bundling unrelated refactors with feature work. +3. Reference issues in your commit messages and PR description when applicable. +4. Update documentation (`docs/`, `README.md`) whenever behavior, defaults or environments change. + +## Coding standards + +- Follow PEP 8 for Python. If you have `ruff` or `black` installed, run them before committing (`ruff check src ui` and `black src ui`). +- Prefer type hints for new modules; FastAPI schemas and pipeline helpers already use Pydantic models you can extend. +- Favor dependency injection over global state—pass configuration into functions where feasible so the FastAPI worker and Streamlit UI stay in sync. +- When touching CUDA or kernel build logic, document the change in `docs/quirks.md` or `docs/installation.md` so operators know about new requirements. + +## Verification checklist + +Before opening a pull request: + +- [ ] `streamlit run streamlit_app.py` starts without stack traces. +- [ ] `uvicorn server:app --host 0.0.0.0 --port 7861` accepts at least one `/api/generate` call (you can use the example payload in [API docs](api.md)). +- [ ] `python app.py` (Gradio) loads when relevant to your change. +- [ ] `mkdocs build` succeeds (documentation stays green). +- [ ] GPU-specific changes are tested on at least one real GPU and noted in the PR description. +- [ ] No large binaries or secrets are committed—place models inside `include/` and gitignore keeps them local. + +If you add scripts or automation, include instructions in `docs/examples.md` or a new page and wire it into `mkdocs.yml`. + +## Submitting your PR + +- Fill out a concise description covering **what changed**, **why**, and any ops impact (new env vars, caches, etc.). +- Attach screenshots or sample renders when altering the UI or pipeline defaults. +- Expect friendly but thorough reviews—batching, caching and GPU tweaks affect many users, so be ready to iterate. +- Squash-merge is fine, but avoid force-pushing after reviews unless you coordinate with the maintainer. + +## Bug reports & feature requests + +When reporting an issue, please include: + +- Operating system, driver versions (`nvidia-smi` output), GPU model +- How you launched LightDiffusion-Next (Streamlit, Docker, FastAPI) +- Relevant logs (`logs/server.log`, Streamlit terminal output, `/api/telemetry` response) +- Steps to reproduce and whether the problem is reproducible on a fresh checkout + +Feature ideas are welcome—outline the use case, expected UX and any new dependencies (models, GPU requirements). Discussions and prototypes in separate branches make reviews easier. + +## Documentation contributions + +- Run `mkdocs serve` while editing to preview changes at http://127.0.0.1:8080. +- Add new pages under `docs/` and update `mkdocs.yml` navigation. +- Screenshots should be optimized PNGs or WebPs stored under `docs/images/`. +- Keep `README.md` focused on quick start—you can link to richer docs pages for details. + +Thanks again for contributing! 🚀 \ No newline at end of file diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 0000000000000000000000000000000000000000..59ef366acd41536aeddd4e4664af14c54baf1402 --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,143 @@ +# Recipes & Workflows + +This page collects practical “recipes” for common LightDiffusion-Next scenarios. Each section lists the UI path, optional CLI equivalents and tips for squeezing the best quality or performance out of the pipeline. + +## 1. Classic text-to-image (SD1.5) + +Steps in the Streamlit UI: + +1. Enter a prompt such as `a cozy reading nook lit by neon signs, cinematic lighting, ultra detailed`. +2. Leave negative prompt empty to use the curated default (includes `EasyNegative` and `badhandv4`). +3. Set width and height to `768 × 512` and request `4` images with a batch size of `2`. +4. Enable **Keep models in VRAM** for faster iteration while exploring. +5. (Optional) Toggle **Enhance prompt** if you have Ollama running. +6. Click **Generate** — watch the TAESD previews update in real time. + +CLI equivalent: + +```bash +python -m src.user.pipeline "a cozy reading nook lit by neon signs" 768 512 4 2 --stable-fast --reuse-seed +``` + +Tips: + +- For softer lighting turn on **AutoHDR** (enabled by default) and lower CFG to 6.5 using the advanced settings drawer. +- Combine with **LoRA** adapters by placing `.safetensors` files in `include/loras/` and selecting them in the UI dropdown. + +## 2. Flux workflow + +Flux requires the quantized GGUF UNet, CLIP, T5 weights and the schnELL VAE (`include/vae/ae.safetensors`). The first run downloads them automatically. + +1. Toggle **Flux mode**. +2. Switch CFG to `1.0` (Flux expects low CFG) and set steps to around 20. +3. Provide a natural language prompt such as `a charcoal sketch of a train arriving at midnight, expressive strokes`. +4. Generate 2 images with batch size 1. + +REST API example: + +```bash +curl -X POST http://localhost:7861/api/generate \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "a charcoal sketch of a train arriving at midnight, expressive strokes", + "width": 832, + "height": 1216, + "num_images": 2, + "flux_enabled": true, + "keep_models_loaded": true + }' | jq '.images[0]' -r | base64 -d > flux.png +``` + +Tips: + +- Flux ignores negative prompts and uses natural language weighting. Seed reuse works the same way as SD1.5. +- Monitor GPU memory in the **Model Cache Management** accordion — Flux models are larger. + +## 3. HiRes Fix + ADetailer portrait + +1. Choose a prompt such as `portrait of a cyberpunk detective, glowing tattoos, rain-soaked alley`. +2. Set `width = 640`, `height = 896`, **num images = 1**. +3. Enable **HiRes Fix**, **ADetailer** and **Stable-Fast**. +4. In the advanced section set **HiRes denoise** to ~0.45 by editing `config.toml` (or accept the default and adjust later). +5. Generate — the pipeline saves the base render, body detail pass and head detail pass separately. + +Where to find outputs: + +- Base image: `output/HiresFix/`. +- Body/head detail passes: `output/Adetailer/`. + +Tips: + +- Provide a short negative prompt that removes “extra limbs” to guide the detector. +- Use the **History** tab to compare detailer versus base results quickly. + +## 4. Img2Img upscaling with Ultimate SD Upscale + +1. Enable **Img2Img mode** and upload your reference image. +2. Set denoise strength via the slider in the Img2Img accordion (`0.3` is a good starting point). +3. Toggle **Stable-Fast** for faster tile processing and keep CFG around 6. +4. Generate. UltimateSDUpscale will split the image into tiles, run targeted refinement and apply RealESRGAN (`include/ESRGAN/RealESRGAN_x4plus.pth`). + +Tips: + +- For stylized upscales change the prompt between passes — the pipeline will regenerate details without overwriting the original. +- Outputs land in `output/Img2Img/` with metadata including seam-fixing parameters. + +## 5. Automated batch via REST API + +Use the FastAPI backend when you need to process multiple prompts from scripts or a Discord bot. + +```python +import base64 +import json +import requests + +payload = { + "prompt": "sunrise over a foggy fjord, volumetric light, ethereal", + "negative_prompt": "low quality, blurry", + "width": 832, + "height": 512, + "num_images": 3, + "batch_size": 3, + "stable_fast": True, + "reuse_seed": False, + "enable_preview": False +} + +resp = requests.post("http://localhost:7861/api/generate", json=payload) +resp.raise_for_status() +images = resp.json().get("images", []) +for idx, b64_img in enumerate(images): + with open(f"fjord_{idx+1}.png", "wb") as f: + f.write(base64.b64decode(b64_img)) +``` + +The queue automatically coalesces compatible requests to maximize GPU utilization. Check `/api/telemetry` for batching statistics and memory usage. + +## 6. Discord bot bridge + +Combine LightDiffusion-Next with the [Boubou](https://github.com/Aatrick/Boubou) Discord bot: + +1. Follow the bot’s README to set your Discord token and install `py-cord` inside the LightDiffusion environment. +2. Point the bot’s configuration at the FastAPI endpoint (`http://localhost:7861`). +3. Give the bot `Send Messages` and `Attach Files` permissions. +4. Use commands such as `/ld prompt:"a watercolor koi pond"` from your server and watch images stream back into the channel. + +## 7. Prompt enhancer playground + +1. Install [Ollama](https://ollama.com/) and run `ollama serve` in another terminal. +2. Pull the suggested model: + + ```bash + ollama pull qwen3:0.6b + ``` + +3. Export the model name before launching the UI: + + ```bash + export PROMPT_ENHANCER_MODEL=qwen3:0.6b + ``` + +4. Enable **Enhance prompt** in Streamlit and inspect the rewritten prompt under the preview section. The original text is still stored as `original_prompt` inside PNG metadata. + +Continue exploring by reading the [performance & tuning](quirks.md) guide or the [REST documentation](api.md) for full endpoint details. \ No newline at end of file diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 0000000000000000000000000000000000000000..743d61eab3aed3515653a4f6f3f71ddd6266b920 --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,68 @@ +# FAQ + +Q: Where do I put my checkpoints? + +A: Put them in `include/checkpoints` (create the folder if missing). The UI and `src/FileManaging/Loader` will detect and list them. + +Q: Why is GPU memory insufficient? + +A: Try reducing `width`/`height`, turning off `keep models loaded`, or enable quantized Flux/GGUF models. See [Performance & Troubleshooting](quirks.md). + +Q: Can I run headless on a server? + +A: Yes — use the FastAPI backend with `docker-compose` or run `server.py` directly. Disable Streamlit if you don’t need the web UI. + +Q: How do I contribute models or LoRAs? + +A: Place LoRA files in `include/loras` and embeddings in `include/embeddings`. See [Contributing](contributing.md) for guidelines. + +/// details | Which diffusion models are supported out of the box? +LightDiffusion-Next ships with Stable Diffusion 1.5-friendly defaults and includes helpers for SDXL-inspired checkpoints, Flux (via the `include/Flux` assets) and quantized Stable-Fast backends. Drop your `.safetensors` or `.ckpt` files into `include/checkpoints`, LoRAs into `include/loras`, embeddings into `include/embeddings`, and Flux weights into `include/Flux`. The loader auto-detects formats and will prompt for missing companions (VAE, CLIP) at startup. +/// + +/// details | What GPU and driver versions do I need? +NVIDIA GPUs with CUDA 12.1+ drivers are recommended. Availability of Stable-Fast, SageAttention and SpargeAttn depends on your installed kernels, drivers and GPU compute capability — the runtime detects and enables compatible backends automatically. For Docker, install the NVIDIA Container Toolkit and verify `nvidia-smi` works inside the container. +/// + +/// details | Can I run LightDiffusion-Next without a GPU? +Yes, but performance will be limited. Install CPU wheels of PyTorch or rely on the bundled Intel oneAPI runtime (Linux only). Disable Stable-Fast/SageAttention in settings, reduce resolution (≤384×384), lower steps (<20) and turn off AutoDetailer/HiResFix to avoid minute-long renders. +/// + +/// details | Where do generated images and metadata live? +Outputs are grouped by workflow under `output/`. For example, standard Txt2Img lands in `output/classic`, HiresFix into `output/HiresFix`, Flux into `output/Flux`, Img2Img upscales into `output/Img2Img`, etc. Each PNG embeds prompt metadata; accompanying JSON manifests are saved when enabled in settings. +/// + +/// details | How do I switch between Streamlit, Gradio and the API? +Use the launch scripts: + +- `streamlit run streamlit_app.py` (default UI) +- `python app.py` (Gradio app for Spaces/remote hosting) +- `uvicorn server:app --host 0.0.0.0 --port 7861` (FastAPI) + +All three share the same pipeline and config. Streamlit/Gradio speak directly to the pipeline, while the API feeds the batching queue in `server.py`. +/// + +/// details | How do I enable Stable-Fast or SageAttention? + +In Streamlit, toggle **Stable-Fast** under *Performance*. The app will compile kernels the first time and reuse them afterwards (cache in `~/.cache/torch_extensions`). SageAttention is enabled automatically on supported GPUs; you can force-disable it by setting `LD_DISABLE_SAGE_ATTENTION=1` before launching. Docker images already ship with the patched kernels compiled. +/// + +/// details | What if the app says a model is missing? + +The downloader checks `include/` on startup and whenever a feature needs a new asset (YOLO, Flux, TAESD). Provide URLs or Hugging Face tokens when prompted, or pre-populate the folders manually. For offline environments, copy the files into the correct directories and ensure filenames match the expected suffixes (e.g., `anything-v4.5-pruned.safetensors`). +/// + +/// details | Can I enhance prompts automatically with Ollama? + +Yes. Install Ollama locally, download a language model (`ollama run mistral`), then enable **Prompt Enhancer** in the UI or set `enhance_prompt=true` in the REST payload. Set `OLLAMA_BASE_URL` if Ollama is not on `http://localhost:11434`. +/// + +/// details | How do I reset persistent settings or history? + +Delete `webui_settings.json` in the project root to reset saved toggles and defaults. Remove individual history directories under `ui/history/` to clear the UI gallery without touching generated images. +/// + +/// details | Need more help? + +Check the [Troubleshooting guide](quirks.md) or [open an issue](https://github.com/Aatricks/LightDiffusion-Next/issues) with logs, hardware specs and steps to reproduce. +/// diff --git a/docs/implemented-optimizations-report.md b/docs/implemented-optimizations-report.md new file mode 100644 index 0000000000000000000000000000000000000000..109b0a4c7e6f94060cb333c87db07bf2759c32fc --- /dev/null +++ b/docs/implemented-optimizations-report.md @@ -0,0 +1,484 @@ +# Implemented Optimizations Report + +This document presents a source-based engineering report on the optimization stack used across generation, model loading, and serving in LightDiffusion-Next. + +Unlike the overview pages: + +- The source tree is treated as the primary reference point. +- Each optimization is described in terms of purpose, implementation, integration, and trade-offs. +- Supporting infrastructure and codebase groundwork are included when they materially contribute to the performance profile of the project. + +## Report Scope + +### Usage Profile Definitions + +- `default`: selected in the standard execution path +- `integrated`: part of the current generation or serving flow +- `optional`: integrated, but enabled through request settings, configuration, or model capabilities +- `conditional`: available when hardware, dependencies, or runtime capabilities allow it +- `implementation-specific`: implemented and used, but its effective behavior is shaped by a narrower internal path than the request surface alone suggests +- `infrastructure-level`: supports the fast path indirectly through loading, transfer, caching, or serving behavior +- `codebase groundwork`: implemented in the codebase as part of the optimization stack, but not yet surfaced as a broad standard pipeline option + +### What This Report Covers + +This report covers both model-level and system-level optimizations: + +- inference and sampling speedups +- precision and memory reductions +- request batching and pipeline throughput improvements +- preview and output-path latency reductions + +It does not catalog ordinary features unless they clearly reduce compute, memory, or end-to-end latency. + +## Quick Inventory + +| Optimization | Usage Profile | Main Goal | Primary Evidence | +|---|---|---|---| +| CUDA runtime tuning (TF32, cuDNN benchmark, SDPA enablement) | integrated, conditional | faster kernels and better backend selection | `src/Device/Device.py` | +| Attention backend cascade (SpargeAttn/SageAttention/xformers/SDPA) | integrated, conditional | faster attention kernels with fallback | `src/Attention/Attention.py`, `src/Attention/AttentionMethods.py` | +| Flux2 SDPA backend priority | integrated, conditional | prefer cuDNN/Flash SDPA for Flux2 attention | `src/NeuralNetwork/flux2/layers.py`, `src/Device/Device.py` | +| Cross-attention K/V projection cache | integrated | skip repeated key/value projection work for static context | `src/Attention/Attention.py` | +| Prompt embedding cache | integrated | avoid re-encoding repeated prompts | `src/Utilities/prompt_cache.py`, `src/clip/Clip.py` | +| Conditioning batch packing and memory-aware concatenation | integrated | reduce forward passes and pack compatible condition chunks | `src/cond/cond.py` | +| CFG=1 unconditional-skip fast path | integrated | skip unnecessary unconditional branch at CFG 1.0 | `src/sample/CFG.py`, `src/sample/BaseSampler.py` | +| AYS scheduler | default | reach similar quality in fewer steps | `src/sample/ays_scheduler.py`, `src/sample/ksampler_util.py` | +| CFG++ samplers | integrated | improve denoising behavior with momentum-style correction | `src/sample/BaseSampler.py` | +| CFG-Free sampling | integrated, optional | taper CFG late in sampling for better detail/naturalness | `src/sample/CFG.py` | +| Dynamic CFG rescaling | integrated, optional | reduce overshoot and saturation from strong CFG | `src/sample/CFG.py` | +| Adaptive noise scheduling | integrated, optional | adjust schedule based on observed complexity | `src/sample/CFG.py` | +| `batched_cfg` request surface | implementation-specific | request-facing control around the deeper conditioning batching path | `src/sample/sampling.py`, `src/cond/cond.py` | +| Multi-scale latent switching | integrated, optional | do some denoising at reduced spatial resolution | `src/sample/BaseSampler.py` | +| HiDiffusion MSW-MSA patching | integrated, optional | patch UNet attention for high-resolution multiscale workflows | `src/Core/Pipeline.py`, `src/hidiffusion/msw_msa_attention.py` | +| Stable-Fast | integrated, conditional | trace/compile UNet forward path | `src/StableFast/StableFast.py`, `src/Core/Pipeline.py` | +| `torch.compile` | integrated, optional | compiler-based model speedup without Stable-Fast | `src/Device/Device.py`, `src/Core/AbstractModel.py` | +| VAE compile, tiled path, and transfer tuning | integrated | speed up decode/encode and avoid OOM | `src/AutoEncoders/VariationalAE.py` | +| BF16/FP16 automatic dtype selection | integrated, conditional | reduce memory and improve throughput on supported hardware | `src/Device/Device.py` | +| FP8 weight quantization | integrated, conditional | reduce weight memory and enable Flux2-friendly inference paths | `src/Core/AbstractModel.py`, `src/Model/ModelPatcher.py` | +| NVFP4 weight quantization | integrated, optional | stronger memory reduction than FP8 | `src/Core/AbstractModel.py`, `src/Model/ModelPatcher.py`, `src/Utilities/Quantization.py` | +| Flux2 load-time weight-only quantization | integrated, conditional | keep large Flux2/Klein components workable on smaller VRAM budgets | `src/Core/Models/Flux2KleinModel.py` | +| ToMe | integrated, optional | reduce attention cost by token merging on UNet models | `src/Model/ModelPatcher.py`, `src/Core/Pipeline.py` | +| DeepCache | integrated, optional, implementation-specific | reuse prior denoiser output between update steps | `src/WaveSpeed/deepcache_nodes.py`, `src/Core/Pipeline.py` | +| First Block Cache for Flux | codebase groundwork | cache transformer work for Flux-like models | `src/WaveSpeed/first_block_cache.py` | +| Low-VRAM partial loading and offload policy | integrated | load only what fits and offload the rest | `src/cond/cond_util.py`, `src/Device/Device.py`, `src/Model/ModelPatcher.py` | +| Async transfer helpers and pinned checkpoint tensors | integrated, infrastructure-level | reduce host/device transfer overhead | `src/Device/Device.py`, `src/Utilities/util.py` | +| Request coalescing and queue batching | integrated | increase throughput across compatible API requests | `server.py` | +| Large-group chunking and image-save guardrails | integrated | keep large coalesced runs from blowing up save/decode paths | `server.py`, `src/FileManaging/ImageSaver.py` | +| Next-model prefetch | integrated | hide future checkpoint load latency | `server.py`, `src/Device/ModelCache.py`, `src/Utilities/util.py` | +| Keep-models-loaded cache | integrated | reuse loaded checkpoints and reduce warm starts | `src/Device/ModelCache.py`, `server.py` | +| In-memory PNG byte buffer | integrated | avoid disk round-trip for API responses | `src/FileManaging/ImageSaver.py`, `server.py` | +| TAESD preview pacing and preview fidelity control | integrated, conditional | reduce preview overhead while keeping live feedback usable | `src/sample/BaseSampler.py`, `src/AutoEncoders/taesd.py`, `server.py` | + +## Executive Summary + +The optimization strategy in LightDiffusion-Next is layered and cumulative rather than dependent on a single acceleration mechanism. + +1. The core generation path combines runtime kernel selection, conditioning batching, lower-precision execution, and schedule optimization. +2. Several optimizations are part of the standard execution path, most notably AYS scheduling, prompt caching, attention backend selection, low-VRAM loading policy, and server-side request grouping. +3. A second layer of optional mechanisms provides workload-specific extensions, including Stable-Fast, `torch.compile`, ToMe, multiscale sampling, quantization, and guidance refinements such as CFG-Free and dynamic rescaling. +4. The serving layer contributes materially to end-to-end throughput and latency through request coalescing, chunking, model prefetching, keep-loaded caching, and in-memory response handling. +5. The codebase also contains foundational work for additional caching paths, particularly around Flux-oriented first-block caching, alongside the currently integrated DeepCache path. + +## Runtime And Attention Optimizations + +### CUDA runtime tuning + +- Status: `integrated, conditional` +- Purpose: use faster math modes and let the backend choose more aggressive convolution and attention kernels. +- Implementation in LightDiffusion-Next: `src/Device/Device.py` enables TF32 (`torch.backends.cuda.matmul.allow_tf32`, `torch.backends.cudnn.allow_tf32`), enables cuDNN benchmarking, and turns on PyTorch math/flash/memory-efficient SDPA when available. +- Project integration: these are process-wide defaults. They do not require per-request toggles, so supported CUDA deployments get them automatically. +- Effect: reduces matmul/convolution cost and opens better SDPA backends with no extra application-layer work. +- Benefits: automatic, broad coverage, low complexity. +- Trade-offs: hardware-conditional; benefits depend on GPU generation and PyTorch build. +- Evidence: `src/Device/Device.py`. + +### Attention backend cascade: SpargeAttn, SageAttention, xformers, PyTorch SDPA + +- Status: `integrated, conditional` +- Purpose: use the fastest available attention kernel and fall back safely when unsupported. +- Implementation in LightDiffusion-Next: UNet/VAE attention chooses `SpargeAttn > SageAttention > xformers > PyTorch` in `src/Attention/Attention.py`; the concrete kernels and fallback behavior live in `src/Attention/AttentionMethods.py`. +- Project integration: the selection happens once when the attention module is imported/constructed. Sage/Sparge paths reshape inputs to HND layouts and pad unsupported head sizes to supported dimensions where possible; larger unsupported head sizes fall back. +- Effect: faster attention on supported CUDA systems without changing calling code. +- Benefits: automatic fallback chain, works across UNet cross-attention and VAE attention blocks, handles padding for awkward head sizes. +- Trade-offs: dependency- and GPU-dependent; not all head sizes stay on the fast path; behavior differs between generic UNet/VAE attention and Flux2 attention. +- Evidence: `src/Attention/Attention.py`, `src/Attention/AttentionMethods.py`. + +### Flux2 SDPA backend priority + +- Status: `integrated, conditional` +- Purpose: prefer the best PyTorch SDPA backend for Flux2 transformer attention. +- Implementation in LightDiffusion-Next: `src/Device/Device.py` builds an SDPA priority context preferring cuDNN attention, then Flash, then efficient, then math; `src/NeuralNetwork/flux2/layers.py` uses `Device.get_sdpa_context()` around `scaled_dot_product_attention`. +- Project integration: Flux2 uses a separate attention implementation from the generic UNet attention path. It first tries prioritized SDPA, then xformers, then plain SDPA. +- Effect: prioritized fast attention for Flux2 with robust fallback behavior. +- Benefits: keeps Flux2 on the most optimized native backend available; does not require custom kernels. +- Trade-offs: benefits depend heavily on PyTorch version, backend support, and GPU runtime. +- Evidence: `src/Device/Device.py`, `src/NeuralNetwork/flux2/layers.py`. + +### Cross-attention static K/V projection cache + +- Status: `integrated` +- Purpose: when the context tensor is unchanged across denoising steps, avoid recomputing K/V projections every step. +- Implementation in LightDiffusion-Next: `CrossAttention` in `src/Attention/Attention.py` keeps a small `_context_cache` keyed by `id(context)` and caches projected `k` and `v`. +- Project integration: this primarily targets prompt-conditioning cases where context is static while the latent evolves. The cache is tiny and self-pruning. +- Effect: shaves repeated linear-projection work from cross-attention-heavy denoising loops. +- Benefits: simple, training-free, no user configuration. +- Trade-offs: keyed by object identity, so it only helps when the exact context object is reused; small cache size limits reuse breadth. +- Evidence: `src/Attention/Attention.py`. + +### Prompt embedding cache + +- Status: `integrated` +- Purpose: cache text encoder outputs for repeated prompts instead of re-encoding them each time. +- Implementation in LightDiffusion-Next: `src/Utilities/prompt_cache.py` stores `(cond, pooled)` entries keyed by prompt hash and CLIP identity; `src/clip/Clip.py` checks the cache before tokenization/encoding and writes back after encode. +- Project integration: prompt caching is globally enabled by default, applies to single prompts and prompt lists, and prunes old entries once the cache exceeds its configured maximum. +- Effect: reduces prompt-side overhead in repeated-prompt workflows, especially seed sweeps and incremental prompt refinement. +- Benefits: low complexity, wired into the actual CLIP encode path, no quality trade-off. +- Trade-offs: cache size is estimate-based and global, not per-model-session aware. +- Evidence: `src/Utilities/prompt_cache.py`, `src/clip/Clip.py`, cache clear hook in `src/Core/Pipeline.py`. + +### Conditioning batch packing and CFG=1 fast path + +- Status: `integrated` +- Purpose: concatenate compatible conditioning work into fewer forward calls, and skip unconditional work entirely when CFG is effectively disabled. +- Implementation in LightDiffusion-Next: `src/cond/cond.py::calc_cond_batch()` groups compatible condition chunks by shape and memory budget, concatenates them, and falls back per chunk when transformer options mismatch. `src/sample/CFG.py` sets `uncond_ = None` when `cond_scale == 1.0` and the optimization is not disabled. +- Project integration: this path is central to the standard sampling flow. The batching logic also validates Flux-style transformer image sizes and falls back when they do not match token grids. +- Effect: fewer model invocations, better GPU utilization, and a lower-cost path for CFG=1 workloads. +- Benefits: real throughput win, memory-aware, includes safety fallback for positional/shape mismatches. +- Trade-offs: batching heuristics are shape- and memory-sensitive; fallback behavior can reduce speed when conditions diverge. +- Evidence: `src/cond/cond.py`, `src/sample/CFG.py`, `src/sample/BaseSampler.py`, `tests/unit/test_calc_cond_batch_fallback.py`. + +## Sampling And Guidance Optimizations + +### AYS scheduler + +- Status: `default` +- Purpose: use precomputed sigma schedules that spend steps where they matter most, so fewer steps can reach comparable quality. +- Implementation in LightDiffusion-Next: schedules are encoded in `src/sample/ays_scheduler.py`; `src/sample/ksampler_util.py` routes `ays`, `ays_sd15`, and `ays_sdxl` to the scheduler and auto-detects model type when possible. +- Project integration: both `server.py` and `src/user/pipeline.py` default the scheduler to `ays`. Exact schedules are used when present; otherwise the code resamples or interpolates schedules. +- Effect: fewer denoising steps for similar output quality, especially on SD1.5 and SDXL. +- Benefits: training-free, defaulted into the request path, compatible with the sampler stack. +- Trade-offs: produces different trajectories than classic schedulers; unsupported step counts use interpolation rather than paper-derived schedules. +- Evidence: `src/sample/ays_scheduler.py`, `src/sample/ksampler_util.py`, defaults in `server.py` and `src/user/pipeline.py`, benchmark usage in `tests/benchmark_performance.py`. + +### CFG++ samplers + +- Status: `integrated` +- Purpose: apply CFG++-style momentum behavior in sampler variants to improve denoising stability and quality. +- Implementation in LightDiffusion-Next: sampler registry maps `_cfgpp` sampler names to the same sampler classes, and `get_sampler()` enables `use_momentum` whenever the sampler name contains `_cfgpp`. +- Project integration: the sampler loop stores prior denoised state and applies momentum-style correction through `BaseSampler.apply_cfg()`. The server default sampler is `dpmpp_sde_cfgpp`. +- Effect: better denoising behavior than plain sampler variants without a separate post-process stage. +- Benefits: integrated directly into the sampler registry; default sampler already uses it. +- Trade-offs: only applies on `_cfgpp` variants; behavior is coupled to sampler implementation details rather than being a universal guidance layer. +- Evidence: `src/sample/BaseSampler.py`, default sampler in `server.py`. + +### CFG-Free sampling + +- Status: `integrated, optional` +- Purpose: reduce CFG late in the denoising process so the model can finish with less over-guidance. +- Implementation in LightDiffusion-Next: `CFGGuider` stores `cfg_free_enabled` and `cfg_free_start_percent`, tracks current sigma position, and progressively reduces `self.cfg` once the configured progress threshold is crossed. +- Project integration: the flag is part of the request/context surface and is forwarded by SD1.5, SDXL, Flux2, HiResFix, and Img2Img code paths. +- Effect: potentially better detail recovery and more natural late-stage refinement. +- Benefits: integrated and actually wired through multiple pipelines; easy to combine with the rest of the sampler stack. +- Trade-offs: quality optimization rather than pure speedup; exact effect is prompt- and sampler-dependent. +- Evidence: `src/sample/CFG.py`, `src/Core/Models/SD15Model.py`, `src/Core/Models/SDXLModel.py`, `src/Core/Models/Flux2KleinModel.py`, `src/Processors/HiresFix.py`, `src/Processors/Img2Img.py`. + +### Dynamic CFG rescaling + +- Status: `integrated, optional` +- Purpose: reduce effective CFG when the guidance delta becomes too strong. +- Implementation in LightDiffusion-Next: `CFGGuider._apply_dynamic_cfg_rescaling()` computes either a variance-based or range-based adjustment and clamps the result. +- Project integration: it runs inside `cfg_function()` before CFG mixing is finalized, so it affects the real denoising path rather than acting as a post-hoc metric. +- Effect: reduces oversaturation and over-guided outputs for high-CFG workloads. +- Benefits: low incremental overhead and direct integration into CFG computation. +- Trade-offs: not a pure speed optimization; the chosen formulas are heuristic and can flatten outputs if pushed too hard. +- Evidence: `src/sample/CFG.py`. + +### Adaptive noise scheduling + +- Status: `integrated, optional` +- Purpose: use observed prediction complexity to perturb the sigma schedule during sampling. +- Implementation in LightDiffusion-Next: `CFGGuider` records complexity history during prediction and scales `sigmas` inside `inner_sample()` if adaptive mode is enabled. +- Project integration: complexity can be estimated with a spatial-difference metric or variance-like behavior, depending on the selected method. +- Effect: attempts to spend effort where the current prediction appears more complex. +- Benefits: implemented end-to-end in the guider. +- Trade-offs: heuristic, can alter reproducibility, and its benefit is much less established in this repo than AYS or request coalescing. +- Evidence: `src/sample/CFG.py`. + +### `batched_cfg` request surface + +- Status: `implementation-specific` +- Purpose: expose control over conditional/unconditional batching. +- Implementation in LightDiffusion-Next: the field exists in the request and context models and is passed into sampling, where it is stored in `model_options["batched_cfg"]`. +- Project integration: the main batching behavior is centered in `calc_cond_batch()`, while `batched_cfg` is carried through `model_options` as part of the request-side control surface around that path. +- Effect: provides a request-facing handle for a batching path whose heavy lifting is performed centrally in conditioning packing. +- Benefits: fits cleanly into the existing request and sampling pipeline. +- Trade-offs: its effect is indirect because the main concatenation behavior is implemented deeper in the conditioning layer. +- Evidence: `src/sample/sampling.py`, `src/Core/Context.py`, `src/cond/cond.py`. + +## Multiscale And Architecture-Specific Optimizations + +### Multi-scale latent switching + +- Status: `integrated, optional` +- Purpose: run some denoising steps at a downscaled latent resolution and return to full resolution for selected steps. +- Implementation in LightDiffusion-Next: `MultiscaleManager` in `src/sample/BaseSampler.py` computes a per-step full-resolution schedule and uses bilinear downscale/upscale around sampler model calls. +- Project integration: the samplers consult `ms.use_fullres(i)` each step. Flux and Flux2 are explicitly excluded because the code treats multiscale as incompatible with DiT-style architectures. +- Effect: lower compute on some denoising steps for compatible samplers and architectures. +- Benefits: actually participates in the sampler loop; configurable by factor and schedule. +- Trade-offs: it necessarily changes the denoising path and can trade detail for speed; not available for Flux/Flux2. +- Evidence: `src/sample/BaseSampler.py`, `src/sample/sampling.py`, `src/Core/Models/Flux2KleinModel.py`. + +### HiDiffusion MSW-MSA patching + +- Status: `integrated, optional` +- Purpose: patch UNet attention for high-resolution workflows using HiDiffusion-style MSW-MSA attention changes. +- Implementation in LightDiffusion-Next: the pipeline clones the inner model and applies `ApplyMSWMSAAttentionSimple` when multiscale is enabled on UNet architectures. +- Project integration: the patch is explicitly blocked for Flux/Flux2 and disabled in some sub-pipelines like refiner or certain detail passes where the project wants to avoid artifact risk. +- Effect: makes the multiscale/high-resolution path more efficient or more stable on SD1.5/SDXL-style UNets. +- Benefits: architecture-aware and guarded against obvious misuse. +- Trade-offs: not universal; adds another patching layer and can be brittle if architecture assumptions drift. +- Evidence: `src/Core/Pipeline.py`, `src/hidiffusion/msw_msa_attention.py`, `src/Core/AbstractModel.py`, `src/Core/Models/SD15Model.py`, `src/Core/Models/SDXLModel.py`. + +## Model Compilation, Precision, And Memory Optimizations + +### Stable-Fast + +- Status: `integrated, conditional` +- Purpose: trace and wrap UNet execution to reduce Python overhead and optionally use CUDA graph behavior. +- Implementation in LightDiffusion-Next: `src/StableFast/StableFast.py` builds a lazy trace module around the model function and stores compiled modules in a cache keyed by converted kwargs; `Pipeline._apply_optimizations()` applies it when `stable_fast` is enabled. +- Project integration: only model types that advertise `supports_stable_fast=True` can use it. Flux2 explicitly opts out at the capability layer. +- Effect: faster repeated UNet execution when the optional `sfast` dependency is present and shapes stay compatible enough for compilation reuse. +- Benefits: capability-gated, optional dependency handled defensively, integrated into the core optimization application phase. +- Trade-offs: dependency-sensitive, compilation overhead can dominate short runs, CUDA graph behavior is less flexible. +- Evidence: `src/StableFast/StableFast.py`, `src/Core/Pipeline.py`, `src/Core/Models/SD15Model.py`, `src/Core/Models/SDXLModel.py`, `src/Core/Models/Flux2KleinModel.py`. + +### `torch.compile` + +- Status: `integrated, optional` +- Purpose: rely on PyTorch compiler paths instead of Stable-Fast. +- Implementation in LightDiffusion-Next: `src/Device/Device.py::compile_model()` defaults to `max-autotune-no-cudagraphs`; `src/Core/AbstractModel.py::apply_torch_compile()` applies it to the top-level module or diffusion submodule when possible. +- Project integration: the optimization is mutually exclusive with Stable-Fast in the main pipeline. +- Effect: compiler-based speedups with a safer default mode than more fragile CUDA-graph-heavy settings. +- Benefits: built on standard PyTorch, tested for safe default mode. +- Trade-offs: compiler behavior is environment-dependent; still vulnerable to dynamic-shape and dynamic-state limitations. +- Evidence: `src/Device/Device.py`, `src/Core/AbstractModel.py`, `src/Core/Pipeline.py`, `tests/unit/test_fp8_compile.py`. + +### VAE compile, tiled path, and transfer tuning + +- Status: `integrated` +- Purpose: speed up VAE encode/decode, reduce overhead, and avoid OOM by choosing tiled or batched paths. +- Implementation in LightDiffusion-Next: `VariationalAE.VAE` compiles the decoder on first use, runs decode/encode under `torch.inference_mode()`, uses channels-last where useful, chooses tiled fallback when memory is tight, and uses non-blocking transfers. +- Project integration: this is automatic. Callers do not opt in. +- Effect: faster VAE stages, less repeated Python/autograd overhead, and better robustness under constrained memory. +- Benefits: always enabled and directly applied in the decode and encode hot path. +- Trade-offs: decoder compile still depends on `torch.compile` availability; tiling adds complexity and can affect throughput at small sizes. +- Evidence: `src/AutoEncoders/VariationalAE.py`. + +### BF16/FP16 automatic dtype selection + +- Status: `integrated, conditional` +- Purpose: pick a lower-precision working dtype that matches the hardware and model constraints. +- Implementation in LightDiffusion-Next: `src/Device/Device.py` contains the dtype selection logic for UNet, text encoder, and VAE devices/dtypes, including bf16 support checks and fallback rules. +- Project integration: loaders and patchers consult these helpers when deciding how to instantiate and place components. +- Effect: reduced memory footprint and better arithmetic throughput on modern hardware. +- Benefits: broad, centralized policy. +- Trade-offs: heuristic; wrong hardware assumptions can reduce numerical stability or disable a faster path. +- Evidence: `src/Device/Device.py`, `src/Model/ModelPatcher.py`, `src/FileManaging/Loader.py`. + +### FP8 weight quantization + +- Status: `integrated, conditional` +- Purpose: store weights in FP8 while casting them back to the input dtype during execution. +- Implementation in LightDiffusion-Next: `AbstractModel.apply_fp8()` hardware-gates support using `Device.is_fp8_supported()`, rewrites eligible weights to FP8, and enables runtime cast behavior on `CastWeightBiasOp` modules. The lower-level `ModelPatcher.weight_only_quantize()` also supports FP8-style quantization. +- Project integration: it is available through generation settings and also used in Flux2 load paths when appropriate. +- Effect: lower model weight memory with an execution path that avoids dtype-mismatch crashes. +- Benefits: tested explicitly, integrates with cast-aware modules, useful for large models. +- Trade-offs: hardware-gated; quality/performance trade-offs depend on model and layer mix. +- Evidence: `src/Core/AbstractModel.py`, `src/Device/Device.py`, `src/Model/ModelPatcher.py`, `tests/unit/test_fp8_compile.py`. + +### NVFP4 weight quantization + +- Status: `integrated, optional` +- Purpose: use a more aggressive 4-bit weight-only format to reduce memory further than FP8. +- Implementation in LightDiffusion-Next: both `AbstractModel.apply_nvfp4()` and `ModelPatcher.weight_only_quantize("nvfp4")` quantize supported weights, store scale buffers, and enable runtime casting/dequantization. +- Project integration: the quantization path is used most clearly in Flux2/Klein loading, but the abstract model path also exists for supported models. +- Effect: significant memory reduction at the cost of more aggressive approximation. +- Benefits: strongest memory reduction path in the repo. +- Trade-offs: more invasive than FP8, more likely to affect quality, and only applies to some weight shapes. +- Evidence: `src/Core/AbstractModel.py`, `src/Model/ModelPatcher.py`, `src/Utilities/Quantization.py`, `tests/test_nvfp4.py`, `tests/test_nvfp4_integration.py`. + +### Flux2 load-time weight-only quantization + +- Status: `integrated, conditional` +- Purpose: automatically quantize large Flux2 diffusion and Klein text encoder weights during loading when the configuration or hardware path calls for it. +- Implementation in LightDiffusion-Next: `Flux2KleinModel.load()` selects a quantization format and applies weight-only quantization to the diffusion model; `_load_klein_text_encoder()` applies the same idea to the text encoder before offloading it back to CPU. +- Project integration: Flux2 is the clearest example in the codebase where quantization is implemented as a first-class loading strategy rather than as a generic capability alone. +- Effect: keeps a large Flux2/Klein stack usable on lower-VRAM systems than an uncompressed load would allow. +- Benefits: integrated, architecture-specific, and directly aligned with large-model VRAM constraints. +- Trade-offs: tightly coupled to Flux2/Klein assumptions; not equivalent to a universally available quantized-mode toggle. +- Evidence: `src/Core/Models/Flux2KleinModel.py`. + +### ToMe + +- Status: `integrated, optional` +- Purpose: merge similar tokens to reduce attention workload in UNet-based models. +- Implementation in LightDiffusion-Next: `ModelPatcher.apply_tome()` applies and removes `tomesd` patches; `Pipeline._apply_optimizations()` applies it only when the model capabilities allow it. +- Project integration: SD1.5 and SDXL advertise `supports_tome=True`; Flux2 advertises `False`. +- Effect: lower attention cost on supported UNet models, particularly at higher token counts. +- Benefits: explicitly capability-gated, integrated into the core optimization phase. +- Trade-offs: optional dependency, UNet-only in current practice, and quality can soften if pushed too aggressively. +- Evidence: `src/Model/ModelPatcher.py`, `src/Core/Pipeline.py`, capability declarations in `src/Core/Models/*`, `tests/unit/test_tome_fix.py`. + +### DeepCache + +- Status: `integrated, optional, implementation-specific` +- Purpose: reuse work across denoising steps rather than running a full forward pass every time. +- Implementation in LightDiffusion-Next: `ApplyDeepCacheOnModel.patch()` clones the model and wraps its UNet function. On cache-update steps it runs the model normally and stores the output; on reuse steps it returns the cached output directly. +- Project integration: the main pipeline applies it from `_apply_optimizations()` when `deepcache_enabled` is true and the model advertises support. +- Effect: fewer full model computations on reuse steps, trading some fidelity for speed. +- Benefits: live integrated path, simple integration model, and capability gating. +- Trade-offs: the implementation works at whole-output reuse granularity rather than a finer-grained internal block reuse strategy, so its speed/fidelity profile is comparatively coarse. +- Evidence: `src/WaveSpeed/deepcache_nodes.py`, `src/Core/Pipeline.py`, `src/Core/AbstractModel.py`, `src/Core/Models/SD15Model.py`, `src/Core/Models/SDXLModel.py`, `tests/test_core_functionalities.py`. + +### First Block Cache for Flux + +- Status: `codebase groundwork` +- Purpose: cache downstream transformer work when the first-block residual indicates the state has not changed much. +- Implementation in LightDiffusion-Next: `src/WaveSpeed/first_block_cache.py` contains cache contexts and patch builders for both UNet-like and Flux-like forward paths. +- Project integration: the module provides the machinery for a Flux-oriented first-block caching path. In the current project flow, the directly surfaced caching path is DeepCache, while this module remains groundwork for a more specialized integration. +- Effect: establishes the components needed for a transformer-oriented cache path in the codebase. +- Benefits: nontrivial implementation foundation already exists. +- Trade-offs: it is not yet surfaced as a broad standard option in the same way as the main integrated optimizations. +- Evidence: `src/WaveSpeed/first_block_cache.py`. + +## Memory Management And Serving Optimizations + +### Low-VRAM partial loading and offload policy + +- Status: `integrated` +- Purpose: keep only the amount of model state in VRAM that current free memory allows, offloading the rest. +- Implementation in LightDiffusion-Next: `cond_util.prepare_sampling()` calls `Device.load_models_gpu(..., force_full_load=False)`; `Device.load_models_gpu()` computes low-VRAM budgets and delegates partial loading to `ModelPatcher.patch_model_lowvram()` and `partially_load()`. +- Project integration: this is a core loading behavior, not a side option. Text encoder and VAE also have explicit offload-device helpers. +- Effect: keeps generation viable on limited VRAM systems and reduces full reload pressure. +- Benefits: central to memory behavior in constrained environments, architecture-aware, and tied into checkpoint, text encoder, and VAE device policy. +- Trade-offs: more complex state management; partial loading can increase latency and complicate debugging. +- Evidence: `src/cond/cond_util.py`, `src/Device/Device.py`, `src/Model/ModelPatcher.py`. + +### Async transfer helpers and pinned checkpoint tensors + +- Status: `integrated, infrastructure-level` +- Purpose: reduce CPU<->GPU transfer cost with asynchronous copies, streams, and pinned host memory. +- Implementation in LightDiffusion-Next: `Device.cast_to()` can issue transfers on offload streams; checkpoint tensors are pinned on CUDA loads in `util.load_torch_file()`; VAE encode/decode uses non-blocking transfers. +- Project integration: these mechanisms appear most clearly in checkpoint loading, model movement, and VAE data flow. Some parts act as general transfer infrastructure rather than as a single user-facing optimization toggle. +- Effect: faster host/device movement and less transfer-induced stalling in hot paths that actually use the helpers. +- Benefits: useful on CUDA systems, especially during model load and VAE stages. +- Trade-offs: integration is uneven; some helper functions look broader than their current call footprint. +- Evidence: `src/Device/Device.py`, `src/Utilities/util.py`, `src/AutoEncoders/VariationalAE.py`. + +### Request coalescing and queue batching + +- Status: `integrated` +- Purpose: batch compatible API requests together so the backend does fewer larger pipeline invocations. +- Implementation in LightDiffusion-Next: `server.py::GenerationBuffer` groups pending requests by a signature that includes model, size, scheduler, sampler, steps, multiscale settings, and other batch-level properties. +- Project integration: the worker chooses the oldest eligible group, optionally waits for more arrivals, flattens per-request samples into one pipeline call, and later remaps saved results back to request futures. +- Effect: better throughput and GPU utilization for concurrent API use. +- Benefits: real server-level optimization, clearly implemented, includes observability-oriented logs. +- Trade-offs: requires careful grouping keys; incompatible request options fragment batching opportunities. +- Evidence: `server.py`. + +### Singleton policy, large-group chunking, and image-save guardrails + +- Status: `integrated` +- Purpose: prevent batching from hurting latency for lone requests, and prevent oversized coalesced batches from exploding decode/save paths. +- Implementation in LightDiffusion-Next: `LD_BATCH_WAIT_SINGLETONS` controls whether singletons wait; `LD_MAX_IMAGES_PER_GROUP` and `ImageSaver.MAX_IMAGES_PER_SAVE` drive chunking; large groups are split into smaller sequential pipeline runs. +- Project integration: the server keeps the coalescing optimization from turning into pathological giant save/decode operations, and tests cover the chunking behavior. +- Effect: better tail latency for single requests and more stable handling of large batched workloads. +- Benefits: directly addresses operational failure modes in large batched workloads. +- Trade-offs: chunking reduces some batching benefits; many environment variables affect behavior. +- Evidence: `server.py`, `src/FileManaging/ImageSaver.py`, `tests/unit/test_generation_buffer_chunking.py`, `docs/quirks.md`. + +### Next-model prefetch + +- Status: `integrated` +- Purpose: while one batch is running, read the next checkpoint into CPU RAM if the queued next batch needs a different model. +- Implementation in LightDiffusion-Next: `GenerationBuffer._look_ahead_and_prefetch()` resolves the next checkpoint, loads it via `util.load_torch_file()` on a background task, and stores it in `ModelCache` as a prefetched state dict. +- Project integration: the next load can reuse the prefetched state dict through `util.load_torch_file()` before the cache entry is cleared. +- Effect: overlaps some future checkpoint load cost with current generation work. +- Benefits: server-side latency hiding with minimal interface impact. +- Trade-offs: only helps when queued work is predictable; increases CPU RAM usage. +- Evidence: `server.py`, `src/Device/ModelCache.py`, `src/Utilities/util.py`. + +### Keep-models-loaded cache + +- Status: `integrated` +- Purpose: keep recently used checkpoints and sampling models resident instead of cleaning them up after every request. +- Implementation in LightDiffusion-Next: `ModelCache` stores checkpoints, TAESD models, sampling models, and the keep-loaded policy; `server.py` temporarily applies the request's `keep_models_loaded` directive for a group. +- Project integration: when enabled, main models are retained and only auxiliary control models are cleaned up aggressively. +- Effect: lower warm-start cost between related generations and less repetitive reload churn. +- Benefits: simple end-user behavior for a meaningful latency/memory trade-off. +- Trade-offs: consumes more VRAM/RAM; can make memory pressure less predictable on multi-user servers. +- Evidence: `src/Device/ModelCache.py`, `server.py`. + +### In-memory PNG byte buffer + +- Status: `integrated` +- Purpose: return API images from memory instead of reading them back from disk after save. +- Implementation in LightDiffusion-Next: `ImageSaver` can store encoded PNG bytes in `_image_bytes_buffer`; `server.py` first calls `pop_image_bytes()` when fulfilling request futures. +- Project integration: batched pipeline runs can still save images normally while the API path avoids a disk round-trip for the response payload. +- Effect: lower response latency and less unnecessary disk I/O for served images. +- Benefits: directly reduces response-path disk I/O in API-serving scenarios. +- Trade-offs: consumes temporary RAM; only helps when the buffer path is actually populated. +- Evidence: `src/FileManaging/ImageSaver.py`, `server.py`. + +### TAESD preview pacing and preview fidelity control + +- Status: `integrated, conditional` +- Purpose: keep live previews useful without letting preview generation dominate sampling time. +- Implementation in LightDiffusion-Next: `SamplerCallback` caches preview settings, only triggers previews at a coarse interval, and runs preview work on a background thread; the server also applies per-request preview fidelity presets (`low`, `balanced`, `high`). +- Project integration: previews are generated only when previewing is enabled, and the preview cadence is adaptive to total step count. +- Effect: live feedback with bounded preview overhead. +- Benefits: explicit pacing, non-blocking thread model, request-level fidelity override. +- Trade-offs: still extra work during sampling; fidelity presets are intentionally coarse. +- Evidence: `src/sample/BaseSampler.py`, `src/AutoEncoders/taesd.py`, `server.py`, preview tests under `tests/e2e` and `tests/integration/api`. + +## Integration Notes + +These notes highlight how several optimizations are currently integrated and used inside the project. + +### 1. Flux-oriented first block caching + +- The codebase contains a dedicated `src/WaveSpeed/first_block_cache.py` module with cache contexts and patch builders for Flux-oriented paths. +- In the current optimization stack, the directly surfaced caching path is DeepCache, while First Block Cache remains implementation groundwork for a more specialized integration. +- This establishes the core components for a transformer-oriented cache path even though it is not yet surfaced as a primary standard option. + +### 2. DeepCache reuse granularity + +- DeepCache is integrated through `src/WaveSpeed/deepcache_nodes.py` and is applied from the main pipeline when enabled. +- In this project, it works by reusing prior denoiser outputs on designated reuse steps. +- This yields a clear speed-fidelity profile based on output reuse rather than on finer-grained internal block caching. + +### 3. Conditioning batching control + +- Conditioning batching is centered in `src/cond/cond.py::calc_cond_batch()`, where compatible condition chunks are packed and concatenated. +- The `batched_cfg` request field participates as request-side control metadata around this behavior. +- In operation, the batching outcome is therefore shaped mainly by the central conditioning logic rather than by a standalone external switch. + +### 4. GPU attention backend selection + +- Attention backend selection is hardware- and build-aware, with the runtime choosing among SpargeAttn, SageAttention, xformers, and PyTorch SDPA based on capability checks. +- The exact backend used in practice therefore depends on the active GPU generation, dependencies, and runtime configuration. +- Backend acceleration is therefore largely automatic from the user perspective while remaining environment-specific in implementation. + +### 5. Prompt cache behavior + +- Prompt caching is implemented as a global dict-backed cache keyed by prompt hash and CLIP identity. +- The cache prunes old entries once it exceeds its configured size threshold. +- In operation, it primarily benefits repeated-prompt workflows such as seed sweeps and prompt iteration. + +## Conclusion + +LightDiffusion-Next uses a layered optimization strategy spanning runtime kernels, scheduling, guidance logic, precision and memory control, model patching, and server-side throughput management. + +- The core operational stack is built around AYS scheduling, attention backend selection, conditioning batching, low-VRAM loading policy, prompt caching, VAE tuning, and request coalescing. +- Optional paths such as Stable-Fast, `torch.compile`, ToMe, DeepCache, multiscale sampling, and quantization extend that stack for specific hardware targets, model families, and workload profiles. +- The serving layer is a first-class component of the performance model, with batching, chunking, prefetching, keep-loaded caches, and in-memory responses contributing directly to end-to-end latency and throughput. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000000000000000000000000000000000000..f40b5681fec630e5bde28fdf232e5a62c0c74cfd --- /dev/null +++ b/docs/index.md @@ -0,0 +1,44 @@ +# LightDiffusion-Next + +LightDiffusion-Next is a refactored and performance-first Stable Diffusion stack that bundles a modern Streamlit UI, an optional Gradio web app, a batched FastAPI backend and highly tuned inference primitives such as Stable-Fast, SageAttention and WaveSpeed caching. + +## Why pick LightDiffusion-Next + +LightDiffusion-Next is built to handle day-to-day generation workloads on consumer GPUs while still scaling up to multi-user servers. + +- **Fast by default.** Stable-Fast compilation, SageAttention, SpargeAttn and WaveSpeed caching are wired in so you can hit top-tier it/s without manual patching. +- **Multiple front-doors.** Choose between the Streamlit control room, a Gradio web UI (great for Spaces) or the programmable FastAPI queue for integrations. +- **Feature complete.** Txt2Img, Img2Img, Flux pipelines, AutoHDR, TAESD previews, prompt enhancement through Ollama, multi-scale diffusion with presets, LoRA mixing and automatic detailing are all available out of the box. +- **Operations friendly.** Docker images, GPU-aware batched serving, model caching controls and observability endpoints make it easy to deploy and monitor. + +## What ships in the box + +- 🚀 **Streamlined UI** with live previews, history, presets, interrupt/resume controls and automatic metadata tagging. +- 🧠 **Prompt toolkit** including reusable negative embeddings, multi-concept weighting, prompt enhancement and prompt history. +- 🧩 **Modular pipeline** that routes SD1.5, SDXL-inspired workflows and quantized Flux models through a single code path with per-sample overrides for HiresFix, ADetailer or Img2Img. +- 🛠️ **Production API** powered by FastAPI with smart request coalescing, telemetry endpoints and base64 image responses ready for bots or creative tooling. +- 📦 **Deployment artifacts** such as Dockerfiles, docker-compose, run scripts for Windows, configurable GPU architecture flags and optional Ollama/Stable-Fast builds. + +## Quick pathways + +- [Installation](installation.md) — pick Docker, Windows batch or manual Python setup. +- [First run & UI tour](usage.md) — learn the Streamlit layout, generation controls and history tools. +- [Workflow playbook](examples.md) — step through Txt2Img, Flux, Img2Img and API recipes. +- [Performance optimizations](optimizations.md) — understand SageAttention, Stable-Fast, WaveSpeed caching and the new AYS scheduler for 2-5x speedup. +- [Align Your Steps](ays-scheduler.md) — learn about AYS scheduler and prompt caching for additional speedup. +- [Prompt Caching](prompt-caching.md) — deep dive into prompt attention caching mechanics and tuning. +- [Performance tuning](quirks.md) — squeeze out extra throughput or reduce VRAM usage. +- [Architecture](architecture.md) — understand how the UI, pipeline and server cooperate. +- [REST & automation](api.md) — integrate Discord bots, automations or other clients. + +## Supported environments at a glance + +- NVIDIA GPUs with CUDA 12.x drivers. SageAttention and SpargeAttn availability is detected at runtime and depends on installed kernels, drivers and GPU compute capability; some kernels may be disabled on newer CUDA runtimes (for example CUDA 12+). RTX 50xx and newer cards may use SageAttention + Stable-Fast where supported. +- Windows 10/11, Ubuntu 22.04+ and containerized deployments via Docker with NVIDIA Container Toolkit. +- Optional CPU-only mode for experimentation (no Stable-Fast/SageAttention speed-ups). + +## Where to head next + +- Start with [Installation](installation.md) to get your environment ready. +- Drop into the [Streamlit UI guide](usage.md) for a tour of generation features and presets. +- Explore [Architecture](architecture.md) when you are ready to customize or embed LightDiffusion-Next in larger systems. \ No newline at end of file diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000000000000000000000000000000000000..4e076df72ea0d1405ff8ceb1c29946ec3099676c --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,161 @@ +# Installation & Setup + +LightDiffusion-Next can run locally on Windows or Linux, inside Docker, or on cloud GPUs. This page walks you through the supported installation paths and the assets you must download before your first generation. + +## Hardware & software requirements + +The project is tuned for NVIDIA GPUs and CUDA 12.x drivers, but it also supports AMD GPUs with ROCm and Apple Silicon with Metal Performance Shaders (MPS). See [ROCm and Metal/MPS Support](rocm-metal-support.md) for platform-specific installation instructions. + +- **Operating system:** Windows 10/11, Ubuntu 22.04+, macOS 12.3+ (for Apple Silicon), or any distro supported by NVIDIA Container Toolkit. +- **Python:** 3.10.x. The run scripts create a virtual environment automatically. +- **GPU:** + - **NVIDIA:** Card with at least compute capability 8.0 (Ampere) for SageAttention/SpargeAttn. RTX 50 series (compute 12.0) runs with SageAttention + Stable-Fast. + - **AMD:** RDNA 2+ or CDNA architectures with ROCm 5.0+. See [ROCm Support](rocm-metal-support.md#rocm-support-amd-gpus). + - **Apple Silicon:** M1/M2/M3 series with macOS 12.3+. See [Metal/MPS Support](rocm-metal-support.md#metalmps-support-apple-silicon). +- **VRAM:** 6 GB minimum (12 GB recommended) for SD1.5 workflows. Flux quantized pipelines require 16 GB+ for comfortable batching. +- **Disk space:** ~15 GB for dependencies plus your checkpoints, LoRAs and flux assets. + +## Choose an installation path + +- [Windows quick start](#windows-quick-start-runbat) +- [Linux or WSL2 manual setup](#linuxwsl2-manual-setup) +- [Containerized deployment](#docker-and-containers) +- [Headless server API](#running-only-the-fastapi-server) + +### Windows quick start (`run.bat`) + +The root repository ships with a convenience script that handles environment creation, dependency installation via `uv`, GPU detection and launching the Streamlit UI. + +1. Install the latest [Python 3.10](https://www.python.org/downloads/release/python-3100/) build and ensure `python` is on your `PATH`. +2. Install the [NVIDIA CUDA 12 runtime driver](https://developer.nvidia.com/cuda-downloads) that matches your GPU. +3. Clone the repository and place your checkpoints in `include/checkpoints` (see [Model assets](#model-assets)). +4. Double-click `run.bat` from a terminal. The script will: + + - Create `.venv` (if it does not exist) and upgrade `pip`. + - Install `uv` for fast dependency resolution. + - Detect an NVIDIA GPU via `nvidia-smi` and install the matching PyTorch wheels. + - Install all requirements and start Streamlit at `http://localhost:8501`. + +5. When you are done, close the terminal to stop the UI. The virtual environment is reusable across runs. + +> **Tip:** To launch the Gradio UI instead, activate `.venv` and run `python app.py`. + +### Linux/WSL2 manual setup + +1. Install system dependencies: + + ```bash + sudo apt update && sudo apt install python3.10 python3.10-venv python3-pip build-essential git + ``` + + > If you plan to use **AutoHDR** (ICC-based color transforms), ensure Little CMS (lcms2) is installed so Pillow can build profile transforms. On Debian/Ubuntu: + ```bash + sudo apt-get install -y liblcms2-2 liblcms2-dev + pip install --upgrade --force-reinstall pillow + ``` + + +2. (Optional) Install the [NVIDIA CUDA 12 toolkit](https://developer.nvidia.com/cuda-toolkit-archive) so SageAttention/SpargeAttn can compile native extensions. +3. Create and activate a virtual environment: + + ```bash + python3 -m venv .venv + source .venv/bin/activate + pip install --upgrade pip uv + ``` + +4. Install PyTorch and core dependencies: + + ```bash + uv pip install --index-url https://download.pytorch.org/whl/cu128 torch torchvision "triton>=2.1.0" + uv pip install -r requirements.txt + ``` + +5. Launch the Streamlit UI: + + ```bash + streamlit run streamlit_app.py --server.address=0.0.0.0 --server.port=8501 + ``` + + Use `python app.py` if you prefer the Gradio interface. + +6. Deactivate the environment with `deactivate` when finished. + +### Docker and containers + +Use Docker when you want an immutable runtime with SageAttention, SpargeAttn and Stable-Fast prebuilt. + +1. Install [Docker Desktop](https://www.docker.com/products/docker-desktop/) or Docker Engine with the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html). +2. Clone the repository and review `docker-compose.yml`. Adjust: + + - `TORCH_CUDA_ARCH_LIST` if you only target a specific GPU architecture. + - `INSTALL_STABLE_FAST` and `INSTALL_OLLAMA` build arguments if you want Stable-Fast or the Ollama prompt enhancer baked into the image. + - Volume mounts for `output/` and the `include/*` directories where you store checkpoints, LoRAs, embeddings and YOLO detectors. + +3. Build and start the stack: + + ```bash + docker-compose up --build + ``` + + Streamlit is exposed on `http://localhost:8501` by default; Gradio is mapped to port `7860` and can be enabled by setting `UI_FRAMEWORK=gradio`. + +4. To rebuild with a different GPU architecture or optional component: + + ```bash + docker-compose build --build-arg TORCH_CUDA_ARCH_LIST="9.0" --build-arg INSTALL_STABLE_FAST=1 + ``` + +### Running only the FastAPI server + +If you want to integrate LightDiffusion-Next into automation pipelines or Discord bots, run the backend without launching a UI. + +1. Follow any of the setup methods above. +2. Run: + + ```bash + uvicorn server:app --host 0.0.0.0 --port 7861 + ``` + +3. Use the [REST API reference](api.md) to submit generation jobs via `POST /api/generate` and inspect queue health via `GET /api/telemetry`. + +## Model assets + +LightDiffusion-Next does not bundle model weights. Place your assets into the `include/` tree before you start generating. + +- `include/checkpoints/` — SD1.5 style `.safetensors` checkpoints (e.g. Meina V10, DreamShaper). The default pipeline expects a file named `Meina V10 - baked VAE.safetensors` unless you override it. +- `include/vae/ae.safetensors` — Flux VAE (download from [black-forest-labs/FLUX.1-schnell](https://huggingface.co/black-forest-labs/FLUX.1-schnell)). Required for Flux mode. +- `include/loras/` — LoRA adapters loaded from the UI or CLI. +- `include/embeddings/` — Negative prompt embeddings such as `EasyNegative`, `badhandv4`. +- `include/yolos/` — YOLO detectors used by ADetailer (`person_yolov8m-seg.pt`, `face_yolov9c.pt`). +- `include/ESRGAN/` — RealESRGAN models leveraged by UltimateSDUpscale in Img2Img workflows. +- `include/sd1_tokenizer/` — Tokenizer files for SD1.x. The repository already includes the defaults. + +Store generated outputs under `output/` (separated into Classic, Flux, Img2Img, HiresFix and ADetailer sub-folders). The folders are created automatically during the first run. + +## Optional accelerations + +- **Stable-Fast** — 70% faster SD1.5 inference through UNet compilation. Set `INSTALL_STABLE_FAST=1` in Docker or pass `--stable-fast` in the CLI/UI to compile on demand. Compilation adds a one-time warm-up cost. +- **SageAttention** — INT8 attention kernels with 15% speedup and lower VRAM use. Built automatically in Docker images; on bare metal, clone [SageAttention](https://github.com/thu-ml/SageAttention) and run `pip install -e . --no-build-isolation` inside your environment. +- **SpargeAttn** — Sparse attention kernels with 40–60% speedup (compute 8.0–9.0 GPUs only). Build from [SpargeAttn](https://github.com/thu-ml/SpargeAttn) using `TORCH_CUDA_ARCH_LIST="8.9"` or similar. +- **Ollama prompt enhancer** — Install [Ollama](https://ollama.com/) and pull `qwen3:0.6b`. Set `PROMPT_ENHANCER_MODEL=qwen3:0.6b` before launching LightDiffusion-Next to enable the automatic prompt rewrite toggle. + +## Verify your installation + +1. Start the UI or FastAPI server. +2. Watch the startup logs — the initialization progress bar runs the dependency download routine (`CheckAndDownload`) and loads the default checkpoint. +3. Generate a 512×512 image with the default prompt. The status bar shows timing and the output appears in `output/Classic`. +4. Confirm the telemetry endpoint is reachable: + + ```bash + curl http://localhost:7861/health + curl http://localhost:7861/api/telemetry + ``` + +## Updating or rebuilding + +- Pull the latest Git changes and rerun `uv pip install -r requirements.txt` in the virtual environment. +- For Docker users, rebuild with `docker-compose build --no-cache` to pick up updates. +- If you upgraded your GPU driver or CUDA toolkit, delete `~/.cache/torch_extensions` to force SageAttention/SpargeAttn to recompile. + +You are now ready to explore the [UI guide](usage.md) and start generating. \ No newline at end of file diff --git a/docs/optimizations.md b/docs/optimizations.md new file mode 100644 index 0000000000000000000000000000000000000000..c1f704e1ea12b4a6ce947799d6df0fc1eba36d9b --- /dev/null +++ b/docs/optimizations.md @@ -0,0 +1,262 @@ +# Performance Optimizations + +LightDiffusion-Next achieves its industry-leading inference speed through a layered stack of training-free optimizations that can be selectively enabled based on your hardware and quality requirements. This page provides an overview of each acceleration technique and links to detailed guides. + +For a detailed source-based report on what is implemented today, including server-side throughput optimizations and practical implementation notes, see the [Implemented Optimizations Report](implemented-optimizations-report.md). + +## Optimization Stack Overview + +The pipeline orchestrates six primary acceleration paths: + +| Technique | Type | Speedup | Quality Impact | Requirements | +|-----------|------|---------|----------------|---------------| +| [AYS Scheduler](#ays-scheduler) | Sampling schedule | ~2x | None/Better | All models | +| [Prompt Caching](#prompt-caching) | Embedding cache | 5-15% | None | All models | +| [SageAttention](#sageattention--spargeattn) | Attention kernel | Moderate | None | All CUDA GPUs | +| [SpargeAttn](#sageattention--spargeattn) | Sparse attention | Significant | Minimal | Compute 8.0-9.0 | +| [Stable-Fast](#stable-fast) | Graph compilation | Significant* | None | >8GB VRAM, batch jobs | +| [WaveSpeed](#wavespeed-caching) | Feature caching | High | Tunable | All models | + +*Speedup depends heavily on batch size and generation count + +These optimizations **work together** — enabling multiple techniques simultaneously can provide substantial cumulative speedup with tunable quality trade-offs. + +## Quick Comparison + +### AYS Scheduler + +**What it does:** Uses research-backed optimal timestep distributions that allow equivalent quality in approximately half the steps. Instead of uniform sigma spacing, AYS concentrates samples on noise levels that contribute most to image formation. + +**When to use:** +- Always recommended for SD1.5, SDXL, and Flux models +- Txt2Img generation +- Production workflows where speed matters +- Any scenario where you'd normally use 20+ steps + +**Trade-offs:** Images will differ slightly from standard schedulers (different sampling path), but quality is equivalent or better. Not ideal when exact reproduction of old results is required. + +[→ Full AYS Scheduler guide](ays-scheduler.md) + +--- + +### Prompt Caching + +**What it does:** Caches CLIP text embeddings for prompts that have been encoded before. When generating multiple images with the same or similar prompts, embeddings are retrieved from cache instead of being recomputed. + +**When to use:** +- Batch generation with same prompt +- Testing different seeds or settings +- Iterative prompt refinement +- Any workflow with repeated prompts + +**Trade-offs:** None — minimal memory overhead (~50-200MB), negligible CPU cost, automatically enabled by default. + +[→ Full Prompt Caching guide](prompt-caching.md) + +--- + +### SageAttention & SpargeAttn {#sageattention--spargeattn} + +**What it does:** Replaces PyTorch's default scaled dot-product attention with highly optimized CUDA kernels. SageAttention uses INT8 quantization for key/value tensors while maintaining FP16 query precision. SpargeAttn extends this with dynamic sparsity pruning, skipping redundant attention computations. + +**When to use:** +- Always enable SageAttention if available (no quality loss, pure speed gain) +- SpargeAttn for maximum speed on supported hardware (RTX 30xx/40xx, A100, H100) +- Both work seamlessly with all samplers, LoRAs and post-processing stages + +**Trade-offs:** None for SageAttention. SpargeAttn may introduce subtle texture variations at very high sparsity thresholds (default is conservative). + +[→ Full SageAttention/SpargeAttn guide](sageattention.md) + +--- + +### CFG Samplers {#cfg-samplers} + +CFG++ Samplers are advanced sampling algorithms that incorporate Classifier-Free Guidance directly into the sampling process, providing better quality and stability compared to standard CFG. + +--- + +### Multi-Scale Diffusion {#multi-scale} + +Multi-Scale Diffusion optimizes performance by processing images at multiple resolutions during generation, reducing computation for high-resolution areas. + +**When to use:** +- High-resolution generation (>1024px) +- When memory is limited +- For faster previews + +**Trade-offs:** May reduce detail in fine areas. + +**Note:** In most cases, Multi-Scale Diffusion in quality mode gives better results than standard diffusion while giving a small speedup (this is explained by the upsampling process). + +--- + +### Stable-Fast + +**What it does:** JIT-compiles the UNet diffusion model into optimized TorchScript with optional CUDA graphs. The first forward pass traces execution, caches kernel launches and fuses operators for reduced overhead. + +**When to use:** +- **Systems with >8GB VRAM** (preferably 12GB+) +- Batch jobs or workflows generating 50+ images with identical settings +- Long-running operations where 30-60s compilation amortizes over time +- Fixed resolutions and batch sizes + +**When NOT to use:** +- Normal 20-step single image generation (compilation overhead > speedup gains) +- Systems with <8GB VRAM +- Flux workflows (different architecture) +- Quick prototyping or frequent model/resolution changes + +**Trade-offs:** Compilation time on first run (30-60s), VRAM overhead (~500MB), reduced flexibility for dynamic shapes. + +[→ Full Stable-Fast guide](stablefast.md) + +--- + +### WaveSpeed Caching + +**What it does:** Exploits temporal redundancy in diffusion processes by reusing work across denoising steps. In the current project stack this primarily means DeepCache on supported UNet models, with additional Flux-oriented cache groundwork present in the codebase. + +1. **DeepCache** — Reuses prior denoiser outputs on selected steps in UNet models (SD1.5, SDXL) +2. **First Block Cache (FBCache)** — Flux-oriented cache machinery available for specialized integration work + +**When to use:** +- Any workflow where you can tolerate slight smoothing in exchange for 2-3x speedup +- Combine with conservative cache intervals (2-3) for minimal quality loss +- Works alongside SageAttention and Stable-Fast + +**Trade-offs:** Reduced fine detail if interval is too high, slight VRAM increase for cached tensors. + +[→ Full WaveSpeed guide](wavespeed.md) + +--- + +## Priority & Fallback System + +LightDiffusion-Next automatically selects the best available attention backend at runtime: + +``` +SpargeAttn > SageAttention > xformers > PyTorch SDPA +``` + +If a kernel fails (e.g., unsupported head dimension), the system gracefully falls back to the next option. You can force PyTorch SDPA by setting `LD_DISABLE_SAGE_ATTENTION=1` for debugging. + +Stable-Fast and WaveSpeed are opt-in toggles controlled via the UI or REST API. + +## Recommended Configurations + +### Maximum Speed - Batch Jobs (SD1.5, >8GB VRAM, 50+ images) +```yaml +stable_fast: true # Only for batch operations +sageattention: auto # or spargeattn if available +deepCache: + enabled: true + interval: 3 + depth: 2 +``` +**Expected:** Maximum speedup for batch operations, some quality loss +**Note:** Disable stable_fast for single 20-step generations + +### Balanced - Quick Generation (SD1.5, any VRAM) +```yaml +scheduler: ays # NEW: Use AYS for 2x speedup +steps: 10 # Reduced from 20 (same quality with AYS) +stable_fast: false # Disabled for normal generations +sageattention: auto +prompt_cache_enabled: true # Enabled by default +deepcache: + enabled: true + interval: 2 + depth: 1 +``` +**Expected:** ~2-3x speedup with minimal quality loss +**Note:** AYS scheduler provides the main speedup; enable stable_fast only for batch jobs (50+ images) + +### Quality-First (Flux) +```yaml +scheduler: ays_flux # NEW: Optimized for Flux models +steps: 10 # Reduced from 15 (same quality with AYS) +stable_fast: false # not supported +sageattention: auto +prompt_cache_enabled: true +deepcache: + enabled: true + interval: 2 +``` +**Expected:** ~2x speedup with minimal quality impact + +### Production API - High Volume (>8GB VRAM) +```yaml +stable_fast: true # Only for sustained high-volume APIs +sageattention: auto +deepCache: + enabled: false # avoid variability across batch sizes +keep_models_loaded: true +``` +**Expected:** Consistent latency for repeated identical requests +**Note:** For low-volume or single-shot APIs, use `stable_fast: false` + +## Hardware-Specific Tips + +### RTX 30xx / 40xx (Ampere/Ada) +- Enable SpargeAttn for best results +- Stable-Fast only for batch jobs (disable for quick 20-step generations) +- Stable-Fast + SpargeAttn + DeepCache stacks well for long operations +- Watch VRAM — Stable-Fast graphs consume ~500MB + +### RTX 50xx (Blackwell) +- SageAttention only (SpargeAttn support pending) +- Stable-Fast works but recompiles for new CUDA arch +- DeepCache is your best additional speedup + +### A100 / H100 (Datacenter) +- SpargeAttn + Stable-Fast + aggressive WaveSpeed +- Prefer larger batch sizes to amortize kernel overhead +- Use CUDA graphs (`enable_cuda_graph=True` in Stable-Fast config) + +### Low VRAM (<8GB) +- **Always disable Stable-Fast** (requires >8GB VRAM) +- Use SageAttention (minimal overhead) +- Enable DeepCache with conservative intervals +- Set `vae_on_cpu=True` for HiRes workflows + +## Debugging & Profiling + +Check which optimizations are active: + +```bash +# View startup logs +cat logs/server.log | grep -i "using\|enabled" + +# Sample output: +# Using SpargeAttn (Sparse + SageAttention) cross attention +# Using SpargeAttn (Sparse + SageAttention) in VAE +# Stable-Fast compilation enabled +# DeepCache active: interval=3, depth=2 +``` + +Monitor telemetry: + +```bash +curl http://localhost:7861/api/telemetry | jq '.vram_usage_mb, .average_latency_ms' +``` + +Disable individual optimizations to isolate issues: + +```bash +export LD_DISABLE_SAGE_ATTENTION=1 # Forces PyTorch SDPA +export LD_DISABLE_STABLE_FAST=1 # Skips compilation +export LD_DISABLE_WAVESPEED=1 # Disables all caching +``` + +## Further Reading +- [AYS Scheduler Deep Dive](ays-scheduler.md) — Theory, implementation, quality tuning +- [Prompt Caching Deep Dive](prompt-caching.md) — Implementation details, cache management, performance impact +- [SageAttention & SpargeAttn Deep Dive](sageattention.md) — Installation, technical details, head dimension handling +- [Stable-Fast Compilation Guide](stablefast.md) — Configuration, CUDA graphs, troubleshooting +- [WaveSpeed Caching Strategies](wavespeed.md) — DeepCache vs FBCache, tuning parameters, compatibility matrix +- [Performance Tuning](quirks.md) — VRAM management, slow first runs, recompilation fixes + +--- + +Armed with this overview, dive into the technique-specific guides or experiment directly in the UI to find your optimal speed/quality balance. diff --git a/docs/prompt-caching.md b/docs/prompt-caching.md new file mode 100644 index 0000000000000000000000000000000000000000..e29e34b80a2c172fbd045efcaa7a933fc57b246c --- /dev/null +++ b/docs/prompt-caching.md @@ -0,0 +1,64 @@ +# Prompt Attention Caching + +### What It Does + +Caches CLIP text embeddings for prompts you've already encoded. When you reuse a prompt (or parts of it), the embedding is retrieved from cache instead of being recomputed. + +### When It Helps Most + +- Batch generation with same prompt +- Testing different seeds +- Incremental prompt refinement +- Generation sessions with repeated themes + +### Configuration + +**Enable/Disable** (default: enabled): +```python +from src.Utilities import prompt_cache + +# Enable (default) +prompt_cache.enable_prompt_cache(True) + +# Disable +prompt_cache.enable_prompt_cache(False) + +# Check status +stats = prompt_cache.get_cache_stats() +print(f"Hit rate: {stats['hit_rate']:.1%}") +``` + +**Cache Settings**: +- Maximum entries: 256 prompts before pruning +- Cache structure: global dict keyed by prompt hash and CLIP identity +- Memory usage: workload-dependent, estimated from cached embedding tensors +- Cache cleared on: restart, disable, or manual clear +- Automatic pruning: removes the oldest 25% of entries when the cache exceeds its limit + +### Viewing Cache Stats + +```python +from src.Utilities import prompt_cache + +# Print statistics +prompt_cache.print_cache_stats() + +# Output: +# ============================================================ +# Prompt Cache Statistics +# ============================================================ +# Status: Enabled +# Entries: 42 +# Size: ~85.3 MB +# Requests: 150 (hits: 108, misses: 42) +# Hit Rate: 72.0% +# ============================================================ +``` + +### Best Practices + +1. **Leave it enabled** - negligible overhead, significant gains +2. **Monitor hit rate** - should be >50% in typical workflows +3. **Clear cache** when switching models or major prompt changes +4. **Batch similar prompts** to maximize cache hits +5. **Expect global behavior** because the cache is shared across repeated prompt encodes rather than being scoped to a single generation session diff --git a/docs/quirks.md b/docs/quirks.md new file mode 100644 index 0000000000000000000000000000000000000000..da062c82f82532391830f522a06b1bef34c2d2bb --- /dev/null +++ b/docs/quirks.md @@ -0,0 +1,60 @@ +# Quirks & Troubleshooting + +This playbook highlights the most common operational quirks you may encounter while running LightDiffusion-Next and the quickest ways to resolve them. + +## GPU memory headaches + +| Symptom | Likely cause | Quick fixes | +| --- | --- | --- | +| `CUDA out of memory` during base diffusion | Resolution or batch too high | Drop to 512×512 or smaller, decrease batch to 1, disable HiresFix or AutoDetailer, prefer Euler/Karras samplers in **CFG++** mode | +| OOM triggered mid-way through HiRes | VRAM spikes when loading VAE/second UNet | Enable **Keep models loaded** (to avoid reloading) or run HiRes on CPU by toggling *VAE on CPU* in settings | +| Flux runs crash immediately | Missing Flux decoder or running on <16 GB VRAM | Place Flux weights in `include/Flux`, disable Flux or use SD1.5 profile on smaller cards | + +Additional tips: + +- Enable **VRAM budget** in Streamlit to see live usage (requires `LD_SHOW_VRAM=1`). +- In Docker, pass `--gpus all` and ensure `NVIDIA_VISIBLE_DEVICES` is not empty. +- Clear `~/.cache/torch_extensions` if Stable-Fast kernels were compiled against an older driver and now fail to load. + +## Slow first runs or repeated recompilation + +- Stable-Fast and SageAttention compile custom kernels on first use. This can take several minutes. Once complete, the compiled artifacts live under `~/.cache/torch_extensions` (host) or `/root/.cache/torch_extensions` (Docker). Mount this directory as a volume for faster cold starts. +- If Streamlit re-compiles every launch, ensure the container or user has write access to the cache directory and that the system clock is correct. +- Set `LD_DISABLE_SAGE_ATTENTION=1` to isolate issues related specifically to SageAttention. + +## Downloader complaints about missing assets + +- The startup checks look for standard filenames (e.g., `yolov8n.pt`, `taesdxl_decoder.safetensors`). Verify these live under the correct subdirectories in `include/`. +- For offline setups, drop the files manually and create empty `.ok` sentinels (e.g., `include/checkpoints/.downloads-ok`) to skip prompts. +- Hugging Face rate limits manifest as HTTP 429. Provide a token via the prompt, set `HF_TOKEN` in the environment or download manually. + +## Streamlit UI quirks + +- **Preview stuck on “Waiting for GPU”** – Check FastAPI logs; the batching worker may be paused. Restart the Streamlit session or run `python server.py` to inspect queue telemetry. +- **Settings reset on restart** – Ensure the process can write to `webui_settings.json`. Remove the file to revert to defaults if it becomes corrupted. +- **History thumbnails missing** – Delete the entry under `ui/history/`; the next render will recreate previews. + +## Gradio or API automation issues + +- `/api/generate` returns 500 with “No images produced”: inspect server logs for `Pipeline import error` or missing models. Ensure `pipeline.py` is importable and the working directory is the repository root. +- Jobs appear stuck: call `/api/telemetry` to inspect `pending_by_signature`. Mixed resolutions or toggles prevent batching; if running single job automation, set `LD_BATCH_WAIT_SINGLETONS=0` to avoid coalescing delays. +- SaveImage aborts with "Attempting to save N images in a single call" (exceeds `MAX_IMAGES_PER_SAVE`): this usually indicates tiled intermediate outputs or a very large batched tensor. The server will chunk large coalesced groups into smaller runs of at most `LD_MAX_IMAGES_PER_GROUP` images (default: 256) to mitigate this. If you must allow larger single-call saves, set `LD_MAX_IMAGES_PER_SAVE` to a higher value in the server environment (e.g., `export LD_MAX_IMAGES_PER_SAVE=256`) but be mindful of disk usage. Alternatively, reduce `num_images` per job or lower `LD_MAX_BATCH_SIZE` to keep groups smaller. +- Health checks: `/health` returns `{ "status": "ok" }`. If it fails, the FastAPI app likely crashed—restart and inspect `logs/server.log`. + +## Docker-specific notes + +- Always build with the provided `Dockerfile` to get SageAttention patches precompiled. +- Forward model assets by mounting `./include` into the container (`-v $(pwd)/include:/app/include`). +- On Windows + WSL2, ensure the WSL distro has the NVIDIA driver bridge (`wsl --status`). + +## Logging & diagnostics + +- Server logs live under `logs/server.log` with per-request IDs. Tail them during load testing: `tail -f logs/server.log`. +- Enable debug logging by exporting `LD_SERVER_LOGLEVEL=DEBUG` before launching Streamlit/Gradio/uvicorn. +- To inspect queue depth without hitting the API, watch the `GenerationBuffer` logs; each batch prints signature summaries. + +## When all else fails + +- Clear the `include/last_seed.txt` file if seed reuse behaves unexpectedly. +- Regenerate Stable-Fast kernels by deleting the cache directory and re-running with `stable_fast` enabled. +- Collect the following before opening an issue: GPU model, driver version, operating system, a copy of `logs/server.log`, hardware info from `/api/telemetry`, and reproduction steps. diff --git a/docs/rocm-metal-support.md b/docs/rocm-metal-support.md new file mode 100644 index 0000000000000000000000000000000000000000..4f5aa0cd8f7dd0e8cb246ae04fd7e1ba34b860a5 --- /dev/null +++ b/docs/rocm-metal-support.md @@ -0,0 +1,360 @@ +# ROCm and Metal/MPS Support + +LightDiffusion-Next includes comprehensive support for AMD GPUs with ROCm and Apple Silicon Macs with Metal Performance Shaders (MPS). This guide covers the platform-specific considerations and optimizations available for non-NVIDIA hardware. + +## ROCm Support (AMD GPUs) + +### Overview + +ROCm (Radeon Open Compute) is AMD's open-source platform for GPU computing. LightDiffusion-Next automatically detects and utilizes ROCm-compatible AMD GPUs through PyTorch's HIP backend. + +### Supported Hardware + +- **RDNA Architecture:** + + - RDNA 2 (RX 6000 series) - FP16 support + - RDNA 3 (RX 7000 series) - FP16 and BF16 support + +- **CDNA Architecture:** + + - CDNA (MI100) + - CDNA 2 (MI200 series) - FP16 and BF16 support + - CDNA 3 (MI300 series) - FP16 and BF16 support + +### Installation + +1. **Install ROCm drivers and runtime:** + + Follow the official [ROCm installation guide](https://rocm.docs.amd.com/en/latest/deploy/linux/quick_start.html) for your Linux distribution. + +```bash + # Example for Ubuntu 22.04 + wget https://repo.radeon.com/amdgpu-install/latest/ubuntu/jammy/amdgpu-install_latest_all.deb + sudo apt-get install ./amdgpu-install_latest_all.deb + sudo amdgpu-install --usecase=rocm +``` + +2. **Verify ROCm installation:** + +```bash + rocm-smi + /opt/rocm/bin/rocminfo +``` + +3. **Install PyTorch with ROCm support:** + +```bash + pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/rocm6.0 + ```bash + # Create virtual environment + python3 -m venv .venv + source .venv/bin/activate + pip install --upgrade pip uv + + # Install PyTorch with ROCm 6.0 support (adjust version as needed) + uv pip install --index-url https://download.pytorch.org/whl/rocm6.0 torch torchvision + + # Install project dependencies + uv pip install -r requirements.txt +``` + +4. **Launch LightDiffusion-Next:** + +```bash + streamlit run streamlit_app.py --server.address=0.0.0.0 --server.port=8501 +``` + +### ROCm-Specific Features + +#### Automatic Detection + +LightDiffusion-Next automatically detects ROCm GPUs at startup and reports them in the logs: + +``` +Device: cuda:0 AMD Radeon RX 7900 XTX (ROCm) : +``` + +#### Memory Management + +- **Cache Management:** ROCm uses a more conservative cache clearing strategy compared to CUDA. Cache is only cleared when explicitly forced to prevent memory fragmentation issues. +- **Memory Statistics:** Full memory statistics are available through the standard PyTorch CUDA API (which works transparently with ROCm). + +#### Precision Support + +- **FP16:** Fully supported on all RDNA and CDNA architectures +- **BF16:** Supported on RDNA 3+ and CDNA 2+ GPUs (automatically detected) +- **FP32:** Always available as fallback + +#### Attention Mechanisms + +| Feature | ROCm Support | Notes | +|---------|--------------|-------| +| PyTorch Scaled Dot-Product Attention (SDPA) | ✅ Yes | Default and recommended | +| PyTorch Flash Attention | ✅ Yes | Available on RDNA 3 and CDNA 2+ | +| xformers | ✅ Yes | Works with ROCm builds of xformers | +| SageAttention | ❌ No | CUDA-only kernels | +| SpargeAttn | ❌ No | CUDA-only kernels | + +**Recommendation:** Use PyTorch's built-in attention (SDPA) on ROCm for best compatibility. Install xformers ROCm build for additional optimizations. + +### Performance Tips + +1. **Use BF16 on supported GPUs:** + + - RDNA 3 (RX 7000 series) and CDNA 2+ support BF16 natively + - BF16 provides better numerical stability than FP16 + +2. **Enable PyTorch attention:** + + - Automatically enabled for PyTorch 2.0+ + - Provides good performance without CUDA-specific optimizations + +3. **Install ROCm-compatible xformers:** + +```bash + # Build xformers from source for ROCm + git clone https://github.com/facebookresearch/xformers.git + cd xformers + git submodule update --init --recursive + pip install -e . --no-build-isolation +``` + +4. **Monitor GPU utilization:** + +```bash + watch -n 1 rocm-smi +``` + +### Known Limitations + +- **SageAttention and SpargeAttn:** These optimizations use CUDA-specific kernels and are not available on ROCm. The system automatically falls back to PyTorch SDPA. +- **Stable-Fast:** May have limited support depending on ROCm version. Test compilation before relying on it. +- **Driver Maturity:** Ensure you're using the latest ROCm version for best stability and performance. + +--- + +## Metal/MPS Support (Apple Silicon) + +### Overview + +Metal Performance Shaders (MPS) provides GPU acceleration on Apple Silicon Macs (M1, M2, M3 series). LightDiffusion-Next automatically detects and utilizes MPS when running on macOS. + +### Supported Hardware + +- **Apple Silicon:** + + - M1, M1 Pro, M1 Max, M1 Ultra + - M2, M2 Pro, M2 Max, M2 Ultra + - M3, M3 Pro, M3 Max + - All future M-series chips + +### Installation + +1. **Ensure macOS is up to date:** + + - macOS 12.3 (Monterey) or later required + - macOS 13+ (Ventura) recommended for best performance + +2. **Install Python 3.10:** + +```bash + # Using Homebrew + brew install python@3.10 +``` + +3. **Create virtual environment and install dependencies:** + +```bash + python3.10 -m venv .venv + source .venv/bin/activate + pip install --upgrade pip + + # Install PyTorch with MPS support + pip install torch torchvision torchaudio + + # Install project dependencies + pip install -r requirements.txt +``` + +4. **Launch LightDiffusion-Next:** + +```bash + streamlit run streamlit_app.py --server.address=0.0.0.0 --server.port=8501 +``` + +### MPS-Specific Features + +#### Automatic Detection + +MPS is automatically detected and enabled on compatible hardware: + +``` +Device: mps +VAE dtype: torch.float16 +Set vram state to: SHARED +``` + +#### Memory Management + +- **Unified Memory:** Apple Silicon uses unified memory shared between CPU and GPU +- **VRAM State:** Automatically set to `SHARED` mode +- **Cache Management:** Uses `torch.mps.empty_cache()` for memory cleanup + +#### Precision Support + +- **FP16:** Fully supported and recommended (default) +- **FP32:** Supported but slower +- **BF16:** Not supported on MPS backend + +#### Attention Mechanisms + +| Feature | MPS Support | Notes | +|---------|-------------|-------| +| PyTorch Scaled Dot-Product Attention (SDPA) | ✅ Yes | Default and recommended | +| PyTorch Flash Attention | ❌ No | Not available on MPS | +| xformers | ❌ No | MPS backend not supported | +| SageAttention | ❌ No | CUDA/MPS incompatible | +| SpargeAttn | ❌ No | CUDA-only kernels | + +**Recommendation:** Use PyTorch's built-in attention (SDPA) on MPS. It's well-optimized for Apple Silicon. + +### Performance Tips + +- **Use FP16 precision:** + +MPS works best with FP16 +Automatically enabled by LightDiffusion-Next + +- **Optimize batch sizes:** + +Start with smaller batch sizes and increase gradually +Monitor memory usage through Activity Monitor + +- **Keep macOS updated:** + +Apple regularly improves MPS performance in system updates + +- **Close unnecessary applications:** + +Unified memory is shared with system processes +Free up RAM for better GPU performance + +- **Monitor GPU usage:** + +```bash + # Use Activity Monitor -> GPU tab + # Or use powermetrics (requires sudo): + sudo powermetrics --samplers gpu_power -i 1000 +``` + +### Known Limitations + +- **Non-blocking transfers:** Not supported; MPS operations are blocking +- **Advanced optimizations:** SageAttention, SpargeAttn, and xformers are not available +- **BF16:** Not supported on MPS backend +- **Memory pressure:** System may swap under high memory load due to unified architecture + +### Unified Memory Considerations + +Apple Silicon's unified memory architecture means: + +- GPU and CPU share the same physical memory pool +- Less memory copying between devices +- System processes compete for the same memory +- Available VRAM depends on total system RAM and current usage + +**Recommended RAM:** + +- 16 GB: SD1.5 models at moderate resolutions +- 32 GB: Comfortable for most workflows including Flux (with quantization) +- 64 GB+: Professional workflows with large batch sizes + +--- + +## Comparison Table + +| Feature | NVIDIA (CUDA) | AMD (ROCm) | Apple (MPS) | +|---------|---------------|------------|-------------| +| FP16 | ✅ Full | ✅ Full | ✅ Full | +| BF16 | ✅ Full | ✅ RDNA3+/CDNA2+ | ❌ No | +| PyTorch SDPA | ✅ Yes | ✅ Yes | ✅ Yes | +| Flash Attention | ✅ Yes | ✅ RDNA3+/CDNA2+ | ❌ No | +| xformers | ✅ Yes | ✅ Build from source | ❌ No | +| SageAttention | ✅ Yes | ❌ No | ❌ No | +| SpargeAttn | ✅ Yes (CC 8.0-9.0) | ❌ No | ❌ No | +| Stable-Fast | ✅ Yes | ⚠️ Limited | ❌ No | +| Memory Management | ✅ Dedicated VRAM | ✅ Dedicated VRAM | ⚠️ Unified Memory | + +--- + +## Troubleshooting + +### ROCm Issues + +**Problem:** PyTorch doesn't detect ROCm GPU + +```bash +# Check ROCm installation +rocm-smi +rocminfo | grep "Name:" + +# Verify PyTorch sees GPU +python -c "import torch; print(torch.cuda.is_available()); print(torch.version.hip)" +``` + +**Problem:** Out of memory errors + +- Reduce batch size +- Enable lower VRAM mode in settings +- Close other GPU-using applications +- Check with `rocm-smi` for memory usage + +**Problem:** Slow performance + +- Verify you're using the correct ROCm-optimized PyTorch build +- Check GPU utilization with `rocm-smi` +- Ensure FP16 or BF16 is enabled (check logs) + +### MPS Issues + +**Problem:** MPS not detected + +```bash +# Verify MPS support +python -c "import torch; print(torch.backends.mps.is_available())" +``` +- Ensure macOS 12.3+ +- Update to latest macOS version +- Reinstall PyTorch + +**Problem:** Memory warnings or crashes + +- Reduce batch size +- Close other applications to free unified memory +- Check Activity Monitor for memory pressure + +**Problem:** Slower than expected performance + +- Verify FP16 is being used (check logs) +- Close background applications +- Update to latest macOS version for performance improvements +- Some models may be CPU-bound on older M1 chips + +--- + +## Getting Help + +For platform-specific issues: + +1. Check the [FAQ](faq.md) for common questions +2. Review PyTorch's platform-specific documentation: + - [ROCm installation](https://pytorch.org/get-started/locally/#linux-rocm) + - [MPS backend](https://pytorch.org/docs/stable/notes/mps.html) +3. Open an issue on GitHub with: + - Platform details (GPU model, driver version, OS) + - LightDiffusion-Next startup logs + - Output of `python -c "import torch; print(torch.__version__); print(torch.version.hip if hasattr(torch.version, 'hip') else 'CUDA'); print(torch.cuda.is_available())"` + +--- + +**Note:** This documentation reflects the current state of ROCm and MPS support in PyTorch and LightDiffusion-Next. As these platforms mature, more optimizations and features may become available. diff --git a/docs/sageattention.md b/docs/sageattention.md new file mode 100644 index 0000000000000000000000000000000000000000..06799397a1221d4b0c92a51290d86afe2a28c8f0 --- /dev/null +++ b/docs/sageattention.md @@ -0,0 +1,338 @@ +# SageAttention & SpargeAttn + +## Overview + +SageAttention and SpargeAttn are drop-in replacements for PyTorch's scaled dot-product attention that can provide significant speedup with zero to minimal quality loss. They work by optimizing the compute-heavy attention mechanism used throughout diffusion models (UNet, VAE, Flux Transformers). + +- **SageAttention**: Uses INT8 quantization for key/value tensors while maintaining FP16 query precision +- **SpargeAttn**: Adds dynamic sparsity pruning on top of SageAttention, skipping redundant attention computations + +Both are **training-free**, **hardware-accelerated** CUDA kernels that integrate transparently into LightDiffusion-Next. + +## How It Works + +### SageAttention + +Standard attention computes: + +$$ +\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V +$$ + +SageAttention accelerates this by: + +1. **Quantizing K and V** to INT8 before the matrix multiplication +2. **Keeping Q in FP16** to preserve attention score precision +3. **Fusing operations** (softmax, scaling, matmul) in hand-tuned CUDA kernels +4. **Dequantizing** output back to FP16 after final matmul + +This reduces memory bandwidth (K/V use half the space) and leverages Tensor Cores more efficiently. + +### SpargeAttn + +SpargeAttn extends SageAttention with **sparse attention masking**: + +1. Computes a similarity metric between query and key patches +2. Prunes attention connections below a learned threshold (default: 60% similarity) +3. Applies cumulative distribution filtering to keep only the top 97% of attention scores +4. Uses partial vector thresholding to skip redundant computations + +The result: 40-60% total speedup over baseline PyTorch attention with minimal impact on output quality. + +## Installation + +### SageAttention (All Platforms) + +**Prerequisites:** +- CUDA Toolkit 11.8+ (must match your PyTorch CUDA version) +- Python 3.8+ +- PyTorch with CUDA support + +**Install:** + +```bash +# Clone repository +git clone https://github.com/thu-ml/SageAttention +cd SageAttention + +# Install from source (no build isolation to respect existing CUDA setup) +pip install -e . --no-build-isolation + +# Verify installation +python -c "import sageattention; print('SageAttention installed successfully')" +``` + +### SpargeAttn (Linux/WSL2 Only) + +**Prerequisites:** +- Same as SageAttention +- Linux or WSL2 environment (Windows native builds fail due to linker path limits) +- GPU with compute capability 8.0-9.0 (RTX 30xx, 40xx, A100, H100) + +**Install:** + +```bash +# Clone repository +git clone https://github.com/thu-ml/SparseAttention +cd SpargeAttn + +# Set GPU architecture (critical for performance) +export TORCH_CUDA_ARCH_LIST="9.0" # Or your GPU: 8.0, 8.6, 8.9, 9.0 + +# Install from source +pip install -e . --no-build-isolation + +# Verify installation +python -c "import spas_sage_attn; print('SpargeAttn installed successfully')" +``` + +**GPU Architecture Reference:** + +| GPU Model | Compute Capability | TORCH_CUDA_ARCH_LIST | +|-----------|-------------------|----------------------| +| RTX 3060/3070/3080/3090 | 8.6 | `"8.6"` | +| RTX 4060/4070/4080/4090 | 8.9 | `"8.9"` | +| A100 | 8.0 | `"8.0"` | +| H100 | 9.0 | `"9.0"` | +| RTX 5060/5070/5080/5090 | 12.0 | SageAttention supported, SpargeAttn pending | + +### Docker Installation + +Both kernels are automatically built during the Docker image creation if the architecture is supported: + +```bash +# Build with SpargeAttn (compute 8.0-9.0) +docker-compose build --build-arg TORCH_CUDA_ARCH_LIST="8.9" + +# RTX 50xx builds (SageAttention only, no SpargeAttn yet) +docker-compose build --build-arg TORCH_CUDA_ARCH_LIST="12.0" +``` + +## Usage + +### Automatic Detection + +LightDiffusion-Next automatically detects and enables the best available attention backend at startup: + +```python +# Priority order (highest to lowest): +SpargeAttn > SageAttention > xformers > PyTorch SDPA +``` + +Check which backend is active in the server logs: + +```bash +# SpargeAttn enabled +cat logs/server.log | grep "attention" +# Output: Using SpargeAttn (Sparse + SageAttention) cross attention + +# SageAttention enabled +# Output: Using SageAttention cross attention + +# Fallback +# Output: Using pytorch cross attention +``` + +### Streamlit UI + +No configuration needed — SageAttention/SpargeAttn are always active if installed. + +### REST API + +Same as UI — the backend selection is transparent: + +```bash +curl -X POST http://localhost:7861/api/generate \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "a serene mountain lake at dawn", + "width": 768, + "height": 512, + "num_images": 1 + }' +# Automatically uses SpargeAttn if available +``` + +### Manual Disable + +Force PyTorch SDPA for debugging: + +```bash +export LD_DISABLE_SAGE_ATTENTION=1 +python streamlit_app.py +``` + +## Performance + +Both SageAttention and SpargeAttn provide measurable speedup over PyTorch SDPA baseline: + +- **SageAttention**: Moderate speedup with zero quality loss (reported ~15-20% in papers) +- **SpargeAttn**: Significant speedup with minimal quality loss (reported ~40-60% in papers) + +Actual performance gains vary based on: +- GPU architecture and VRAM +- Model type (SD1.5, SDXL, Flux) +- Resolution and batch size +- Head dimensions and sequence lengths + +**Note:** Benchmark your specific setup to measure real-world performance.## Technical Details + +### Head Dimension Support + +Both kernels natively support head dimensions of `[64, 96, 128]`. For other dimensions: + +- **< 64**: Pad to 64, compute, then slice result +- **64-128**: Pad to 128, compute, then slice result +- **> 128**: Fallback to xformers or PyTorch SDPA + +LightDiffusion-Next handles padding/slicing automatically. + +### Tensor Layout + +SageAttention expects tensors in `(batch_size, num_heads, seq_len, head_dim)` format. The pipeline reshapes inputs transparently: + +```python +# Internal reshaping (handled automatically) +q, k, v = map( + lambda t: t.reshape(b, -1, heads, dim_head).transpose(1, 2), + (q, k, v), +) +out = sageattention.sageattn(q, k, v, tensor_layout="HND") +``` + +### SpargeAttn Thresholds + +Default pruning parameters (tuned for quality/speed balance): + +```python +out = spas_sage_attn.spas_sage2_attn_meansim_cuda( + q, k, v, + simthreshd1=0.6, # Similarity threshold (60%) + cdfthreshd=0.97, # Keep top 97% of attention scores + pvthreshd=15, # Partial vector threshold + is_causal=False +) +``` + +Adjust `simthreshd1` for different trade-offs: +- `0.5`: More aggressive pruning, higher speedup, slight quality loss +- `0.7`: Conservative pruning, lower speedup, minimal quality loss + +## Compatibility + +### Compatible With + +- ✅ Stable Diffusion 1.5 +- ✅ Stable Diffusion 2.1 +- ✅ SDXL +- ✅ Flux (both cross-attention and self-attention blocks) +- ✅ All samplers (Euler, DPM++, etc.) +- ✅ LoRA adapters +- ✅ Textual inversion embeddings +- ✅ HiresFix, ADetailer, Img2Img +- ✅ Stable-Fast (when stacked) +- ✅ WaveSpeed caching (when stacked) + +### Known Limitations + +- ❌ RTX 50xx (compute 12.0) does not support SpargeAttn yet (SageAttention works) +- ❌ CPU-only inference (CUDA required) +- ❌ AMD GPUs (ROCm port not available) +- ⚠️ Head dimensions > 128 fall back to slower backends + +## Troubleshooting + +### Import Error: `No module named 'sageattention'` + +**Cause:** Not installed or installation failed. + +**Fix:** +```bash +cd SageAttention +pip install -e . --no-build-isolation +``` + +Verify CUDA toolkit is accessible: +```bash +nvcc --version # Should match PyTorch CUDA version +``` + +### Compilation Error: `nvcc fatal error` + +**Cause:** CUDA toolkit not found or version mismatch. + +**Fix:** +1. Install CUDA toolkit matching your PyTorch version +2. Add CUDA to PATH: + ```bash + export PATH=/usr/local/cuda/bin:$PATH + export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH + ``` +3. Reinstall SageAttention + +### SpargeAttn Build Fails on Windows + +**Cause:** Windows linker has path length limitations. + +**Fix:** Use WSL2 or native Linux: +```bash +# In WSL2 +cd SpargeAttn +export TORCH_CUDA_ARCH_LIST="8.9" +pip install -e . --no-build-isolation +``` + +### Slower Than Expected + +**Cause:** Wrong GPU architecture compiled or kernel fallback. + +**Fix:** +1. Check logs for "Using pytorch cross attention" (fallback indicator) +2. Rebuild with correct `TORCH_CUDA_ARCH_LIST` +3. Verify GPU compute capability: + ```bash + nvidia-smi --query-gpu=compute_cap --format=csv + ``` + +### Quality Degradation with SpargeAttn + +**Cause:** Pruning thresholds too aggressive. + +**Fix:** Currently not user-configurable in the UI, but you can modify `src/Attention/AttentionMethods.py`: +```python +# Line ~290 +out = spas_sage_attn.spas_sage2_attn_meansim_cuda( + q, k, v, + simthreshd1=0.7, # Increase from 0.6 for better quality + cdfthreshd=0.98, # Increase from 0.97 + pvthreshd=15, + is_causal=False +) +``` + +## Citation + +If you use SageAttention or SpargeAttn in your work: + +```bibtex +@article{sageattention2024, + title={SageAttention: Accurate 8-Bit Attention for Plug-and-play Inference Acceleration}, + author={Zhang, Jintao and Zhang, Jia and Zhai, Pengle and others}, + journal={arXiv preprint arXiv:2410.02367}, + year={2024} +} + +@article{spargeattn2024, + title={SpargeAttn: Sparsity-Aware Efficient Attention for Long Context LLMs}, + author={Zhang, Jintao and others}, + journal={arXiv preprint}, + year={2024} +} +``` + +## Resources + +- [SageAttention Repository](https://github.com/thu-ml/SageAttention) +- [SpargeAttn Repository](https://github.com/thu-ml/SparseAttention) +- [SageAttention Paper](https://arxiv.org/abs/2410.02367) +- [Flash Attention](https://github.com/Dao-AILab/flash-attention) (related work) diff --git a/docs/stablefast.md b/docs/stablefast.md new file mode 100644 index 0000000000000000000000000000000000000000..5600472ef0e60b3e4816f0464cd5fdd0f4219e34 --- /dev/null +++ b/docs/stablefast.md @@ -0,0 +1,412 @@ +# Stable-Fast Compilation + +## Overview + +Stable-Fast is a JIT compilation framework that optimizes Stable Diffusion UNet models by tracing execution, fusing operators and optionally capturing CUDA graphs. It can provide significant speedup for SD1.5/SDXL batch workflows with zero quality loss. + +Unlike runtime attention optimizations (SageAttention, SpargeAttn), Stable-Fast performs **ahead-of-time compilation** on the first inference pass. The compiled model is cached and reused for subsequent generations with compatible shapes. + +## How It Works + +Stable-Fast applies three optimization layers: + +### 1. TorchScript Tracing + +The first forward pass through the UNet is recorded into a static computational graph: + +```python +traced_model = torch.jit.trace(unet, example_inputs) +``` + +This eliminates Python interpreter overhead and enables downstream graph optimizations. + +### 2. Operator Fusion + +The traced graph undergoes pattern-based fusion: + +- **Conv + BatchNorm fusion**: Merges normalization into convolution weights +- **Activation fusion**: Fuses ReLU/GELU/SiLU directly into linear/conv ops +- **Memory layout optimization**: Converts to channels-last format for faster conv execution +- **Triton kernels**: Replaces PyTorch ops with hand-tuned Triton implementations (if `enable_triton=True`) + +Example fusion: + +```python +# Before: +x = conv(input) +x = batch_norm(x) +x = relu(x) + +# After: +x = fused_conv_bn_relu(input) # Single kernel launch +``` + +### 3. CUDA Graph Capture (Optional) + +When `enable_cuda_graph=True`, the entire forward pass is captured as a static CUDA graph: + +- Kernel launches are recorded once and replayed on subsequent runs +- Eliminates CPU launch overhead (~10-15% speedup) +- Requires fixed input shapes and batch sizes + +**Trade-off:** Higher VRAM usage (~500MB for graph buffers) and less flexibility. + +## Installation + +### Windows/Linux (Manual) + +Follow the [official guide](https://github.com/chengzeyi/stable-fast?tab=readme-ov-file#installation): + +```bash +# Install from PyPI (recommended) +pip install stable-fast + +# Or build from source for latest features +git clone https://github.com/chengzeyi/stable-fast +cd stable-fast +pip install -e . +``` + +**Prerequisites:** +- PyTorch 2.0+ with CUDA support +- xformers (optional but recommended) +- Triton (optional for Triton kernel fusion) + +### Docker + +Stable-Fast is included in the Docker image when `INSTALL_STABLE_FAST=1`: + +```bash +docker-compose build --build-arg INSTALL_STABLE_FAST=1 +``` + +Default is `0` (disabled) to reduce image size and build time. + +## Usage + +### Streamlit UI + +Enable in the **Performance** section of the sidebar: + +1. Check **Stable Fast** +2. Generate images — the first run compiles the model (30-60s delay) +3. Subsequent generations reuse the cached compiled model + +**Visual indicator:** The first generation shows "Compiling model..." in the progress bar. + +### REST API + +Pass `stable_fast: true` in the request payload: + +```bash +curl -X POST http://localhost:7861/api/generate \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "a peaceful garden with cherry blossoms", + "width": 768, + "height": 512, + "num_images": 1, + "stable_fast": true + }' +``` + +### Configuration + +Stable-Fast behavior is controlled by `CompilationConfig`: + +```python +from sfast.compilers.diffusion_pipeline_compiler import CompilationConfig + +config = CompilationConfig.Default() +config.enable_xformers = True # Use xformers attention +config.enable_cuda_graph = False # CUDA graphs (set True for max speed) +config.enable_jit_freeze = True # Freeze traced graph +config.enable_cnn_optimization = True # Conv fusion +config.enable_triton = False # Triton kernels (experimental) +config.memory_format = torch.channels_last # Optimize memory layout +``` + +LightDiffusion-Next uses sensible defaults (CUDA graphs disabled by default for flexibility). To override: + +```python +# In src/StableFast/StableFast.py +def gen_stable_fast_config(enable_cuda_graph=False): + config = CompilationConfig.Default() + config.enable_cuda_graph = enable_cuda_graph # Pass True for max speed + # ... rest of config +``` + +## Performance + +### Speedup Benchmarks + +Stable-Fast provides speedup through: +- **JIT compilation**: Eliminates Python overhead +- **Operator fusion**: Reduces kernel launches +- **CUDA graphs** (optional): Further reduces CPU overhead + +Speedup varies significantly based on: +- GPU architecture +- Batch size and generation count +- Model size (SD1.5 vs SDXL) +- Whether CUDA graphs are enabled + +**Note:** Performance benefits are most noticeable for batch operations (50+ images). For single 20-step generations, compilation overhead may exceed speedup gains. + +### Compilation Time + +First-run compilation overhead: + +- **SD1.5 UNet**: ~30s (traced once per resolution/batch size) +- **SDXL UNet**: ~60s (larger model) +- **Subsequent runs**: <1s (cached) + +Cached compiled models persist in `~/.cache/torch_extensions/`. Clear this directory to force recompilation. + +## Stacking with Other Optimizations + +Stable-Fast is **fully compatible** with SageAttention, SpargeAttn and WaveSpeed: + +### Stable-Fast + SageAttention + +```yaml +stable_fast: true +# SageAttention auto-detected +``` + +**Result:** 70% (Stable-Fast) + 15% (SageAttention) = **~2x total speedup** + +### Stable-Fast + SpargeAttn + +```yaml +stable_fast: true +# SpargeAttn auto-detected +``` + +**Result:** 70% (Stable-Fast) + 40% (SpargeAttn) = **~2.4x total speedup** + +### Stable-Fast + SpargeAttn + DeepCache + +```yaml +stable_fast: true +deepcache: + enabled: true + interval: 3 + depth: 2 +# SpargeAttn auto-detected +``` + +**Result:** 70% × 40% × 150% (DeepCache 2-3x) = **~4-5x total speedup** + +## Compatibility + +### Compatible With + +- ✅ Stable Diffusion 1.5 +- ✅ Stable Diffusion 2.1 +- ✅ SDXL +- ✅ All samplers (Euler, DPM++, etc.) +- ✅ LoRA adapters +- ✅ Textual inversion embeddings +- ✅ HiresFix +- ✅ ADetailer +- ✅ Img2Img (with fixed denoise strength) +- ✅ SageAttention/SpargeAttn +- ✅ WaveSpeed caching + +### Not Compatible With + +- ❌ Flux models (different architecture, no UNet) +- ❌ Dynamic resolution changes after compilation +- ❌ Dynamic batch size changes after compilation (with CUDA graphs) +- ⚠️ Frequent model switching (recompiles each time) + +## Troubleshooting + +### Slow First Run / Repeated Recompilation + +**Symptom:** Every generation triggers compilation, even with identical settings. + +**Causes:** +1. Cache directory not writable +2. System clock incorrect (invalidates timestamps) +3. Different model loaded (each model is cached separately) + +**Fixes:** +```bash +# Check cache permissions +ls -la ~/.cache/torch_extensions + +# Ensure stable timestamps +date # Should be correct + +# Mount cache in Docker to persist across container restarts +docker run -v ~/.cache/torch_extensions:/root/.cache/torch_extensions ... +``` + +### CUDA Out of Memory During Compilation + +**Symptom:** OOM error on first run but not subsequent runs. + +**Cause:** Compilation allocates temporary buffers for tracing. + +**Fixes:** +1. Disable CUDA graphs: `enable_cuda_graph=False` (saves ~500MB) +2. Reduce batch size temporarily for first run +3. Clear other VRAM consumers (close other apps, disable model caching) + +### Compilation Hangs or Crashes + +**Symptom:** Process freezes during "Compiling model..." step. + +**Causes:** +1. Triton compilation error (if `enable_triton=True`) +2. Driver incompatibility +3. Insufficient CPU RAM for graph analysis + +**Fixes:** +```bash +# Disable Triton +# In src/StableFast/StableFast.py: +config.enable_triton = False + +# Update NVIDIA driver +nvidia-smi # Check version, upgrade if < 525.x + +# Increase Docker memory limit +# In docker-compose.yml: +deploy: + resources: + limits: + memory: 16G # Increase from default +``` + +### Error: `torch.jit.trace` fails + +**Symptom:** `RuntimeError: Could not trace model` + +**Cause:** Dynamic control flow in model (if/else statements depending on runtime values). + +**Fix:** This is rare with standard SD models. If it occurs: +1. Check for custom LoRA/embeddings with dynamic logic +2. Disable Stable-Fast for that specific generation +3. Report issue with model details + +### Model Quality Degradation + +**Symptom:** Compiled model produces different outputs than baseline. + +**Cause:** Numeric precision differences from operator fusion (very rare). + +**Fixes:** +```python +# Disable aggressive optimizations +config.enable_cnn_optimization = False +config.memory_format = None # Use default layout +``` + +If issue persists, disable Stable-Fast and file a bug report. + +## Advanced Configuration + +### Custom Compilation Config + +Override defaults in `src/StableFast/StableFast.py`: + +```python +def gen_stable_fast_config(enable_cuda_graph=False): + config = CompilationConfig.Default() + + # Maximum speed (higher VRAM usage) + config.enable_cuda_graph = True + config.enable_triton = True + config.prefer_lowp_gemm = True # Use FP16 matrix multiplies + + # Balanced (recommended) + config.enable_cuda_graph = False + config.enable_triton = False + config.enable_cnn_optimization = True + + # Debug (no optimizations) + config.enable_cuda_graph = False + config.enable_jit_freeze = False + config.enable_cnn_optimization = False + + return config +``` + +### Clear Cached Compilations + +```bash +# Linux/Mac +rm -rf ~/.cache/torch_extensions + +# Windows +del /s /q %USERPROFILE%\.cache\torch_extensions + +# Docker (mount cache as volume) +docker run -v my_cache:/root/.cache/torch_extensions ... +docker volume rm my_cache # Clear cache +``` + +### Profile Compilation + +```bash +# Enable debug logging +export LD_SERVER_LOGLEVEL=DEBUG + +# Run generation and check logs +cat logs/server.log | grep "Stable" +``` + +## Best Practices + +### Production Deployments + +1. **Pre-compile models** during startup with a warm-up request (only for batch/long-running services) +2. **Mount cache volume** to persist compilations across container restarts +3. **Disable CUDA graphs** if serving multiple batch sizes +4. **Enable CUDA graphs** for fixed-resolution APIs with consistent high-volume traffic +5. **Disable Stable-Fast entirely** for single-shot API endpoints (compilation overhead exceeds benefit) + +Example warm-up: + +```python +# In startup script +def warmup_stable_fast(model, width=768, height=512): + """Pre-compile model with dummy input.""" + dummy_input = torch.randn(1, 4, height // 8, width // 8, device="cuda") + dummy_timestep = torch.tensor([999], device="cuda") + + with torch.no_grad(): + model(dummy_input, dummy_timestep, c={}) + + print("Stable-Fast compilation complete") +``` + +### Development Workflows + +1. **Disable Stable-Fast** when experimenting with new models/LoRAs (avoids repeated recompilation) +2. **Enable for final testing** to verify production performance +3. **Clear cache** after upgrading PyTorch/CUDA drivers + +## Citation + +If you use Stable-Fast in your work: + +```bibtex +@misc{stable-fast, + author = {Cheng Zeyi}, + title = {stable-fast: Fast Inference for Stable Diffusion}, + year = {2023}, + publisher = {GitHub}, + url = {https://github.com/chengzeyi/stable-fast} +} +``` + +## Resources + +- [Stable-Fast Repository](https://github.com/chengzeyi/stable-fast) +- [Installation Guide](https://github.com/chengzeyi/stable-fast?tab=readme-ov-file#installation) +- [TorchScript Documentation](https://pytorch.org/docs/stable/jit.html) +- [CUDA Graphs Guide](https://pytorch.org/blog/accelerating-pytorch-with-cuda-graphs/) diff --git a/docs/tome.md b/docs/tome.md new file mode 100644 index 0000000000000000000000000000000000000000..2c6ea0b003ad543dcf6508a3681a6555ffe17019 --- /dev/null +++ b/docs/tome.md @@ -0,0 +1,272 @@ +# Token Merging (ToMe) + +## Overview + +Token Merging (ToMe) is a **performance optimization** that accelerates diffusion models by intelligently merging similar tokens in the attention mechanism. By identifying and combining redundant computations, ToMe achieves **20-60% speedup** with minimal quality impact. + +Unlike feature caching (DeepCache, WaveSpeed), ToMe reduces the computational graph itself — fewer tokens means fewer attention operations, less memory bandwidth, and faster generation. + +This is a **training-free**, **drop-in optimization** that works with all Stable Diffusion models (SD1.5, SDXL) and can be combined with other speedup techniques. + +## How It Works + +### The Token Redundancy Problem + +Diffusion models process images as sequences of tokens (patches): + +``` +Input Image (512×512) → Tokenize → 4096 tokens (64×64 grid of 8×8 patches) +``` + +At each attention layer, **every token attends to every other token**: + +$$ +\text{Attention Cost} = O(N^2 \cdot D) +$$ + +Where: +- $N$ = number of tokens (e.g., 4096 for 512×512) +- $D$ = embedding dimension (e.g., 768 or 1024) + +**Key insight:** Many tokens are highly similar (e.g., sky regions, uniform backgrounds, smooth gradients). Computing attention between nearly-identical tokens is redundant. + +### The ToMe Solution + +Token Merging reduces redundancy through **bipartite matching**: + +``` +Step 1: Split tokens into two sets +┌─────────────────────┬─────────────────────┐ +│ Destination Set (dst)│ Source Set (src) │ +│ [Token 1, 3, 5, ...] │ [Token 2, 4, 6, ...] │ +└─────────────────────┴─────────────────────┘ + +Step 2: Compute similarity (cosine distance) + dst[0] ↔ src[0]: 0.92 (highly similar!) + dst[0] ↔ src[1]: 0.34 + dst[0] ↔ src[2]: 0.18 + ... + +Step 3: Merge most similar pairs + merged_token[0] = (dst[0] + src[0]) / 2 + +Step 4: Continue with fewer tokens + 4096 tokens → 2048 tokens (50% merge ratio) + Attention cost reduced by ~4x +``` + +This happens **per attention layer**, with merge ratio dynamically adjusting based on layer depth. + +## Configuration + +### Parameters + +| Parameter | Type | Default | Range | Description | +|-----------|------|---------|-------|-------------| +| `tome_enabled` | bool | `False` | - | Enable Token Merging | +| `tome_ratio` | float | `0.5` | 0.0-0.9 | Percentage of tokens to merge (higher = faster, lower quality) | +| `tome_max_downsample` | int | `1` | 1, 2, 4, 8 | Apply ToMe to layers with downsampling ≤ this value | + +### Choosing `tome_max_downsample` + +Controls which UNet layers apply ToMe: + +| Value | Layers Affected | Speed vs Quality | +|-------|----------------|------------------| +| **1** | Only full-resolution layers (4/15) | Conservative, minimal quality impact | +| **2** | Half-resolution layers (8/15) | Balanced (recommended) | +| **4** | Quarter-resolution layers (12/15) | Aggressive | +| **8** | All layers (15/15) | Maximum speedup, noticeable quality loss | + +**Recommendation:** Start with `max_downsample=1`. Only increase if you need more speedup and can tolerate quality reduction. + +## Usage + +### Streamlit UI + +Enable in the **🔀 Token Merging (ToMe)** expander: + +1. Check **Enable Token Merging** +2. Select a preset: + - **Conservative** — 30% merge, max_downsample=2 (minimal impact) + - **Balanced** — 50% merge, max_downsample=1 (recommended) + - **Aggressive** — 70% merge, max_downsample=1 (maximum speed) + - **Custom** — Manual slider control +3. Generate images — console confirms activation + +**Visual feedback:** +``` +✓ Token Merging ACTIVE: 50% merge ratio, max_downsample=1 +``` + +### REST API + +Include in your generation request: + +```bash +curl -X POST http://localhost:7861/api/generate \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "a cyberpunk cityscape at night, neon lights", + "width": 1024, + "height": 512, + "steps": 25, + "tome_enabled": true, + "tome_ratio": 0.5, + "tome_max_downsample": 1 + }' +``` + +### Python API + +```python +from src.user.pipeline import pipeline + +pipeline( + prompt="a detailed fantasy castle on a cliff", + w=768, + h=1024, + steps=30, + sampler="dpmpp_sde_cfgpp", + scheduler="ays", + tome_enabled=True, + tome_ratio=0.5, + tome_max_downsample=1, + number=4 # Generate multiple images faster +) +``` + +## Troubleshooting + +### "No speedup detected" + +**Possible causes:** +1. **tomesd not installed** — Install with `pip install tomesd` +2. **Other bottlenecks** — Enable only ToMe for isolated testing +3. **Very low resolution** — ToMe benefits are minimal below 512px + +**Solutions:** +```bash +# Check installation +python -c "import tomesd; print('ToMe available')" + +# Test in isolation at 1024×512 (ideal resolution for ToMe) +python quick_tome_test.py +``` + +### "Images look blurry or soft" + +**Cause:** `tome_ratio` too high (>0.6) or `max_downsample` too aggressive (>2). + +**Solutions:** +- Reduce `tome_ratio` to 0.4-0.5 +- Lower `max_downsample` to 1 +- Increase `steps` to 30-35 for better convergence +- Disable ToMe for final high-quality renders + +### "Minimal speedup despite 70% merge" + +**Cause:** Other optimizations (DeepCache, Multi-Scale) already bottlenecked elsewhere (VAE decode, sampling overhead). + +**Solutions:** +- Profile with isolated tests (disable all other optimizations) +- Ensure GPU isn't memory-bound (reduce batch size) +- Check system monitoring for CPU/disk bottlenecks + +### "Model fails to load / tomesd errors" + +**Cause:** Outdated tomesd version or incompatible model architecture. + +**Solutions:** +```bash +# Update tomesd +pip install --upgrade tomesd + +# Check compatibility (ToMe only works with UNet-based models) +# Flux/Transformer models require different ToMe variant (not yet supported) +``` + +## Technical Details + +### Implementation + +ToMe is applied via the `ModelPatcher` class (`src/Model/ModelPatcher.py`): + +```python +def apply_tome(self, ratio: float = 0.5, max_downsample: int = 1) -> bool: + """Apply Token Merging to the diffusion model.""" + # Remove any existing patch (handles cached models) + try: + tomesd.remove_patch(self) + except: + pass + + # Apply ToMe patch + tomesd.apply_patch( + self, # ModelPatcher with .model.diffusion_model structure + ratio=ratio, + max_downsample=max_downsample + ) + self.tome_enabled = True + return True +``` + +**Cache handling:** ToMe patches are removed after each generation and re-applied as needed, ensuring correct behavior with model caching. + +### Bipartite Matching Algorithm + +ToMe uses **proportional attention-based matching**: + +1. **Partition tokens:** + $$ + T_{\text{dst}}, T_{\text{src}} = \text{partition}(T, \text{stride}=(2,2)) + $$ + +2. **Compute similarity matrix:** + $$ + S_{ij} = \frac{T_{\text{dst}}[i] \cdot T_{\text{src}}[j]}{||T_{\text{dst}}[i]|| \cdot ||T_{\text{src}}[j]||} + $$ + +3. **Find top-k matches:** + $$ + k = \lfloor \text{ratio} \times |T_{\text{src}}| \rfloor + $$ + +4. **Merge tokens:** + $$ + T'[i] = \frac{T_{\text{dst}}[i] + T_{\text{src}}[\text{match}(i)]}{2} + $$ + +## Compatibility + +| Feature | Compatible? | Notes | +|---------|-------------|-------| +| **SD1.5 models** | ✓ | Full support, tested extensively | +| **SDXL models** | ✓ | Full support, larger speedup | +| **Flux models** | ✗ | UNet-specific, Transformer variant TBD | +| **All samplers** | ✓ | ToMe patches attention, agnostic to sampler | +| **CFG-Free** | ✓ | No interaction, both apply independently | +| **DeepCache** | ✓ | Excellent combination, speedups multiply | +| **Multi-Scale** | ✓ | Compatible, benefits stack | +| **HiRes Fix** | ✓ | Applied to all upscaling passes | +| **ADetailer** | ✓ | Applied to detail-enhancement passes | +| **Stable-Fast** | ✓ | Can combine for maximum speedup | + +## Limitations + +1. **UNet-only:** Transformer architectures (Flux) use different attention patterns — dedicated Transformer-ToMe needed +2. **Detail sensitivity:** High-frequency textures (fabric weave, individual hairs) see most quality impact +3. **Diminishing returns:** Beyond 60% merge, quality degrades faster than speed improves +4. **One-time patch:** Doesn't adapt merge ratio dynamically during generation + +## Related Optimizations + +- **[DeepCache](wavespeed.md#deepcache)**: Feature caching — complements ToMe, speedups multiply (~2.8x combined) +- **[Multi-Scale Diffusion](optimizations.md#multi-scale)**: Resolution-based optimization — also reduces token count +- **[Stable-Fast](stablefast.md)**: Compilation-based speedup — can combine for maximum performance + +## References & Further Reading + +- **Original Paper:** [Token Merging for Fast Stable Diffusion](https://arxiv.org/abs/2303.17604) (Bolya & Hoffman, 2023) +- **tomesd Library:** https://github.com/dbolya/tomesd +- **ToMe for Vision Transformers:** https://github.com/facebookresearch/ToMe diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000000000000000000000000000000000000..9263ef477f2ceb0d041c32ced7ad313d91f97a40 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,134 @@ +# Usage + +# First Run & UI Tour + +This page walks you through launching LightDiffusion-Next, understanding the Streamlit layout, using the optional Gradio UI and triggering a first generation from the command line. + +## Launching the Streamlit UI + +- **Windows:** run `run.bat` (see [Installation](installation.md)). +- **Linux/macOS/WSL2:** activate your virtual environment and run `streamlit run streamlit_app.py --server.port=8501`. +- **Docker:** start the compose stack and open `http://localhost:8501`. + +You will see an initialization progress indicator while checkpoints and auxiliary models are downloaded. Once complete the app switches to a two-tab layout: **🎨 Generate** and **📜 History**. + +## Generate tab + +The Generate tab is designed as a control surface where the left sidebar contains parameters and the right canvas displays previews and final renders. + +### Prompt & base settings + +- **Prompt / Negative prompt** — text areas at the top of the sidebar. Negative prompts are optional; the pipeline automatically falls back to a curated default containing `EasyNegative`, `badhandv4`, `lr` and `ng_deepnegative` embeddings. +- **Dimensions** — width/height sliders (64–2048) with automatic aspect handling in the gallery. +- **Images & batch** — request multiple images per job; large requests may be chunked server-side into groups no larger than `LD_MAX_IMAGES_PER_GROUP` images (default: 256) to avoid memory and disk pressure. Use the `batch_size` setting to control internal sampler batch size and adjust `LD_MAX_IMAGES_PER_GROUP` via environment variables if necessary. + +### Feature toggles + +- **HiRes Fix** — Upscales the latent and runs an extra sampling pass. Generates output in `output/HiresFix`. +- **ADetailer** — Uses SAM + YOLO and Impact Pack prompt heads to redraw faces/bodies. Additional artifacts are saved to `output/Adetailer`. +- **Enhance prompt** — Sends your prompt through the Ollama model specified by `PROMPT_ENHANCER_MODEL` (defaults to `qwen3:0.6b`). The rewritten prompt is shown in the sidebar and in image metadata. +- **Stable-Fast** — Enables UNet compilation (after the first warm-up) for faster iterations. +- **Flux mode** — Routes the job through the quantized Flux pipeline (requires the `ae.safetensors` VAE and quantized GGUF weights downloaded via `CheckAndDownloadFlux`). +- **Img2Img mode** — Reveals an image uploader. The selected picture is used as the source latent, optionally combined with UltimateSDUpscale. +- **Keep models in VRAM** — Toggle model caching between jobs to reduce load time at the cost of VRAM retention. +- **Real-time preview** — Streams TAESD previews into a responsive gallery while sampling is still running. Disable it when running headless to save resources. + +### Sampling & Scheduling + +The **⚡ Sampling & Scheduling** section provides direct control over the sampling process: + +- **Scheduler** — Choose from 8 scheduler options including the new **AYS (Align Your Steps)** schedulers which provide ~2x speedup by using optimized sigma distributions. Options include: + - Normal, Karras, Simple, Beta (traditional schedulers) + - AYS, AYS SD1.5, AYS SDXL, AYS Flux (optimized schedulers) +- **Sampler** — Select from 6 available samplers: + - Standard: Euler, Euler Ancestral + - CFG++ variants: Euler CFG++, Euler Ancestral CFG++, DPM++ 2M CFG++, DPM++ SDE CFG++ +- **Steps** — Adjust sampling steps (1-150). The UI shows recommendations based on your scheduler choice (e.g., 10 steps for AYS vs 20 for normal). +- **Prompt Cache** — Toggle prompt caching on/off (enabled by default). View cache statistics showing hits/misses and clear the cache when needed. + + +### Multi-scale diffusion presets + +Under the “Multi-Scale Diffusion Settings” accordion you can: + +- Choose a preset (`quality`, `performance`, `balanced`, `disabled`). +- Override the scale factor and the number of steps to run at full resolution. +- Enable intermittent full-resolution refinement. + +Multi-scale diffusion provides major frame-time savings at high resolutions and is enabled by default. + +### Model cache management + +- **🔍 Check VRAM Usage** — reports total/used/free VRAM, cached checkpoints and whether the “keep loaded” flag is active. +- **🗑️ Clear Model Cache** — evicts models from VRAM so the next job reloads everything fresh. + +### Status & previews + +- A status bar at the bottom of the page surfaces timing, generation stage and any warnings. +- When real-time preview is enabled, the canvas shows the six most recent TAESD frames. They disappear automatically when generation completes. + +## Keyboard shortcuts & session state + +- Most sliders support arrow-key and shift + arrow adjustments. +- The UI remembers your last-used settings inside `webui_settings.json`. Toggle “Verbose mode” in the settings drawer to see more runtime information. +- Seeds are stored in `include/last_seed.txt`. Enable “Reuse seed” to repeat a composition. + +## History tab + +- Displays every PNG in the `output/**` tree with metadata overlays (timestamp, dimensions, prompt). +- Use “🔄 Refresh History” to rescan the folders, “🗑️ Delete Selected Image” for targeted cleanup or “⚠️ Clear All Images” to wipe everything. +- Selections show exact file paths so you can open them in external editors. + +## Using the Gradio UI + +Run `python app.py` (or set `UI_FRAMEWORK=gradio` in Docker) to launch the Gradio frontend at `http://localhost:7860`. + +- The controls mirror the Streamlit sidebar but the layout is optimized for Hugging Face Spaces. +- Live previews stream directly to the main gallery while jobs run. +- The 📸 Image History tab reads from the same `output/` folders as Streamlit, so both UIs share artifacts and metadata. + +## Command-line pipeline + +You can invoke the pipeline without any UI for scripted jobs. + +```bash +python -m src.user.pipeline "a futuristic city at dusk" 768 512 2 2 --hires-fix --adetailer --stable-fast --reuse-seed +``` + +- Positional arguments: `prompt width height number batch`. +- Flags mirror the UI toggles (`--img2img`, `--flux`, `--prio-speed`, `--multiscale-preset`, etc.). +- Img2Img uses the prompt as a filesystem path unless you pass `--img2img-image` through the FastAPI server (see [REST & automation](api.md)). + +## Streamlit tips + +- Click “Retry Initialization” if the download step fails — the app reruns `CheckAndDownload()`. +- Use the sidebar menu → **Rerun** if you change source code while developing custom nodes. +- When running on laptops, disable “Keep models in VRAM” before closing the UI to release GPU memory for other applications. + +## Programmatic pipeline usage (Python) + +You can import and call the pipeline directly from Python. The function lives at `src.user.pipeline.pipeline` and accepts the same runtime flags as the CLI. The example below shows a minimal, synchronous call that runs the pipeline and handles the returned mapping when running in batched mode. + +```python +from src.user.pipeline import pipeline + +result = pipeline( + prompt=["a futuristic city at dusk", "a cyberpunk alley, rainy"], + w=768, + h=512, + number=2, + batch=2, + hires_fix=False, + adetailer=False, + stable_fast=False, + reuse_seed=False, + flux_enabled=False, +) + +# When run in batched mode `pipeline` returns a dict with key 'batched_results' +if isinstance(result, dict) and "batched_results" in result: + for req_id, entries in result["batched_results"].items(): + print(f"Request {req_id} produced {len(entries)} artifacts") +else: + print("Pipeline completed; check output/ for generated images") +``` \ No newline at end of file diff --git a/docs/wavespeed.md b/docs/wavespeed.md new file mode 100644 index 0000000000000000000000000000000000000000..124e84a04a6eeddb51e1353fa54edb1eae929586 --- /dev/null +++ b/docs/wavespeed.md @@ -0,0 +1,473 @@ +# WaveSpeed Caching + +## Overview + +WaveSpeed is the project's caching-oriented optimization layer for reusing work across denoising steps. In the current codebase, the integrated path is DeepCache for UNet-based models, and the repository also contains groundwork for a Flux-oriented First Block Cache path. + +LightDiffusion-Next contains two WaveSpeed-related implementations: + +1. **DeepCache** — Integrated for UNet-based models (SD1.5, SDXL) +2. **First Block Cache (FBCache)** — Flux-oriented cache machinery present in the codebase + +Both are training-free. DeepCache is the user-facing path today; First Block Cache is codebase groundwork for a more specialized transformer caching path. + +## How It Works + +### Core Insight + +Diffusion models denoise images iteratively over 20-50 steps. Researchers observed that: + +- **High-level features** (semantic structure, composition) change slowly across steps +- **Low-level features** (fine details, textures) require frequent updates + +WaveSpeed aims to reduce repeated computation across nearby denoising steps by reusing information from earlier steps where practical. + +### DeepCache (UNet Models) {#deepcache} + +DeepCache is the integrated WaveSpeed path for UNet models. + +**Cache step (every N steps):** +1. Run the full denoiser path +2. Store the output for later reuse + +**Reuse step (intermediate steps):** +1. Reuse the cached denoiser output +2. Skip the full model recomputation for that step + +**Speedup:** ~50-70% time saved per reuse step → 2-3x total speedup with `interval=3` + +### First Block Cache (Flux Models) + +Flux uses Transformer blocks instead of UNet convolutions. The repository includes a First Block Cache implementation for this architecture family: + +``` +┌─────────────────────────────────────────┐ +│ First Transformer Block (always run) │ ← Computes initial features +├─────────────────────────────────────────┤ +│ Remaining Blocks (cached if similar) │ ← FBCache caching zone +└─────────────────────────────────────────┘ +``` + +**Cache decision logic:** +1. Run first Transformer block +2. Compare output to previous step's output +3. If difference < threshold: reuse cached remaining blocks +4. If difference ≥ threshold: run all blocks and update cache + +In the current project structure, this cache path is implementation groundwork rather than a standard generation toggle like DeepCache. + +## DeepCache Configuration + +### Parameters + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `cache_interval` | int | 3 | Steps between cache updates (higher = faster, lower quality) | +| `cache_depth` | int | 2 | UNet depth for caching (0-12, higher = more aggressive) | +| `start_step` | int | 0 | Timestep to start caching (0-1000) | +| `end_step` | int | 1000 | Timestep to stop caching (0-1000) | + +### Streamlit UI + +Enable in the **⚡ DeepCache Acceleration** expander: + +1. Check **Enable DeepCache** +2. Adjust sliders: + - **Cache Interval**: 1-10 (default: 3) + - **Cache Depth**: 0-12 (default: 2) + - **Start/End Steps**: 0-1000 (default: 0/1000) +3. Generate images — caching applies transparently + +### REST API + +```bash +curl -X POST http://localhost:7861/api/generate \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "a misty forest at twilight", + "width": 768, + "height": 512, + "deepcache_enabled": true, + "deepcache_interval": 3, + "deepcache_depth": 2 + }' +``` + +### Recommended Presets + +#### Balanced (Default) +```yaml +cache_interval: 3 +cache_depth: 2 +start_step: 0 +end_step: 1000 +``` +- **Speedup:** 2-2.3x +- **Quality loss:** Very slight (1-2%) +- **Use case:** Everyday generation + +#### Maximum Speed +```yaml +cache_interval: 5 +cache_depth: 3 +start_step: 0 +end_step: 1000 +``` +- **Speedup:** 2.5-3x +- **Quality loss:** Noticeable (5-7%) +- **Use case:** Rapid prototyping, batch jobs + +#### Maximum Quality +```yaml +cache_interval: 2 +cache_depth: 1 +start_step: 0 +end_step: 1000 +``` +- **Speedup:** 1.5-2x +- **Quality loss:** Minimal (<1%) +- **Use case:** Final renders, client work + +#### Partial Caching (Critical Steps Only) +```yaml +cache_interval: 3 +cache_depth: 2 +start_step: 200 +end_step: 800 +``` +- **Speedup:** 1.8-2.2x +- **Quality loss:** Minimal +- **Use case:** Preserve early structure, late details + +## First Block Cache (FBCache) Configuration + +### Parameters + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `residual_diff_threshold` | float | 0.05 | Max feature difference to trigger cache reuse (0.0-1.0) | + +### Usage + +First Block Cache is not currently exposed as a standard per-generation toggle. The implementation is available in the codebase for specialized integration work: + +```python +# In src/user/pipeline.py +from src.WaveSpeed import fbcache_nodes + +# Create cache context +cache_context = fbcache_nodes.create_cache_context() + +# Apply caching to a Flux-style model +with fbcache_nodes.cache_context(cache_context): + patched_model = fbcache_nodes.create_patch_flux_forward_orig( + flux_model, + residual_diff_threshold=0.05, # Lower = stricter caching + ) + # Generate images... +``` + +### Tuning Threshold + +- **Lower threshold (0.01-0.03)**: Stricter caching, recomputes more often, higher quality +- **Higher threshold (0.05-0.1)**: Looser caching, reuses more often, higher speedup +- **Recommended:** 0.05 (balances quality and speed) + +## Performance + +### Speedup Guidance + +Speedup scales with cache interval and depth: + +| Model | Cache Interval | Expected Behavior | +|-------|---------------|-------------------| +| SD1.5 | 2 | Moderate speedup, minimal quality loss | +| SD1.5 | 3 | Good speedup, slight quality loss | +| SD1.5 | 5 | High speedup, noticeable quality loss | +| SDXL | 3 | Good speedup, slight quality loss | +| Flux-style caching paths | implementation-specific | Depends on the integration path | + +**Performance varies based on:** +- GPU architecture +- Model size +- Resolution +- Sampler choice +- Number of steps + +**Recommendation:** Start with `interval=3` and adjust based on your quality requirements.### VRAM Impact + +Caching increases VRAM usage slightly (50-200MB depending on resolution): + +| Model | Baseline VRAM | + DeepCache | Increase | +|-------|--------------|-------------|----------| +| SD1.5 (768×512) | 3.2 GB | 3.4 GB | +200 MB | +| SDXL (1024×1024) | 6.8 GB | 7.0 GB | +200 MB | +| Flux (832×1216) | 12.5 GB | 12.6 GB | +100 MB | + +## Stacking with Other Optimizations + +WaveSpeed is **fully compatible** with SageAttention, SpargeAttn and Stable-Fast: + +### DeepCache + SageAttention + +```yaml +deepcache_enabled: true +deepcache_interval: 3 +# SageAttention auto-detected +``` + +**Result:** 2.2x (DeepCache) × 1.15 (SageAttention) = **~2.5x total speedup** + +### DeepCache + SpargeAttn + +```yaml +deepcache_enabled: true +deepcache_interval: 3 +# SpargeAttn auto-detected +``` + +**Result:** Enhanced speedup from caching and sparse attention + +### DeepCache + Stable-Fast + SpargeAttn + +```yaml +stable_fast: true +deepcache_enabled: true +deepcache_interval: 3 +# SpargeAttn auto-detected +``` + +**Result:** Maximum combined speedup (all optimizations active, batch operations only) + +## Compatibility + +### DeepCache Compatible With + +- ✅ Stable Diffusion 1.5 +- ✅ Stable Diffusion 2.1 +- ✅ SDXL +- ✅ All samplers (Euler, DPM++, etc.) +- ✅ LoRA adapters +- ✅ Textual inversion embeddings +- ✅ HiresFix +- ✅ ADetailer +- ✅ Multi-scale diffusion +- ✅ SageAttention/SpargeAttn +- ✅ Stable-Fast + +### DeepCache NOT Compatible With + +- ❌ Flux models (use FBCache instead) +- ❌ Img2Img mode (can cause artifacts) + +### FBCache Compatible With + +- ✅ Flux models +- ✅ SageAttention/SpargeAttn +- ✅ All Flux-compatible features + +### FBCache NOT Compatible With + +- ❌ SD1.5/SDXL (use DeepCache instead) +- ❌ Stable-Fast (Flux not supported by Stable-Fast) + +## Troubleshooting + +### No Speedup Observed + +**Causes:** +1. DeepCache disabled or not applied to correct model type +2. Cache interval too low (interval=1 provides no caching) +3. Model loaded incorrectly + +**Fixes:** +```bash +# Check logs for DeepCache activation +cat logs/server.log | grep -i "deepcache\|cache" + +# Verify UI toggle is enabled +# Streamlit: Check "Enable DeepCache" checkbox +# API: Ensure "deepcache_enabled": true in payload + +# Try higher interval +deepcache_interval: 3 # Instead of 1 or 2 +``` + +### Quality Degradation + +**Symptoms:** +- Blurry details +- Smoothed textures +- Loss of fine patterns + +**Causes:** +1. Cache interval too high +2. Cache depth too aggressive +3. Wrong model type (Flux using DeepCache) + +**Fixes:** +```yaml +# Reduce cache interval +deepcache_interval: 2 # Down from 5 + +# Reduce cache depth +deepcache_depth: 1 # Down from 3 + +# Disable caching for critical phases +deepcache_start_step: 200 # Skip early structure formation +deepcache_end_step: 800 # Skip late detail refinement +``` + +### Artifacts in Img2Img + +**Symptom:** Visible seams, inconsistent styles when using DeepCache with Img2Img. + +**Cause:** Img2Img starts from a noisy input image, which violates DeepCache's assumptions about feature consistency. + +**Fix:** Disable DeepCache for Img2Img: +```yaml +deepcache_enabled: false # When img2img_enabled: true +``` + +### VRAM Increase + +**Symptom:** OOM errors after enabling DeepCache. + +**Cause:** Cached features consume additional VRAM. + +**Fixes:** +1. Reduce batch size +2. Lower resolution +3. Disable other VRAM-heavy features (Stable-Fast CUDA graphs) +4. Use lower cache depth: + ```yaml + deepcache_depth: 1 # Minimal caching + ``` + +### Flux FBCache Not Working + +**Symptom:** No speedup with Flux generation. + +**Cause:** FBCache implementation is more subtle — check logs for cache hit rate. + +**Debugging:** +```bash +# Enable debug logging +export LD_SERVER_LOGLEVEL=DEBUG + +# Check cache statistics +cat logs/server.log | grep "cache" +``` + +If no cache hits, try adjusting threshold: +```python +# In pipeline.py +residual_diff_threshold=0.1 # Increase from 0.05 for more cache reuse +``` + +## Quality Comparison + +Visual impact of different cache intervals: + +| Interval | Speed | Visual Difference | +|----------|-------|-------------------| +| Disabled | Baseline | Baseline (100% quality) | +| 2 | Faster | Virtually identical | +| 3 | Much faster | Very subtle smoothing | +| 5 | Very fast | Noticeable detail loss | +| 7+ | Fastest | Obvious quality degradation | + +**Recommendation:** Start with `interval=3` and adjust based on visual results. + +## Technical Details + +### DeepCache Implementation + +Simplified pseudocode: + +```python +class DeepCacheWrapper: + def __init__(self, model, interval, depth): + self.model = model + self.interval = interval + self.cached_output = None + self.current_step = 0 + + def forward(self, x, timestep): + is_cache_step = (self.current_step % self.interval == 0) + + if is_cache_step: + # Run full model, cache output + output = self.model(x, timestep) + self.cached_output = output.clone() + else: + # Reuse cached output (skip expensive computation) + output = self.cached_output + + self.current_step += 1 + return output +``` + +Actual implementation in `src/WaveSpeed/deepcache_nodes.py` includes: +- Proper timestep tracking +- Cache invalidation on batch changes +- Error handling and fallback to full forward + +### FBCache Residual Comparison + +```python +# Compute first block output +first_output = first_transformer_block(hidden_states) + +# Compare to previous step +residual = first_output - previous_first_output +residual_norm = residual.abs().mean() / first_output.abs().mean() + +if residual_norm < threshold: + # Feature change is small — reuse cached blocks + hidden_states = apply_cached_residual(first_output) +else: + # Feature change is large — recompute all blocks + hidden_states = run_remaining_blocks(first_output) + cache_residual(hidden_states) +``` + +## Best Practices + +### For Everyday Use + +1. **Enable DeepCache** with default settings (`interval=3`, `depth=2`) +2. **Stack with SageAttention** for 2.5x+ total speedup +3. **Disable for final client renders** if absolute quality is critical + +### For Batch Processing + +1. **Use aggressive caching** (`interval=5`, `depth=3`) +2. **Pre-generate previews** at high speed, re-render winners at full quality +3. **Disable TAESD previews** to avoid overhead (set `enable_preview=false`) + +### For Low VRAM + +1. **Use conservative caching** (`interval=2`, `depth=1`) +2. **Avoid stacking** with Stable-Fast CUDA graphs +3. **Monitor VRAM** via `/api/telemetry` endpoint + +## Citation + +If you use WaveSpeed/DeepCache in your work: + +```bibtex +@inproceedings{ma2023deepcache, + title={DeepCache: Accelerating Diffusion Models for Free}, + author={Ma, Xinyin and Fang, Gongfan and Wang, Xinchao}, + booktitle={CVPR}, + year={2024} +} +``` + +## Resources + +- [DeepCache Paper](https://arxiv.org/abs/2312.00858) +- [DeepCache Repository](https://github.com/horseee/DeepCache) +- [ComfyUI DeepCache Implementation](https://gist.github.com/laksjdjf/435c512bc19636e9c9af4ee7bea9eb86) (reference for LightDiffusion-Next) +- [First Block Cache Discussion](https://github.com/comfyanonymous/ComfyUI/discussions/3491) diff --git a/download_flux.py b/download_flux.py new file mode 100644 index 0000000000000000000000000000000000000000..ed408e8f42ca3705284a68abc6a55112341d857a --- /dev/null +++ b/download_flux.py @@ -0,0 +1,21 @@ +import os +import sys +from pathlib import Path + +# Add project root to path +project_root = Path(__file__).resolve().parent +sys.path.insert(0, str(project_root)) + +try: + from src.FileManaging import Downloader + print("Initializing Flux2 Klein download...") + Downloader.CheckAndDownloadFlux2() + print("\nDownload process finished.") + print("Models should be located in:") + print(" - ./include/diffusion_model/ (Diffusion Model)") + print(" - ./include/text_encoder/ (Text Encoder)") + print(" - ./include/vae/ (VAE)") +except ImportError as e: + print(f"Error: Could not import Downloader. Make sure you are running this from the project root. {e}") +except Exception as e: + print(f"An unexpected error occurred: {e}") \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d2e77611fd3d959fee0487c41bd27b318be32b04 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,73 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: + +```js +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + + // Remove tseslint.configs.recommended and replace with this + tseslint.configs.recommendedTypeChecked, + // Alternatively, use this for stricter rules + tseslint.configs.strictTypeChecked, + // Optionally, add this for stylistic rules + tseslint.configs.stylisticTypeChecked, + + // Other configs... + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` + +You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: + +```js +// eslint.config.js +import reactX from 'eslint-plugin-react-x' +import reactDom from 'eslint-plugin-react-dom' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + // Enable lint rules for React + reactX.configs['recommended-typescript'], + // Enable lint rules for React DOM + reactDom.configs.recommended, + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` diff --git a/frontend/dist/assets/index-7kNA4Hm-.js b/frontend/dist/assets/index-7kNA4Hm-.js new file mode 100644 index 0000000000000000000000000000000000000000..c41cfbf75ceaca6456aac72c6537062bf4667e61 --- /dev/null +++ b/frontend/dist/assets/index-7kNA4Hm-.js @@ -0,0 +1,62 @@ +function lE(n,l){for(var r=0;ro[c]})}}}return Object.freeze(Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}))}(function(){const l=document.createElement("link").relList;if(l&&l.supports&&l.supports("modulepreload"))return;for(const c of document.querySelectorAll('link[rel="modulepreload"]'))o(c);new MutationObserver(c=>{for(const u of c)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&o(d)}).observe(document,{childList:!0,subtree:!0});function r(c){const u={};return c.integrity&&(u.integrity=c.integrity),c.referrerPolicy&&(u.referrerPolicy=c.referrerPolicy),c.crossOrigin==="use-credentials"?u.credentials="include":c.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function o(c){if(c.ep)return;c.ep=!0;const u=r(c);fetch(c.href,u)}})();function Gr(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var Tf={exports:{}},Dr={};var bg;function iE(){if(bg)return Dr;bg=1;var n=Symbol.for("react.transitional.element"),l=Symbol.for("react.fragment");function r(o,c,u){var d=null;if(u!==void 0&&(d=""+u),c.key!==void 0&&(d=""+c.key),"key"in c){u={};for(var p in c)p!=="key"&&(u[p]=c[p])}else u=c;return c=u.ref,{$$typeof:n,type:o,key:d,ref:c!==void 0?c:null,props:u}}return Dr.Fragment=l,Dr.jsx=r,Dr.jsxs=r,Dr}var xg;function rE(){return xg||(xg=1,Tf.exports=iE()),Tf.exports}var b=rE(),Of={exports:{}},we={};var Sg;function oE(){if(Sg)return we;Sg=1;var n=Symbol.for("react.transitional.element"),l=Symbol.for("react.portal"),r=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),c=Symbol.for("react.profiler"),u=Symbol.for("react.consumer"),d=Symbol.for("react.context"),p=Symbol.for("react.forward_ref"),h=Symbol.for("react.suspense"),m=Symbol.for("react.memo"),v=Symbol.for("react.lazy"),y=Symbol.for("react.activity"),w=Symbol.iterator;function _(N){return N===null||typeof N!="object"?null:(N=w&&N[w]||N["@@iterator"],typeof N=="function"?N:null)}var E={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},S=Object.assign,A={};function T(N,F,te){this.props=N,this.context=F,this.refs=A,this.updater=te||E}T.prototype.isReactComponent={},T.prototype.setState=function(N,F){if(typeof N!="object"&&typeof N!="function"&&N!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,N,F,"setState")},T.prototype.forceUpdate=function(N){this.updater.enqueueForceUpdate(this,N,"forceUpdate")};function O(){}O.prototype=T.prototype;function j(N,F,te){this.props=N,this.context=F,this.refs=A,this.updater=te||E}var z=j.prototype=new O;z.constructor=j,S(z,T.prototype),z.isPureReactComponent=!0;var k=Array.isArray;function Y(){}var U={H:null,A:null,T:null,S:null},I=Object.prototype.hasOwnProperty;function ae(N,F,te){var ne=te.ref;return{$$typeof:n,type:N,key:F,ref:ne!==void 0?ne:null,props:te}}function ce(N,F){return ae(N.type,F,N.props)}function H(N){return typeof N=="object"&&N!==null&&N.$$typeof===n}function le(N){var F={"=":"=0",":":"=2"};return"$"+N.replace(/[=:]/g,function(te){return F[te]})}var ve=/\/+/g;function re(N,F){return typeof N=="object"&&N!==null&&N.key!=null?le(""+N.key):F.toString(36)}function de(N){switch(N.status){case"fulfilled":return N.value;case"rejected":throw N.reason;default:switch(typeof N.status=="string"?N.then(Y,Y):(N.status="pending",N.then(function(F){N.status==="pending"&&(N.status="fulfilled",N.value=F)},function(F){N.status==="pending"&&(N.status="rejected",N.reason=F)})),N.status){case"fulfilled":return N.value;case"rejected":throw N.reason}}throw N}function M(N,F,te,ne,ie){var se=typeof N;(se==="undefined"||se==="boolean")&&(N=null);var $=!1;if(N===null)$=!0;else switch(se){case"bigint":case"string":case"number":$=!0;break;case"object":switch(N.$$typeof){case n:case l:$=!0;break;case v:return $=N._init,M($(N._payload),F,te,ne,ie)}}if($)return ie=ie(N),$=ne===""?"."+re(N,0):ne,k(ie)?(te="",$!=null&&(te=$.replace(ve,"$&/")+"/"),M(ie,F,te,"",function(Oe){return Oe})):ie!=null&&(H(ie)&&(ie=ce(ie,te+(ie.key==null||N&&N.key===ie.key?"":(""+ie.key).replace(ve,"$&/")+"/")+$)),F.push(ie)),1;$=0;var Se=ne===""?".":ne+":";if(k(N))for(var pe=0;pe>>1,J=M[ee];if(0>>1;eec(te,W))nec(ie,te)?(M[ee]=ie,M[ne]=W,ee=ne):(M[ee]=te,M[F]=W,ee=F);else if(nec(ie,W))M[ee]=ie,M[ne]=W,ee=ne;else break e}}return Q}function c(M,Q){var W=M.sortIndex-Q.sortIndex;return W!==0?W:M.id-Q.id}if(n.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var u=performance;n.unstable_now=function(){return u.now()}}else{var d=Date,p=d.now();n.unstable_now=function(){return d.now()-p}}var h=[],m=[],v=1,y=null,w=3,_=!1,E=!1,S=!1,A=!1,T=typeof setTimeout=="function"?setTimeout:null,O=typeof clearTimeout=="function"?clearTimeout:null,j=typeof setImmediate<"u"?setImmediate:null;function z(M){for(var Q=r(m);Q!==null;){if(Q.callback===null)o(m);else if(Q.startTime<=M)o(m),Q.sortIndex=Q.expirationTime,l(h,Q);else break;Q=r(m)}}function k(M){if(S=!1,z(M),!E)if(r(h)!==null)E=!0,Y||(Y=!0,le());else{var Q=r(m);Q!==null&&de(k,Q.startTime-M)}}var Y=!1,U=-1,I=5,ae=-1;function ce(){return A?!0:!(n.unstable_now()-aeM&&ce());){var ee=y.callback;if(typeof ee=="function"){y.callback=null,w=y.priorityLevel;var J=ee(y.expirationTime<=M);if(M=n.unstable_now(),typeof J=="function"){y.callback=J,z(M),Q=!0;break t}y===r(h)&&o(h),z(M)}else o(h);y=r(h)}if(y!==null)Q=!0;else{var N=r(m);N!==null&&de(k,N.startTime-M),Q=!1}}break e}finally{y=null,w=W,_=!1}Q=void 0}}finally{Q?le():Y=!1}}}var le;if(typeof j=="function")le=function(){j(H)};else if(typeof MessageChannel<"u"){var ve=new MessageChannel,re=ve.port2;ve.port1.onmessage=H,le=function(){re.postMessage(null)}}else le=function(){T(H,0)};function de(M,Q){U=T(function(){M(n.unstable_now())},Q)}n.unstable_IdlePriority=5,n.unstable_ImmediatePriority=1,n.unstable_LowPriority=4,n.unstable_NormalPriority=3,n.unstable_Profiling=null,n.unstable_UserBlockingPriority=2,n.unstable_cancelCallback=function(M){M.callback=null},n.unstable_forceFrameRate=function(M){0>M||125ee?(M.sortIndex=W,l(m,M),r(h)===null&&M===r(m)&&(S?(O(U),U=-1):S=!0,de(k,W-ee))):(M.sortIndex=J,l(h,M),E||_||(E=!0,Y||(Y=!0,le()))),M},n.unstable_shouldYield=ce,n.unstable_wrapCallback=function(M){var Q=w;return function(){var W=w;w=Q;try{return M.apply(this,arguments)}finally{w=W}}}})(jf)),jf}var _g;function sE(){return _g||(_g=1,Nf.exports=cE()),Nf.exports}var Df={exports:{}},At={};var Cg;function uE(){if(Cg)return At;Cg=1;var n=Ni();function l(h){var m="https://react.dev/errors/"+h;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(l){console.error(l)}}return n(),Df.exports=uE(),Df.exports}var Tg;function fE(){if(Tg)return Mr;Tg=1;var n=sE(),l=Ni(),r=Od();function o(e){var t="https://react.dev/errors/"+e;if(1J||(e.current=ee[J],ee[J]=null,J--)}function te(e,t){J++,ee[J]=e.current,e.current=t}var ne=N(null),ie=N(null),se=N(null),$=N(null);function Se(e,t){switch(te(se,t),te(ie,e),te(ne,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Pv(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Pv(t),e=Gv(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}F(ne),te(ne,e)}function pe(){F(ne),F(ie),F(se)}function Oe(e){e.memoizedState!==null&&te($,e);var t=ne.current,a=Gv(t,e.type);t!==a&&(te(ie,e),te(ne,a))}function Ce(e){ie.current===e&&(F(ne),F(ie)),$.current===e&&(F($),Or._currentValue=W)}var ke,Ke;function nt(e){if(ke===void 0)try{throw Error()}catch(a){var t=a.stack.trim().match(/\n( *(at )?)/);ke=t&&t[1]||"",Ke=-1)":-1s||R[i]!==q[s]){var X=` +`+R[i].replace(" at new "," at ");return e.displayName&&X.includes("")&&(X=X.replace("",e.displayName)),X}while(1<=i&&0<=s);break}}}finally{_n=!1,Error.prepareStackTrace=a}return(a=e?e.displayName||e.name:"")?nt(a):""}function ha(e,t){switch(e.tag){case 26:case 27:case 5:return nt(e.type);case 16:return nt("Lazy");case 13:return e.child!==t&&t!==null?nt("Suspense Fallback"):nt("Suspense");case 19:return nt("SuspenseList");case 0:case 15:return Cn(e.type,!1);case 11:return Cn(e.type.render,!1);case 1:return Cn(e.type,!0);case 31:return nt("Activity");default:return""}}function Vn(e){try{var t="",a=null;do t+=ha(e,a),a=e,e=e.return;while(e);return t}catch(i){return` +Error generating stack: `+i.message+` +`+i.stack}}var el=Object.prototype.hasOwnProperty,va=n.unstable_scheduleCallback,ga=n.unstable_cancelCallback,ds=n.unstable_shouldYield,ps=n.unstable_requestPaint,Rt=n.unstable_now,oe=n.unstable_getCurrentPriorityLevel,ye=n.unstable_ImmediatePriority,Ze=n.unstable_UserBlockingPriority,We=n.unstable_NormalPriority,dt=n.unstable_LowPriority,Pt=n.unstable_IdlePriority,mn=n.log,Ui=n.unstable_setDisableYieldValue,Pn=null,bt=null;function Gt(e){if(typeof mn=="function"&&Ui(e),bt&&typeof bt.setStrictMode=="function")try{bt.setStrictMode(Pn,e)}catch{}}var xt=Math.clz32?Math.clz32:qi,Hi=Math.log,Bi=Math.LN2;function qi(e){return e>>>=0,e===0?32:31-(Hi(e)/Bi|0)|0}var kl=256,Wr=262144,Jr=4194304;function tl(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function $r(e,t,a){var i=e.pendingLanes;if(i===0)return 0;var s=0,f=e.suspendedLanes,g=e.pingedLanes;e=e.warmLanes;var C=i&134217727;return C!==0?(i=C&~f,i!==0?s=tl(i):(g&=C,g!==0?s=tl(g):a||(a=C&~e,a!==0&&(s=tl(a))))):(C=i&~f,C!==0?s=tl(C):g!==0?s=tl(g):a||(a=i&~e,a!==0&&(s=tl(a)))),s===0?0:t!==0&&t!==s&&(t&f)===0&&(f=s&-s,a=t&-t,f>=a||f===32&&(a&4194048)!==0)?t:s}function Vi(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function FS(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Ep(){var e=Jr;return Jr<<=1,(Jr&62914560)===0&&(Jr=4194304),e}function ms(e){for(var t=[],a=0;31>a;a++)t.push(e);return t}function Pi(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function XS(e,t,a,i,s,f){var g=e.pendingLanes;e.pendingLanes=a,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=a,e.entangledLanes&=a,e.errorRecoveryDisabledLanes&=a,e.shellSuspendCounter=0;var C=e.entanglements,R=e.expirationTimes,q=e.hiddenUpdates;for(a=g&~a;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var JS=/[\n"\\]/g;function tn(e){return e.replace(JS,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function xs(e,t,a,i,s,f,g,C){e.name="",g!=null&&typeof g!="function"&&typeof g!="symbol"&&typeof g!="boolean"?e.type=g:e.removeAttribute("type"),t!=null?g==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+en(t)):e.value!==""+en(t)&&(e.value=""+en(t)):g!=="submit"&&g!=="reset"||e.removeAttribute("value"),t!=null?Ss(e,g,en(t)):a!=null?Ss(e,g,en(a)):i!=null&&e.removeAttribute("value"),s==null&&f!=null&&(e.defaultChecked=!!f),s!=null&&(e.checked=s&&typeof s!="function"&&typeof s!="symbol"),C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"?e.name=""+en(C):e.removeAttribute("name")}function Lp(e,t,a,i,s,f,g,C){if(f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"&&(e.type=f),t!=null||a!=null){if(!(f!=="submit"&&f!=="reset"||t!=null)){bs(e);return}a=a!=null?""+en(a):"",t=t!=null?""+en(t):a,C||t===e.value||(e.value=t),e.defaultValue=t}i=i??s,i=typeof i!="function"&&typeof i!="symbol"&&!!i,e.checked=C?e.checked:!!i,e.defaultChecked=!!i,g!=null&&typeof g!="function"&&typeof g!="symbol"&&typeof g!="boolean"&&(e.name=g),bs(e)}function Ss(e,t,a){t==="number"&&no(e.ownerDocument)===e||e.defaultValue===""+a||(e.defaultValue=""+a)}function Vl(e,t,a,i){if(e=e.options,t){t={};for(var s=0;s"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),As=!1;if(Fn)try{var Xi={};Object.defineProperty(Xi,"passive",{get:function(){As=!0}}),window.addEventListener("test",Xi,Xi),window.removeEventListener("test",Xi,Xi)}catch{As=!1}var ba=null,Ts=null,lo=null;function Gp(){if(lo)return lo;var e,t=Ts,a=t.length,i,s="value"in ba?ba.value:ba.textContent,f=s.length;for(e=0;e=Ki),Kp=" ",Zp=!1;function Wp(e,t){switch(e){case"keyup":return Aw.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Jp(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var Fl=!1;function Ow(e,t){switch(e){case"compositionend":return Jp(t);case"keypress":return t.which!==32?null:(Zp=!0,Kp);case"textInput":return e=t.data,e===Kp&&Zp?null:e;default:return null}}function Rw(e,t){if(Fl)return e==="compositionend"||!Ds&&Wp(e,t)?(e=Gp(),lo=Ts=ba=null,Fl=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:a,offset:t-e};e=i}e:{for(;a;){if(a.nextSibling){a=a.nextSibling;break e}a=a.parentNode}a=void 0}a=rm(a)}}function cm(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?cm(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function sm(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=no(e.document);t instanceof e.HTMLIFrameElement;){try{var a=typeof t.contentWindow.location.href=="string"}catch{a=!1}if(a)e=t.contentWindow;else break;t=no(e.document)}return t}function ks(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var Uw=Fn&&"documentMode"in document&&11>=document.documentMode,Xl=null,Ls=null,$i=null,Us=!1;function um(e,t,a){var i=a.window===a?a.document:a.nodeType===9?a:a.ownerDocument;Us||Xl==null||Xl!==no(i)||(i=Xl,"selectionStart"in i&&ks(i)?i={start:i.selectionStart,end:i.selectionEnd}:(i=(i.ownerDocument&&i.ownerDocument.defaultView||window).getSelection(),i={anchorNode:i.anchorNode,anchorOffset:i.anchorOffset,focusNode:i.focusNode,focusOffset:i.focusOffset}),$i&&Ji($i,i)||($i=i,i=Jo(Ls,"onSelect"),0>=g,s-=g,An=1<<32-xt(t)+s|a<_e?(De=he,he=null):De=he.sibling;var Ue=V(L,he,B[_e],K);if(Ue===null){he===null&&(he=De);break}e&&he&&Ue.alternate===null&&t(L,he),D=f(Ue,D,_e),Le===null?ge=Ue:Le.sibling=Ue,Le=Ue,he=De}if(_e===B.length)return a(L,he),Me&&In(L,_e),ge;if(he===null){for(;_e_e?(De=he,he=null):De=he.sibling;var Va=V(L,he,Ue.value,K);if(Va===null){he===null&&(he=De);break}e&&he&&Va.alternate===null&&t(L,he),D=f(Va,D,_e),Le===null?ge=Va:Le.sibling=Va,Le=Va,he=De}if(Ue.done)return a(L,he),Me&&In(L,_e),ge;if(he===null){for(;!Ue.done;_e++,Ue=B.next())Ue=Z(L,Ue.value,K),Ue!==null&&(D=f(Ue,D,_e),Le===null?ge=Ue:Le.sibling=Ue,Le=Ue);return Me&&In(L,_e),ge}for(he=i(he);!Ue.done;_e++,Ue=B.next())Ue=G(he,L,_e,Ue.value,K),Ue!==null&&(e&&Ue.alternate!==null&&he.delete(Ue.key===null?_e:Ue.key),D=f(Ue,D,_e),Le===null?ge=Ue:Le.sibling=Ue,Le=Ue);return e&&he.forEach(function(aE){return t(L,aE)}),Me&&In(L,_e),ge}function Fe(L,D,B,K){if(typeof B=="object"&&B!==null&&B.type===S&&B.key===null&&(B=B.props.children),typeof B=="object"&&B!==null){switch(B.$$typeof){case _:e:{for(var ge=B.key;D!==null;){if(D.key===ge){if(ge=B.type,ge===S){if(D.tag===7){a(L,D.sibling),K=s(D,B.props.children),K.return=L,L=K;break e}}else if(D.elementType===ge||typeof ge=="object"&&ge!==null&&ge.$$typeof===I&&dl(ge)===D.type){a(L,D.sibling),K=s(D,B.props),ir(K,B),K.return=L,L=K;break e}a(L,D);break}else t(L,D);D=D.sibling}B.type===S?(K=ol(B.props.children,L.mode,K,B.key),K.return=L,L=K):(K=ho(B.type,B.key,B.props,null,L.mode,K),ir(K,B),K.return=L,L=K)}return g(L);case E:e:{for(ge=B.key;D!==null;){if(D.key===ge)if(D.tag===4&&D.stateNode.containerInfo===B.containerInfo&&D.stateNode.implementation===B.implementation){a(L,D.sibling),K=s(D,B.children||[]),K.return=L,L=K;break e}else{a(L,D);break}else t(L,D);D=D.sibling}K=Ys(B,L.mode,K),K.return=L,L=K}return g(L);case I:return B=dl(B),Fe(L,D,B,K)}if(de(B))return ue(L,D,B,K);if(le(B)){if(ge=le(B),typeof ge!="function")throw Error(o(150));return B=ge.call(B),be(L,D,B,K)}if(typeof B.then=="function")return Fe(L,D,wo(B),K);if(B.$$typeof===j)return Fe(L,D,yo(L,B),K);Eo(L,B)}return typeof B=="string"&&B!==""||typeof B=="number"||typeof B=="bigint"?(B=""+B,D!==null&&D.tag===6?(a(L,D.sibling),K=s(D,B),K.return=L,L=K):(a(L,D),K=Gs(B,L.mode,K),K.return=L,L=K),g(L)):a(L,D)}return function(L,D,B,K){try{lr=0;var ge=Fe(L,D,B,K);return ai=null,ge}catch(he){if(he===ni||he===xo)throw he;var Le=Ft(29,he,null,L.mode);return Le.lanes=K,Le.return=L,Le}}}var ml=Mm(!0),zm=Mm(!1),_a=!1;function nu(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function au(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Ca(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Aa(e,t,a){var i=e.updateQueue;if(i===null)return null;if(i=i.shared,(He&2)!==0){var s=i.pending;return s===null?t.next=t:(t.next=s.next,s.next=t),i.pending=t,t=mo(e),gm(e,null,a),t}return po(e,i,t,a),mo(e)}function rr(e,t,a){if(t=t.updateQueue,t!==null&&(t=t.shared,(a&4194048)!==0)){var i=t.lanes;i&=e.pendingLanes,a|=i,t.lanes=a,Cp(e,a)}}function lu(e,t){var a=e.updateQueue,i=e.alternate;if(i!==null&&(i=i.updateQueue,a===i)){var s=null,f=null;if(a=a.firstBaseUpdate,a!==null){do{var g={lane:a.lane,tag:a.tag,payload:a.payload,callback:null,next:null};f===null?s=f=g:f=f.next=g,a=a.next}while(a!==null);f===null?s=f=t:f=f.next=t}else s=f=t;a={baseState:i.baseState,firstBaseUpdate:s,lastBaseUpdate:f,shared:i.shared,callbacks:i.callbacks},e.updateQueue=a;return}e=a.lastBaseUpdate,e===null?a.firstBaseUpdate=t:e.next=t,a.lastBaseUpdate=t}var iu=!1;function or(){if(iu){var e=ti;if(e!==null)throw e}}function cr(e,t,a,i){iu=!1;var s=e.updateQueue;_a=!1;var f=s.firstBaseUpdate,g=s.lastBaseUpdate,C=s.shared.pending;if(C!==null){s.shared.pending=null;var R=C,q=R.next;R.next=null,g===null?f=q:g.next=q,g=R;var X=e.alternate;X!==null&&(X=X.updateQueue,C=X.lastBaseUpdate,C!==g&&(C===null?X.firstBaseUpdate=q:C.next=q,X.lastBaseUpdate=R))}if(f!==null){var Z=s.baseState;g=0,X=q=R=null,C=f;do{var V=C.lane&-536870913,G=V!==C.lane;if(G?(je&V)===V:(i&V)===V){V!==0&&V===ei&&(iu=!0),X!==null&&(X=X.next={lane:0,tag:C.tag,payload:C.payload,callback:null,next:null});e:{var ue=e,be=C;V=t;var Fe=a;switch(be.tag){case 1:if(ue=be.payload,typeof ue=="function"){Z=ue.call(Fe,Z,V);break e}Z=ue;break e;case 3:ue.flags=ue.flags&-65537|128;case 0:if(ue=be.payload,V=typeof ue=="function"?ue.call(Fe,Z,V):ue,V==null)break e;Z=y({},Z,V);break e;case 2:_a=!0}}V=C.callback,V!==null&&(e.flags|=64,G&&(e.flags|=8192),G=s.callbacks,G===null?s.callbacks=[V]:G.push(V))}else G={lane:V,tag:C.tag,payload:C.payload,callback:C.callback,next:null},X===null?(q=X=G,R=Z):X=X.next=G,g|=V;if(C=C.next,C===null){if(C=s.shared.pending,C===null)break;G=C,C=G.next,G.next=null,s.lastBaseUpdate=G,s.shared.pending=null}}while(!0);X===null&&(R=Z),s.baseState=R,s.firstBaseUpdate=q,s.lastBaseUpdate=X,f===null&&(s.shared.lanes=0),ja|=g,e.lanes=g,e.memoizedState=Z}}function km(e,t){if(typeof e!="function")throw Error(o(191,e));e.call(t)}function Lm(e,t){var a=e.callbacks;if(a!==null)for(e.callbacks=null,e=0;ef?f:8;var g=M.T,C={};M.T=C,_u(e,!1,t,a);try{var R=s(),q=M.S;if(q!==null&&q(C,R),R!==null&&typeof R=="object"&&typeof R.then=="function"){var X=Xw(R,i);fr(e,t,X,Zt(e))}else fr(e,t,i,Zt(e))}catch(Z){fr(e,t,{then:function(){},status:"rejected",reason:Z},Zt())}finally{Q.p=f,g!==null&&C.types!==null&&(g.types=C.types),M.T=g}}function Jw(){}function wu(e,t,a,i){if(e.tag!==5)throw Error(o(476));var s=mh(e).queue;ph(e,s,t,W,a===null?Jw:function(){return hh(e),a(i)})}function mh(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:W,baseState:W,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Wn,lastRenderedState:W},next:null};var a={};return t.next={memoizedState:a,baseState:a,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Wn,lastRenderedState:a},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function hh(e){var t=mh(e);t.next===null&&(t=e.alternate.memoizedState),fr(e,t.next.queue,{},Zt())}function Eu(){return Et(Or)}function vh(){return ot().memoizedState}function gh(){return ot().memoizedState}function $w(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var a=Zt();e=Ca(a);var i=Aa(t,e,a);i!==null&&(Ht(i,t,a),rr(i,t,a)),t={cache:Js()},e.payload=t;return}t=t.return}}function e1(e,t,a){var i=Zt();a={lane:i,revertLane:0,gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Mo(e)?bh(t,a):(a=Vs(e,t,a,i),a!==null&&(Ht(a,e,i),xh(a,t,i)))}function yh(e,t,a){var i=Zt();fr(e,t,a,i)}function fr(e,t,a,i){var s={lane:i,revertLane:0,gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null};if(Mo(e))bh(t,s);else{var f=e.alternate;if(e.lanes===0&&(f===null||f.lanes===0)&&(f=t.lastRenderedReducer,f!==null))try{var g=t.lastRenderedState,C=f(g,a);if(s.hasEagerState=!0,s.eagerState=C,Yt(C,g))return po(e,t,s,0),Xe===null&&fo(),!1}catch{}if(a=Vs(e,t,s,i),a!==null)return Ht(a,e,i),xh(a,t,i),!0}return!1}function _u(e,t,a,i){if(i={lane:2,revertLane:nf(),gesture:null,action:i,hasEagerState:!1,eagerState:null,next:null},Mo(e)){if(t)throw Error(o(479))}else t=Vs(e,a,i,2),t!==null&&Ht(t,e,2)}function Mo(e){var t=e.alternate;return e===Ee||t!==null&&t===Ee}function bh(e,t){ii=Ao=!0;var a=e.pending;a===null?t.next=t:(t.next=a.next,a.next=t),e.pending=t}function xh(e,t,a){if((a&4194048)!==0){var i=t.lanes;i&=e.pendingLanes,a|=i,t.lanes=a,Cp(e,a)}}var dr={readContext:Et,use:Ro,useCallback:at,useContext:at,useEffect:at,useImperativeHandle:at,useLayoutEffect:at,useInsertionEffect:at,useMemo:at,useReducer:at,useRef:at,useState:at,useDebugValue:at,useDeferredValue:at,useTransition:at,useSyncExternalStore:at,useId:at,useHostTransitionStatus:at,useFormState:at,useActionState:at,useOptimistic:at,useMemoCache:at,useCacheRefresh:at};dr.useEffectEvent=at;var Sh={readContext:Et,use:Ro,useCallback:function(e,t){return Nt().memoizedState=[e,t===void 0?null:t],e},useContext:Et,useEffect:lh,useImperativeHandle:function(e,t,a){a=a!=null?a.concat([e]):null,jo(4194308,4,ch.bind(null,t,e),a)},useLayoutEffect:function(e,t){return jo(4194308,4,e,t)},useInsertionEffect:function(e,t){jo(4,2,e,t)},useMemo:function(e,t){var a=Nt();t=t===void 0?null:t;var i=e();if(hl){Gt(!0);try{e()}finally{Gt(!1)}}return a.memoizedState=[i,t],i},useReducer:function(e,t,a){var i=Nt();if(a!==void 0){var s=a(t);if(hl){Gt(!0);try{a(t)}finally{Gt(!1)}}}else s=t;return i.memoizedState=i.baseState=s,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:s},i.queue=e,e=e.dispatch=e1.bind(null,Ee,e),[i.memoizedState,e]},useRef:function(e){var t=Nt();return e={current:e},t.memoizedState=e},useState:function(e){e=gu(e);var t=e.queue,a=yh.bind(null,Ee,t);return t.dispatch=a,[e.memoizedState,a]},useDebugValue:xu,useDeferredValue:function(e,t){var a=Nt();return Su(a,e,t)},useTransition:function(){var e=gu(!1);return e=ph.bind(null,Ee,e.queue,!0,!1),Nt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,a){var i=Ee,s=Nt();if(Me){if(a===void 0)throw Error(o(407));a=a()}else{if(a=t(),Xe===null)throw Error(o(349));(je&127)!==0||Pm(i,t,a)}s.memoizedState=a;var f={value:a,getSnapshot:t};return s.queue=f,lh(Ym.bind(null,i,f,e),[e]),i.flags|=2048,oi(9,{destroy:void 0},Gm.bind(null,i,f,a,t),null),a},useId:function(){var e=Nt(),t=Xe.identifierPrefix;if(Me){var a=Tn,i=An;a=(i&~(1<<32-xt(i)-1)).toString(32)+a,t="_"+t+"R_"+a,a=To++,0<\/script>",f=f.removeChild(f.firstChild);break;case"select":f=typeof i.is=="string"?g.createElement("select",{is:i.is}):g.createElement("select"),i.multiple?f.multiple=!0:i.size&&(f.size=i.size);break;default:f=typeof i.is=="string"?g.createElement(s,{is:i.is}):g.createElement(s)}}f[St]=t,f[Dt]=i;e:for(g=t.child;g!==null;){if(g.tag===5||g.tag===6)f.appendChild(g.stateNode);else if(g.tag!==4&&g.tag!==27&&g.child!==null){g.child.return=g,g=g.child;continue}if(g===t)break e;for(;g.sibling===null;){if(g.return===null||g.return===t)break e;g=g.return}g.sibling.return=g.return,g=g.sibling}t.stateNode=f;e:switch(Ct(f,s,i),s){case"button":case"input":case"select":case"textarea":i=!!i.autoFocus;break e;case"img":i=!0;break e;default:i=!1}i&&$n(t)}}return $e(t),Hu(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,a),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==i&&$n(t);else{if(typeof i!="string"&&t.stateNode===null)throw Error(o(166));if(e=se.current,Jl(t)){if(e=t.stateNode,a=t.memoizedProps,i=null,s=wt,s!==null)switch(s.tag){case 27:case 5:i=s.memoizedProps}e[St]=t,e=!!(e.nodeValue===a||i!==null&&i.suppressHydrationWarning===!0||qv(e.nodeValue,a)),e||wa(t,!0)}else e=$o(e).createTextNode(i),e[St]=t,t.stateNode=e}return $e(t),null;case 31:if(a=t.memoizedState,e===null||e.memoizedState!==null){if(i=Jl(t),a!==null){if(e===null){if(!i)throw Error(o(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(o(557));e[St]=t}else cl(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;$e(t),e=!1}else a=Qs(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),e=!0;if(!e)return t.flags&256?(It(t),t):(It(t),null);if((t.flags&128)!==0)throw Error(o(558))}return $e(t),null;case 13:if(i=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(s=Jl(t),i!==null&&i.dehydrated!==null){if(e===null){if(!s)throw Error(o(318));if(s=t.memoizedState,s=s!==null?s.dehydrated:null,!s)throw Error(o(317));s[St]=t}else cl(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;$e(t),s=!1}else s=Qs(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=s),s=!0;if(!s)return t.flags&256?(It(t),t):(It(t),null)}return It(t),(t.flags&128)!==0?(t.lanes=a,t):(a=i!==null,e=e!==null&&e.memoizedState!==null,a&&(i=t.child,s=null,i.alternate!==null&&i.alternate.memoizedState!==null&&i.alternate.memoizedState.cachePool!==null&&(s=i.alternate.memoizedState.cachePool.pool),f=null,i.memoizedState!==null&&i.memoizedState.cachePool!==null&&(f=i.memoizedState.cachePool.pool),f!==s&&(i.flags|=2048)),a!==e&&a&&(t.child.flags|=8192),Ho(t,t.updateQueue),$e(t),null);case 4:return pe(),e===null&&of(t.stateNode.containerInfo),$e(t),null;case 10:return Kn(t.type),$e(t),null;case 19:if(F(rt),i=t.memoizedState,i===null)return $e(t),null;if(s=(t.flags&128)!==0,f=i.rendering,f===null)if(s)mr(i,!1);else{if(lt!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(f=Co(e),f!==null){for(t.flags|=128,mr(i,!1),e=f.updateQueue,t.updateQueue=e,Ho(t,e),t.subtreeFlags=0,e=a,a=t.child;a!==null;)ym(a,e),a=a.sibling;return te(rt,rt.current&1|2),Me&&In(t,i.treeForkCount),t.child}e=e.sibling}i.tail!==null&&Rt()>Go&&(t.flags|=128,s=!0,mr(i,!1),t.lanes=4194304)}else{if(!s)if(e=Co(f),e!==null){if(t.flags|=128,s=!0,e=e.updateQueue,t.updateQueue=e,Ho(t,e),mr(i,!0),i.tail===null&&i.tailMode==="hidden"&&!f.alternate&&!Me)return $e(t),null}else 2*Rt()-i.renderingStartTime>Go&&a!==536870912&&(t.flags|=128,s=!0,mr(i,!1),t.lanes=4194304);i.isBackwards?(f.sibling=t.child,t.child=f):(e=i.last,e!==null?e.sibling=f:t.child=f,i.last=f)}return i.tail!==null?(e=i.tail,i.rendering=e,i.tail=e.sibling,i.renderingStartTime=Rt(),e.sibling=null,a=rt.current,te(rt,s?a&1|2:a&1),Me&&In(t,i.treeForkCount),e):($e(t),null);case 22:case 23:return It(t),ou(),i=t.memoizedState!==null,e!==null?e.memoizedState!==null!==i&&(t.flags|=8192):i&&(t.flags|=8192),i?(a&536870912)!==0&&(t.flags&128)===0&&($e(t),t.subtreeFlags&6&&(t.flags|=8192)):$e(t),a=t.updateQueue,a!==null&&Ho(t,a.retryQueue),a=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(a=e.memoizedState.cachePool.pool),i=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(i=t.memoizedState.cachePool.pool),i!==a&&(t.flags|=2048),e!==null&&F(fl),null;case 24:return a=null,e!==null&&(a=e.memoizedState.cache),t.memoizedState.cache!==a&&(t.flags|=2048),Kn(ct),$e(t),null;case 25:return null;case 30:return null}throw Error(o(156,t.tag))}function i1(e,t){switch(Xs(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Kn(ct),pe(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Ce(t),null;case 31:if(t.memoizedState!==null){if(It(t),t.alternate===null)throw Error(o(340));cl()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(It(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(o(340));cl()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return F(rt),null;case 4:return pe(),null;case 10:return Kn(t.type),null;case 22:case 23:return It(t),ou(),e!==null&&F(fl),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Kn(ct),null;case 25:return null;default:return null}}function Fh(e,t){switch(Xs(t),t.tag){case 3:Kn(ct),pe();break;case 26:case 27:case 5:Ce(t);break;case 4:pe();break;case 31:t.memoizedState!==null&&It(t);break;case 13:It(t);break;case 19:F(rt);break;case 10:Kn(t.type);break;case 22:case 23:It(t),ou(),e!==null&&F(fl);break;case 24:Kn(ct)}}function hr(e,t){try{var a=t.updateQueue,i=a!==null?a.lastEffect:null;if(i!==null){var s=i.next;a=s;do{if((a.tag&e)===e){i=void 0;var f=a.create,g=a.inst;i=f(),g.destroy=i}a=a.next}while(a!==s)}}catch(C){Pe(t,t.return,C)}}function Ra(e,t,a){try{var i=t.updateQueue,s=i!==null?i.lastEffect:null;if(s!==null){var f=s.next;i=f;do{if((i.tag&e)===e){var g=i.inst,C=g.destroy;if(C!==void 0){g.destroy=void 0,s=t;var R=a,q=C;try{q()}catch(X){Pe(s,R,X)}}}i=i.next}while(i!==f)}}catch(X){Pe(t,t.return,X)}}function Xh(e){var t=e.updateQueue;if(t!==null){var a=e.stateNode;try{Lm(t,a)}catch(i){Pe(e,e.return,i)}}}function Ih(e,t,a){a.props=vl(e.type,e.memoizedProps),a.state=e.memoizedState;try{a.componentWillUnmount()}catch(i){Pe(e,t,i)}}function vr(e,t){try{var a=e.ref;if(a!==null){switch(e.tag){case 26:case 27:case 5:var i=e.stateNode;break;case 30:i=e.stateNode;break;default:i=e.stateNode}typeof a=="function"?e.refCleanup=a(i):a.current=i}}catch(s){Pe(e,t,s)}}function On(e,t){var a=e.ref,i=e.refCleanup;if(a!==null)if(typeof i=="function")try{i()}catch(s){Pe(e,t,s)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof a=="function")try{a(null)}catch(s){Pe(e,t,s)}else a.current=null}function Qh(e){var t=e.type,a=e.memoizedProps,i=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":a.autoFocus&&i.focus();break e;case"img":a.src?i.src=a.src:a.srcSet&&(i.srcset=a.srcSet)}}catch(s){Pe(e,e.return,s)}}function Bu(e,t,a){try{var i=e.stateNode;T1(i,e.type,a,t),i[Dt]=t}catch(s){Pe(e,e.return,s)}}function Kh(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&La(e.type)||e.tag===4}function qu(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Kh(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&La(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Vu(e,t,a){var i=e.tag;if(i===5||i===6)e=e.stateNode,t?(a.nodeType===9?a.body:a.nodeName==="HTML"?a.ownerDocument.body:a).insertBefore(e,t):(t=a.nodeType===9?a.body:a.nodeName==="HTML"?a.ownerDocument.body:a,t.appendChild(e),a=a._reactRootContainer,a!=null||t.onclick!==null||(t.onclick=Yn));else if(i!==4&&(i===27&&La(e.type)&&(a=e.stateNode,t=null),e=e.child,e!==null))for(Vu(e,t,a),e=e.sibling;e!==null;)Vu(e,t,a),e=e.sibling}function Bo(e,t,a){var i=e.tag;if(i===5||i===6)e=e.stateNode,t?a.insertBefore(e,t):a.appendChild(e);else if(i!==4&&(i===27&&La(e.type)&&(a=e.stateNode),e=e.child,e!==null))for(Bo(e,t,a),e=e.sibling;e!==null;)Bo(e,t,a),e=e.sibling}function Zh(e){var t=e.stateNode,a=e.memoizedProps;try{for(var i=e.type,s=t.attributes;s.length;)t.removeAttributeNode(s[0]);Ct(t,i,a),t[St]=e,t[Dt]=a}catch(f){Pe(e,e.return,f)}}var ea=!1,ft=!1,Pu=!1,Wh=typeof WeakSet=="function"?WeakSet:Set,gt=null;function r1(e,t){if(e=e.containerInfo,uf=rc,e=sm(e),ks(e)){if("selectionStart"in e)var a={start:e.selectionStart,end:e.selectionEnd};else e:{a=(a=e.ownerDocument)&&a.defaultView||window;var i=a.getSelection&&a.getSelection();if(i&&i.rangeCount!==0){a=i.anchorNode;var s=i.anchorOffset,f=i.focusNode;i=i.focusOffset;try{a.nodeType,f.nodeType}catch{a=null;break e}var g=0,C=-1,R=-1,q=0,X=0,Z=e,V=null;t:for(;;){for(var G;Z!==a||s!==0&&Z.nodeType!==3||(C=g+s),Z!==f||i!==0&&Z.nodeType!==3||(R=g+i),Z.nodeType===3&&(g+=Z.nodeValue.length),(G=Z.firstChild)!==null;)V=Z,Z=G;for(;;){if(Z===e)break t;if(V===a&&++q===s&&(C=g),V===f&&++X===i&&(R=g),(G=Z.nextSibling)!==null)break;Z=V,V=Z.parentNode}Z=G}a=C===-1||R===-1?null:{start:C,end:R}}else a=null}a=a||{start:0,end:0}}else a=null;for(ff={focusedElem:e,selectionRange:a},rc=!1,gt=t;gt!==null;)if(t=gt,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,gt=e;else for(;gt!==null;){switch(t=gt,f=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(a=0;a title"))),Ct(f,i,a),f[St]=e,vt(f),i=f;break e;case"link":var g=ag("link","href",s).get(i+(a.href||""));if(g){for(var C=0;CFe&&(g=Fe,Fe=be,be=g);var L=om(C,be),D=om(C,Fe);if(L&&D&&(G.rangeCount!==1||G.anchorNode!==L.node||G.anchorOffset!==L.offset||G.focusNode!==D.node||G.focusOffset!==D.offset)){var B=Z.createRange();B.setStart(L.node,L.offset),G.removeAllRanges(),be>Fe?(G.addRange(B),G.extend(D.node,D.offset)):(B.setEnd(D.node,D.offset),G.addRange(B))}}}}for(Z=[],G=C;G=G.parentNode;)G.nodeType===1&&Z.push({element:G,left:G.scrollLeft,top:G.scrollTop});for(typeof C.focus=="function"&&C.focus(),C=0;Ca?32:a,M.T=null,a=Ku,Ku=null;var f=Ma,g=ia;if(pt=0,di=Ma=null,ia=0,(He&6)!==0)throw Error(o(331));var C=He;if(He|=4,cv(f.current),iv(f,f.current,g,a),He=C,wr(0,!1),bt&&typeof bt.onPostCommitFiberRoot=="function")try{bt.onPostCommitFiberRoot(Pn,f)}catch{}return!0}finally{Q.p=s,M.T=i,Av(e,t)}}function Ov(e,t,a){t=an(a,t),t=Ou(e.stateNode,t,2),e=Aa(e,t,2),e!==null&&(Pi(e,2),Rn(e))}function Pe(e,t,a){if(e.tag===3)Ov(e,e,a);else for(;t!==null;){if(t.tag===3){Ov(t,e,a);break}else if(t.tag===1){var i=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof i.componentDidCatch=="function"&&(Da===null||!Da.has(i))){e=an(a,e),a=Rh(2),i=Aa(t,a,2),i!==null&&(Nh(a,i,t,e),Pi(i,2),Rn(i));break}}t=t.return}}function $u(e,t,a){var i=e.pingCache;if(i===null){i=e.pingCache=new s1;var s=new Set;i.set(t,s)}else s=i.get(t),s===void 0&&(s=new Set,i.set(t,s));s.has(a)||(Fu=!0,s.add(a),e=m1.bind(null,e,t,a),t.then(e,e))}function m1(e,t,a){var i=e.pingCache;i!==null&&i.delete(t),e.pingedLanes|=e.suspendedLanes&a,e.warmLanes&=~a,Xe===e&&(je&a)===a&&(lt===4||lt===3&&(je&62914560)===je&&300>Rt()-Po?(He&2)===0&&pi(e,0):Xu|=a,fi===je&&(fi=0)),Rn(e)}function Rv(e,t){t===0&&(t=Ep()),e=rl(e,t),e!==null&&(Pi(e,t),Rn(e))}function h1(e){var t=e.memoizedState,a=0;t!==null&&(a=t.retryLane),Rv(e,a)}function v1(e,t){var a=0;switch(e.tag){case 31:case 13:var i=e.stateNode,s=e.memoizedState;s!==null&&(a=s.retryLane);break;case 19:i=e.stateNode;break;case 22:i=e.stateNode._retryCache;break;default:throw Error(o(314))}i!==null&&i.delete(t),Rv(e,a)}function g1(e,t){return va(e,t)}var Ko=null,hi=null,ef=!1,Zo=!1,tf=!1,ka=0;function Rn(e){e!==hi&&e.next===null&&(hi===null?Ko=hi=e:hi=hi.next=e),Zo=!0,ef||(ef=!0,b1())}function wr(e,t){if(!tf&&Zo){tf=!0;do for(var a=!1,i=Ko;i!==null;){if(e!==0){var s=i.pendingLanes;if(s===0)var f=0;else{var g=i.suspendedLanes,C=i.pingedLanes;f=(1<<31-xt(42|e)+1)-1,f&=s&~(g&~C),f=f&201326741?f&201326741|1:f?f|2:0}f!==0&&(a=!0,Mv(i,f))}else f=je,f=$r(i,i===Xe?f:0,i.cancelPendingCommit!==null||i.timeoutHandle!==-1),(f&3)===0||Vi(i,f)||(a=!0,Mv(i,f));i=i.next}while(a);tf=!1}}function y1(){Nv()}function Nv(){Zo=ef=!1;var e=0;ka!==0&&R1()&&(e=ka);for(var t=Rt(),a=null,i=Ko;i!==null;){var s=i.next,f=jv(i,t);f===0?(i.next=null,a===null?Ko=s:a.next=s,s===null&&(hi=a)):(a=i,(e!==0||(f&3)!==0)&&(Zo=!0)),i=s}pt!==0&&pt!==5||wr(e),ka!==0&&(ka=0)}function jv(e,t){for(var a=e.suspendedLanes,i=e.pingedLanes,s=e.expirationTimes,f=e.pendingLanes&-62914561;0C)break;var X=R.transferSize,Z=R.initiatorType;X&&Vv(Z)&&(R=R.responseEnd,g+=X*(R"u"?null:document;function $v(e,t,a){var i=vi;if(i&&typeof t=="string"&&t){var s=tn(t);s='link[rel="'+e+'"][href="'+s+'"]',typeof a=="string"&&(s+='[crossorigin="'+a+'"]'),Jv.has(s)||(Jv.add(s),e={rel:e,crossOrigin:a,href:t},i.querySelector(s)===null&&(t=i.createElement("link"),Ct(t,"link",e),vt(t),i.head.appendChild(t)))}}function H1(e){ra.D(e),$v("dns-prefetch",e,null)}function B1(e,t){ra.C(e,t),$v("preconnect",e,t)}function q1(e,t,a){ra.L(e,t,a);var i=vi;if(i&&e&&t){var s='link[rel="preload"][as="'+tn(t)+'"]';t==="image"&&a&&a.imageSrcSet?(s+='[imagesrcset="'+tn(a.imageSrcSet)+'"]',typeof a.imageSizes=="string"&&(s+='[imagesizes="'+tn(a.imageSizes)+'"]')):s+='[href="'+tn(e)+'"]';var f=s;switch(t){case"style":f=gi(e);break;case"script":f=yi(e)}un.has(f)||(e=y({rel:"preload",href:t==="image"&&a&&a.imageSrcSet?void 0:e,as:t},a),un.set(f,e),i.querySelector(s)!==null||t==="style"&&i.querySelector(Ar(f))||t==="script"&&i.querySelector(Tr(f))||(t=i.createElement("link"),Ct(t,"link",e),vt(t),i.head.appendChild(t)))}}function V1(e,t){ra.m(e,t);var a=vi;if(a&&e){var i=t&&typeof t.as=="string"?t.as:"script",s='link[rel="modulepreload"][as="'+tn(i)+'"][href="'+tn(e)+'"]',f=s;switch(i){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":f=yi(e)}if(!un.has(f)&&(e=y({rel:"modulepreload",href:e},t),un.set(f,e),a.querySelector(s)===null)){switch(i){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(a.querySelector(Tr(f)))return}i=a.createElement("link"),Ct(i,"link",e),vt(i),a.head.appendChild(i)}}}function P1(e,t,a){ra.S(e,t,a);var i=vi;if(i&&e){var s=Bl(i).hoistableStyles,f=gi(e);t=t||"default";var g=s.get(f);if(!g){var C={loading:0,preload:null};if(g=i.querySelector(Ar(f)))C.loading=5;else{e=y({rel:"stylesheet",href:e,"data-precedence":t},a),(a=un.get(f))&&yf(e,a);var R=g=i.createElement("link");vt(R),Ct(R,"link",e),R._p=new Promise(function(q,X){R.onload=q,R.onerror=X}),R.addEventListener("load",function(){C.loading|=1}),R.addEventListener("error",function(){C.loading|=2}),C.loading|=4,tc(g,t,i)}g={type:"stylesheet",instance:g,count:1,state:C},s.set(f,g)}}}function G1(e,t){ra.X(e,t);var a=vi;if(a&&e){var i=Bl(a).hoistableScripts,s=yi(e),f=i.get(s);f||(f=a.querySelector(Tr(s)),f||(e=y({src:e,async:!0},t),(t=un.get(s))&&bf(e,t),f=a.createElement("script"),vt(f),Ct(f,"link",e),a.head.appendChild(f)),f={type:"script",instance:f,count:1,state:null},i.set(s,f))}}function Y1(e,t){ra.M(e,t);var a=vi;if(a&&e){var i=Bl(a).hoistableScripts,s=yi(e),f=i.get(s);f||(f=a.querySelector(Tr(s)),f||(e=y({src:e,async:!0,type:"module"},t),(t=un.get(s))&&bf(e,t),f=a.createElement("script"),vt(f),Ct(f,"link",e),a.head.appendChild(f)),f={type:"script",instance:f,count:1,state:null},i.set(s,f))}}function eg(e,t,a,i){var s=(s=se.current)?ec(s):null;if(!s)throw Error(o(446));switch(e){case"meta":case"title":return null;case"style":return typeof a.precedence=="string"&&typeof a.href=="string"?(t=gi(a.href),a=Bl(s).hoistableStyles,i=a.get(t),i||(i={type:"style",instance:null,count:0,state:null},a.set(t,i)),i):{type:"void",instance:null,count:0,state:null};case"link":if(a.rel==="stylesheet"&&typeof a.href=="string"&&typeof a.precedence=="string"){e=gi(a.href);var f=Bl(s).hoistableStyles,g=f.get(e);if(g||(s=s.ownerDocument||s,g={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},f.set(e,g),(f=s.querySelector(Ar(e)))&&!f._p&&(g.instance=f,g.state.loading=5),un.has(e)||(a={rel:"preload",as:"style",href:a.href,crossOrigin:a.crossOrigin,integrity:a.integrity,media:a.media,hrefLang:a.hrefLang,referrerPolicy:a.referrerPolicy},un.set(e,a),f||F1(s,e,a,g.state))),t&&i===null)throw Error(o(528,""));return g}if(t&&i!==null)throw Error(o(529,""));return null;case"script":return t=a.async,a=a.src,typeof a=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=yi(a),a=Bl(s).hoistableScripts,i=a.get(t),i||(i={type:"script",instance:null,count:0,state:null},a.set(t,i)),i):{type:"void",instance:null,count:0,state:null};default:throw Error(o(444,e))}}function gi(e){return'href="'+tn(e)+'"'}function Ar(e){return'link[rel="stylesheet"]['+e+"]"}function tg(e){return y({},e,{"data-precedence":e.precedence,precedence:null})}function F1(e,t,a,i){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?i.loading=1:(t=e.createElement("link"),i.preload=t,t.addEventListener("load",function(){return i.loading|=1}),t.addEventListener("error",function(){return i.loading|=2}),Ct(t,"link",a),vt(t),e.head.appendChild(t))}function yi(e){return'[src="'+tn(e)+'"]'}function Tr(e){return"script[async]"+e}function ng(e,t,a){if(t.count++,t.instance===null)switch(t.type){case"style":var i=e.querySelector('style[data-href~="'+tn(a.href)+'"]');if(i)return t.instance=i,vt(i),i;var s=y({},a,{"data-href":a.href,"data-precedence":a.precedence,href:null,precedence:null});return i=(e.ownerDocument||e).createElement("style"),vt(i),Ct(i,"style",s),tc(i,a.precedence,e),t.instance=i;case"stylesheet":s=gi(a.href);var f=e.querySelector(Ar(s));if(f)return t.state.loading|=4,t.instance=f,vt(f),f;i=tg(a),(s=un.get(s))&&yf(i,s),f=(e.ownerDocument||e).createElement("link"),vt(f);var g=f;return g._p=new Promise(function(C,R){g.onload=C,g.onerror=R}),Ct(f,"link",i),t.state.loading|=4,tc(f,a.precedence,e),t.instance=f;case"script":return f=yi(a.src),(s=e.querySelector(Tr(f)))?(t.instance=s,vt(s),s):(i=a,(s=un.get(f))&&(i=y({},a),bf(i,s)),e=e.ownerDocument||e,s=e.createElement("script"),vt(s),Ct(s,"link",i),e.head.appendChild(s),t.instance=s);case"void":return null;default:throw Error(o(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(i=t.instance,t.state.loading|=4,tc(i,a.precedence,e));return t.instance}function tc(e,t,a){for(var i=a.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),s=i.length?i[i.length-1]:null,f=s,g=0;g title"):null)}function X1(e,t,a){if(a===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;return t.rel==="stylesheet"?(e=t.disabled,typeof t.precedence=="string"&&e==null):!0;case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function ig(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function I1(e,t,a,i){if(a.type==="stylesheet"&&(typeof i.media!="string"||matchMedia(i.media).matches!==!1)&&(a.state.loading&4)===0){if(a.instance===null){var s=gi(i.href),f=t.querySelector(Ar(s));if(f){t=f._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=ac.bind(e),t.then(e,e)),a.state.loading|=4,a.instance=f,vt(f);return}f=t.ownerDocument||t,i=tg(i),(s=un.get(s))&&yf(i,s),f=f.createElement("link"),vt(f);var g=f;g._p=new Promise(function(C,R){g.onload=C,g.onerror=R}),Ct(f,"link",i),a.instance=f}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(a,t),(t=a.state.preload)&&(a.state.loading&3)===0&&(e.count++,a=ac.bind(e),t.addEventListener("load",a),t.addEventListener("error",a))}}var xf=0;function Q1(e,t){return e.stylesheets&&e.count===0&&ic(e,e.stylesheets),0xf?50:800)+t);return e.unsuspend=a,function(){e.unsuspend=null,clearTimeout(i),clearTimeout(s)}}:null}function ac(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)ic(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var lc=null;function ic(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,lc=new Map,t.forEach(K1,e),lc=null,ac.call(e))}function K1(e,t){if(!(t.state.loading&4)){var a=lc.get(e);if(a)var i=a.get(null);else{a=new Map,lc.set(e,a);for(var s=e.querySelectorAll("link[data-precedence],style[data-precedence]"),f=0;f"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(l){console.error(l)}}return n(),Rf.exports=fE(),Rf.exports}var pE=dE();const fb=(...n)=>n.filter((l,r,o)=>!!l&&l.trim()!==""&&o.indexOf(l)===r).join(" ").trim();const mE=n=>n.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();const hE=n=>n.replace(/^([A-Z])|[\s-_]+(\w)/g,(l,r,o)=>o?o.toUpperCase():r.toLowerCase());const Rg=n=>{const l=hE(n);return l.charAt(0).toUpperCase()+l.slice(1)};var Mf={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};const vE=n=>{for(const l in n)if(l.startsWith("aria-")||l==="role"||l==="title")return!0;return!1},gE=x.createContext({}),yE=()=>x.useContext(gE),bE=x.forwardRef(({color:n,size:l,strokeWidth:r,absoluteStrokeWidth:o,className:c="",children:u,iconNode:d,...p},h)=>{const{size:m=24,strokeWidth:v=2,absoluteStrokeWidth:y=!1,color:w="currentColor",className:_=""}=yE()??{},E=o??y?Number(r??v)*24/Number(l??m):r??v;return x.createElement("svg",{ref:h,...Mf,width:l??m??Mf.width,height:l??m??Mf.height,stroke:n??w,strokeWidth:E,className:fb("lucide",_,c),...!u&&!vE(p)&&{"aria-hidden":"true"},...p},[...d.map(([S,A])=>x.createElement(S,A)),...Array.isArray(u)?u:[u]])});const Ot=(n,l)=>{const r=x.forwardRef(({className:o,...c},u)=>x.createElement(bE,{ref:u,iconNode:l,className:fb(`lucide-${mE(Rg(n))}`,`lucide-${n}`,o),...c}));return r.displayName=Rg(n),r};const xE=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],SE=Ot("check",xE);const wE=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],Rd=Ot("chevron-down",wE);const EE=[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]],_E=Ot("chevron-up",EE);const CE=[["path",{d:"M16 14v2.2l1.6 1",key:"fo4ql5"}],["path",{d:"M7 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2",key:"1urifu"}],["circle",{cx:"16",cy:"16",r:"6",key:"qoo3c4"}]],AE=Ot("folder-clock",CE);const TE=[["path",{d:"M16 5h6",key:"1vod17"}],["path",{d:"M19 2v6",key:"4bpg5p"}],["path",{d:"M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5",key:"1ue2ih"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}]],OE=Ot("image-plus",TE);const RE=[["path",{d:"M10.3 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10l-3.1-3.1a2 2 0 0 0-2.814.014L6 21",key:"9csbqa"}],["path",{d:"m14 19.5 3-3 3 3",key:"9vmjn0"}],["path",{d:"M17 22v-5.5",key:"1aa6fl"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}]],NE=Ot("image-up",RE);const jE=[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m8 11 4 4 4-4",key:"1dohi6"}],["path",{d:"M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4",key:"1ywtjm"}]],DE=Ot("import",jE);const ME=[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",key:"zw3jo"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",key:"1wduqc"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",key:"kqbvx6"}]],Ng=Ot("layers",ME);const zE=[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]],kE=Ot("loader-circle",zE);const LE=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m10 15-3-3 3-3",key:"1pgupc"}]],UE=Ot("panel-right-open",LE);const HE=[["path",{d:"M10 5H3",key:"1qgfaw"}],["path",{d:"M12 19H3",key:"yhmn1j"}],["path",{d:"M14 3v4",key:"1sua03"}],["path",{d:"M16 17v4",key:"1q0r14"}],["path",{d:"M21 12h-9",key:"1o4lsq"}],["path",{d:"M21 19h-5",key:"1rlt1p"}],["path",{d:"M21 5h-7",key:"1oszz2"}],["path",{d:"M8 10v4",key:"tgpxqk"}],["path",{d:"M8 12H3",key:"a7s4jb"}]],jg=Ot("sliders-horizontal",HE);const BE=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],ad=Ot("sparkles",BE);const qE=[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m17 8-5-5-5 5",key:"7q97r8"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}]],VE=Ot("upload",qE);const PE=[["path",{d:"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72",key:"ul74o6"}],["path",{d:"m14 7 3 3",key:"1r5n42"}],["path",{d:"M5 6v4",key:"ilb8ba"}],["path",{d:"M19 14v4",key:"blhpug"}],["path",{d:"M10 2v2",key:"7u0qdc"}],["path",{d:"M7 8H3",key:"zfb6yr"}],["path",{d:"M21 16h-4",key:"1cnmox"}],["path",{d:"M11 3H9",key:"1obp7u"}]],GE=Ot("wand-sparkles",PE);const YE=[["rect",{width:"8",height:"8",x:"3",y:"3",rx:"2",key:"by2w9f"}],["path",{d:"M7 11v4a2 2 0 0 0 2 2h4",key:"xkn7yn"}],["rect",{width:"8",height:"8",x:"13",y:"13",rx:"2",key:"1cgmvn"}]],FE=Ot("workflow",YE);const XE=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],db=Ot("x",XE);function pb(n,l){return function(){return n.apply(l,arguments)}}const{toString:IE}=Object.prototype,{getPrototypeOf:Nd}=Object,{iterator:Xc,toStringTag:mb}=Symbol,Ic=(n=>l=>{const r=IE.call(l);return n[r]||(n[r]=r.slice(8,-1).toLowerCase())})(Object.create(null)),Sn=n=>(n=n.toLowerCase(),l=>Ic(l)===n),Qc=n=>l=>typeof l===n,{isArray:ji}=Array,Ai=Qc("undefined");function Yr(n){return n!==null&&!Ai(n)&&n.constructor!==null&&!Ai(n.constructor)&&qt(n.constructor.isBuffer)&&n.constructor.isBuffer(n)}const hb=Sn("ArrayBuffer");function QE(n){let l;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?l=ArrayBuffer.isView(n):l=n&&n.buffer&&hb(n.buffer),l}const KE=Qc("string"),qt=Qc("function"),vb=Qc("number"),Fr=n=>n!==null&&typeof n=="object",ZE=n=>n===!0||n===!1,Cc=n=>{if(Ic(n)!=="object")return!1;const l=Nd(n);return(l===null||l===Object.prototype||Object.getPrototypeOf(l)===null)&&!(mb in n)&&!(Xc in n)},WE=n=>{if(!Fr(n)||Yr(n))return!1;try{return Object.keys(n).length===0&&Object.getPrototypeOf(n)===Object.prototype}catch{return!1}},JE=Sn("Date"),$E=Sn("File"),e_=Sn("Blob"),t_=Sn("FileList"),n_=n=>Fr(n)&&qt(n.pipe),a_=n=>{let l;return n&&(typeof FormData=="function"&&n instanceof FormData||qt(n.append)&&((l=Ic(n))==="formdata"||l==="object"&&qt(n.toString)&&n.toString()==="[object FormData]"))},l_=Sn("URLSearchParams"),[i_,r_,o_,c_]=["ReadableStream","Request","Response","Headers"].map(Sn),s_=n=>n.trim?n.trim():n.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function Xr(n,l,{allOwnKeys:r=!1}={}){if(n===null||typeof n>"u")return;let o,c;if(typeof n!="object"&&(n=[n]),ji(n))for(o=0,c=n.length;o0;)if(c=r[o],l===c.toLowerCase())return c;return null}const _l=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,yb=n=>!Ai(n)&&n!==_l;function ld(){const{caseless:n,skipUndefined:l}=yb(this)&&this||{},r={},o=(c,u)=>{if(u==="__proto__"||u==="constructor"||u==="prototype")return;const d=n&&gb(r,u)||u;Cc(r[d])&&Cc(c)?r[d]=ld(r[d],c):Cc(c)?r[d]=ld({},c):ji(c)?r[d]=c.slice():(!l||!Ai(c))&&(r[d]=c)};for(let c=0,u=arguments.length;c(Xr(l,(c,u)=>{r&&qt(c)?Object.defineProperty(n,u,{value:pb(c,r),writable:!0,enumerable:!0,configurable:!0}):Object.defineProperty(n,u,{value:c,writable:!0,enumerable:!0,configurable:!0})},{allOwnKeys:o}),n),f_=n=>(n.charCodeAt(0)===65279&&(n=n.slice(1)),n),d_=(n,l,r,o)=>{n.prototype=Object.create(l.prototype,o),Object.defineProperty(n.prototype,"constructor",{value:n,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(n,"super",{value:l.prototype}),r&&Object.assign(n.prototype,r)},p_=(n,l,r,o)=>{let c,u,d;const p={};if(l=l||{},n==null)return l;do{for(c=Object.getOwnPropertyNames(n),u=c.length;u-- >0;)d=c[u],(!o||o(d,n,l))&&!p[d]&&(l[d]=n[d],p[d]=!0);n=r!==!1&&Nd(n)}while(n&&(!r||r(n,l))&&n!==Object.prototype);return l},m_=(n,l,r)=>{n=String(n),(r===void 0||r>n.length)&&(r=n.length),r-=l.length;const o=n.indexOf(l,r);return o!==-1&&o===r},h_=n=>{if(!n)return null;if(ji(n))return n;let l=n.length;if(!vb(l))return null;const r=new Array(l);for(;l-- >0;)r[l]=n[l];return r},v_=(n=>l=>n&&l instanceof n)(typeof Uint8Array<"u"&&Nd(Uint8Array)),g_=(n,l)=>{const o=(n&&n[Xc]).call(n);let c;for(;(c=o.next())&&!c.done;){const u=c.value;l.call(n,u[0],u[1])}},y_=(n,l)=>{let r;const o=[];for(;(r=n.exec(l))!==null;)o.push(r);return o},b_=Sn("HTMLFormElement"),x_=n=>n.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(r,o,c){return o.toUpperCase()+c}),Dg=(({hasOwnProperty:n})=>(l,r)=>n.call(l,r))(Object.prototype),S_=Sn("RegExp"),bb=(n,l)=>{const r=Object.getOwnPropertyDescriptors(n),o={};Xr(r,(c,u)=>{let d;(d=l(c,u,n))!==!1&&(o[u]=d||c)}),Object.defineProperties(n,o)},w_=n=>{bb(n,(l,r)=>{if(qt(n)&&["arguments","caller","callee"].indexOf(r)!==-1)return!1;const o=n[r];if(qt(o)){if(l.enumerable=!1,"writable"in l){l.writable=!1;return}l.set||(l.set=()=>{throw Error("Can not rewrite read-only method '"+r+"'")})}})},E_=(n,l)=>{const r={},o=c=>{c.forEach(u=>{r[u]=!0})};return ji(n)?o(n):o(String(n).split(l)),r},__=()=>{},C_=(n,l)=>n!=null&&Number.isFinite(n=+n)?n:l;function A_(n){return!!(n&&qt(n.append)&&n[mb]==="FormData"&&n[Xc])}const T_=n=>{const l=new Array(10),r=(o,c)=>{if(Fr(o)){if(l.indexOf(o)>=0)return;if(Yr(o))return o;if(!("toJSON"in o)){l[c]=o;const u=ji(o)?[]:{};return Xr(o,(d,p)=>{const h=r(d,c+1);!Ai(h)&&(u[p]=h)}),l[c]=void 0,u}}return o};return r(n,0)},O_=Sn("AsyncFunction"),R_=n=>n&&(Fr(n)||qt(n))&&qt(n.then)&&qt(n.catch),xb=((n,l)=>n?setImmediate:l?((r,o)=>(_l.addEventListener("message",({source:c,data:u})=>{c===_l&&u===r&&o.length&&o.shift()()},!1),c=>{o.push(c),_l.postMessage(r,"*")}))(`axios@${Math.random()}`,[]):r=>setTimeout(r))(typeof setImmediate=="function",qt(_l.postMessage)),N_=typeof queueMicrotask<"u"?queueMicrotask.bind(_l):typeof process<"u"&&process.nextTick||xb,j_=n=>n!=null&&qt(n[Xc]),P={isArray:ji,isArrayBuffer:hb,isBuffer:Yr,isFormData:a_,isArrayBufferView:QE,isString:KE,isNumber:vb,isBoolean:ZE,isObject:Fr,isPlainObject:Cc,isEmptyObject:WE,isReadableStream:i_,isRequest:r_,isResponse:o_,isHeaders:c_,isUndefined:Ai,isDate:JE,isFile:$E,isBlob:e_,isRegExp:S_,isFunction:qt,isStream:n_,isURLSearchParams:l_,isTypedArray:v_,isFileList:t_,forEach:Xr,merge:ld,extend:u_,trim:s_,stripBOM:f_,inherits:d_,toFlatObject:p_,kindOf:Ic,kindOfTest:Sn,endsWith:m_,toArray:h_,forEachEntry:g_,matchAll:y_,isHTMLForm:b_,hasOwnProperty:Dg,hasOwnProp:Dg,reduceDescriptors:bb,freezeMethods:w_,toObjectSet:E_,toCamelCase:x_,noop:__,toFiniteNumber:C_,findKey:gb,global:_l,isContextDefined:yb,isSpecCompliantForm:A_,toJSONObject:T_,isAsyncFn:O_,isThenable:R_,setImmediate:xb,asap:N_,isIterable:j_};let xe=class Sb extends Error{static from(l,r,o,c,u,d){const p=new Sb(l.message,r||l.code,o,c,u);return p.cause=l,p.name=l.name,d&&Object.assign(p,d),p}constructor(l,r,o,c,u){super(l),this.name="AxiosError",this.isAxiosError=!0,r&&(this.code=r),o&&(this.config=o),c&&(this.request=c),u&&(this.response=u,this.status=u.status)}toJSON(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:P.toJSONObject(this.config),code:this.code,status:this.status}}};xe.ERR_BAD_OPTION_VALUE="ERR_BAD_OPTION_VALUE";xe.ERR_BAD_OPTION="ERR_BAD_OPTION";xe.ECONNABORTED="ECONNABORTED";xe.ETIMEDOUT="ETIMEDOUT";xe.ERR_NETWORK="ERR_NETWORK";xe.ERR_FR_TOO_MANY_REDIRECTS="ERR_FR_TOO_MANY_REDIRECTS";xe.ERR_DEPRECATED="ERR_DEPRECATED";xe.ERR_BAD_RESPONSE="ERR_BAD_RESPONSE";xe.ERR_BAD_REQUEST="ERR_BAD_REQUEST";xe.ERR_CANCELED="ERR_CANCELED";xe.ERR_NOT_SUPPORT="ERR_NOT_SUPPORT";xe.ERR_INVALID_URL="ERR_INVALID_URL";const D_=null;function id(n){return P.isPlainObject(n)||P.isArray(n)}function wb(n){return P.endsWith(n,"[]")?n.slice(0,-2):n}function Mg(n,l,r){return n?n.concat(l).map(function(c,u){return c=wb(c),!r&&u?"["+c+"]":c}).join(r?".":""):l}function M_(n){return P.isArray(n)&&!n.some(id)}const z_=P.toFlatObject(P,{},null,function(l){return/^is[A-Z]/.test(l)});function Kc(n,l,r){if(!P.isObject(n))throw new TypeError("target must be an object");l=l||new FormData,r=P.toFlatObject(r,{metaTokens:!0,dots:!1,indexes:!1},!1,function(S,A){return!P.isUndefined(A[S])});const o=r.metaTokens,c=r.visitor||v,u=r.dots,d=r.indexes,h=(r.Blob||typeof Blob<"u"&&Blob)&&P.isSpecCompliantForm(l);if(!P.isFunction(c))throw new TypeError("visitor must be a function");function m(E){if(E===null)return"";if(P.isDate(E))return E.toISOString();if(P.isBoolean(E))return E.toString();if(!h&&P.isBlob(E))throw new xe("Blob is not supported. Use a Buffer instead.");return P.isArrayBuffer(E)||P.isTypedArray(E)?h&&typeof Blob=="function"?new Blob([E]):Buffer.from(E):E}function v(E,S,A){let T=E;if(E&&!A&&typeof E=="object"){if(P.endsWith(S,"{}"))S=o?S:S.slice(0,-2),E=JSON.stringify(E);else if(P.isArray(E)&&M_(E)||(P.isFileList(E)||P.endsWith(S,"[]"))&&(T=P.toArray(E)))return S=wb(S),T.forEach(function(j,z){!(P.isUndefined(j)||j===null)&&l.append(d===!0?Mg([S],z,u):d===null?S:S+"[]",m(j))}),!1}return id(E)?!0:(l.append(Mg(A,S,u),m(E)),!1)}const y=[],w=Object.assign(z_,{defaultVisitor:v,convertValue:m,isVisitable:id});function _(E,S){if(!P.isUndefined(E)){if(y.indexOf(E)!==-1)throw Error("Circular reference detected in "+S.join("."));y.push(E),P.forEach(E,function(T,O){(!(P.isUndefined(T)||T===null)&&c.call(l,T,P.isString(O)?O.trim():O,S,w))===!0&&_(T,S?S.concat(O):[O])}),y.pop()}}if(!P.isObject(n))throw new TypeError("data must be an object");return _(n),l}function zg(n){const l={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(n).replace(/[!'()~]|%20|%00/g,function(o){return l[o]})}function jd(n,l){this._pairs=[],n&&Kc(n,this,l)}const Eb=jd.prototype;Eb.append=function(l,r){this._pairs.push([l,r])};Eb.toString=function(l){const r=l?function(o){return l.call(this,o,zg)}:zg;return this._pairs.map(function(c){return r(c[0])+"="+r(c[1])},"").join("&")};function k_(n){return encodeURIComponent(n).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}function _b(n,l,r){if(!l)return n;const o=r&&r.encode||k_,c=P.isFunction(r)?{serialize:r}:r,u=c&&c.serialize;let d;if(u?d=u(l,c):d=P.isURLSearchParams(l)?l.toString():new jd(l,c).toString(o),d){const p=n.indexOf("#");p!==-1&&(n=n.slice(0,p)),n+=(n.indexOf("?")===-1?"?":"&")+d}return n}class kg{constructor(){this.handlers=[]}use(l,r,o){return this.handlers.push({fulfilled:l,rejected:r,synchronous:o?o.synchronous:!1,runWhen:o?o.runWhen:null}),this.handlers.length-1}eject(l){this.handlers[l]&&(this.handlers[l]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(l){P.forEach(this.handlers,function(o){o!==null&&l(o)})}}const Dd={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1,legacyInterceptorReqResOrdering:!0},L_=typeof URLSearchParams<"u"?URLSearchParams:jd,U_=typeof FormData<"u"?FormData:null,H_=typeof Blob<"u"?Blob:null,B_={isBrowser:!0,classes:{URLSearchParams:L_,FormData:U_,Blob:H_},protocols:["http","https","file","blob","url","data"]},Md=typeof window<"u"&&typeof document<"u",rd=typeof navigator=="object"&&navigator||void 0,q_=Md&&(!rd||["ReactNative","NativeScript","NS"].indexOf(rd.product)<0),V_=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope&&typeof self.importScripts=="function",P_=Md&&window.location.href||"http://localhost",G_=Object.freeze(Object.defineProperty({__proto__:null,hasBrowserEnv:Md,hasStandardBrowserEnv:q_,hasStandardBrowserWebWorkerEnv:V_,navigator:rd,origin:P_},Symbol.toStringTag,{value:"Module"})),Tt={...G_,...B_};function Y_(n,l){return Kc(n,new Tt.classes.URLSearchParams,{visitor:function(r,o,c,u){return Tt.isNode&&P.isBuffer(r)?(this.append(o,r.toString("base64")),!1):u.defaultVisitor.apply(this,arguments)},...l})}function F_(n){return P.matchAll(/\w+|\[(\w*)]/g,n).map(l=>l[0]==="[]"?"":l[1]||l[0])}function X_(n){const l={},r=Object.keys(n);let o;const c=r.length;let u;for(o=0;o=r.length;return d=!d&&P.isArray(c)?c.length:d,h?(P.hasOwnProp(c,d)?c[d]=[c[d],o]:c[d]=o,!p):((!c[d]||!P.isObject(c[d]))&&(c[d]=[]),l(r,o,c[d],u)&&P.isArray(c[d])&&(c[d]=X_(c[d])),!p)}if(P.isFormData(n)&&P.isFunction(n.entries)){const r={};return P.forEachEntry(n,(o,c)=>{l(F_(o),c,r,0)}),r}return null}function I_(n,l,r){if(P.isString(n))try{return(l||JSON.parse)(n),P.trim(n)}catch(o){if(o.name!=="SyntaxError")throw o}return(r||JSON.stringify)(n)}const Ir={transitional:Dd,adapter:["xhr","http","fetch"],transformRequest:[function(l,r){const o=r.getContentType()||"",c=o.indexOf("application/json")>-1,u=P.isObject(l);if(u&&P.isHTMLForm(l)&&(l=new FormData(l)),P.isFormData(l))return c?JSON.stringify(Cb(l)):l;if(P.isArrayBuffer(l)||P.isBuffer(l)||P.isStream(l)||P.isFile(l)||P.isBlob(l)||P.isReadableStream(l))return l;if(P.isArrayBufferView(l))return l.buffer;if(P.isURLSearchParams(l))return r.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),l.toString();let p;if(u){if(o.indexOf("application/x-www-form-urlencoded")>-1)return Y_(l,this.formSerializer).toString();if((p=P.isFileList(l))||o.indexOf("multipart/form-data")>-1){const h=this.env&&this.env.FormData;return Kc(p?{"files[]":l}:l,h&&new h,this.formSerializer)}}return u||c?(r.setContentType("application/json",!1),I_(l)):l}],transformResponse:[function(l){const r=this.transitional||Ir.transitional,o=r&&r.forcedJSONParsing,c=this.responseType==="json";if(P.isResponse(l)||P.isReadableStream(l))return l;if(l&&P.isString(l)&&(o&&!this.responseType||c)){const d=!(r&&r.silentJSONParsing)&&c;try{return JSON.parse(l,this.parseReviver)}catch(p){if(d)throw p.name==="SyntaxError"?xe.from(p,xe.ERR_BAD_RESPONSE,this,null,this.response):p}}return l}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:Tt.classes.FormData,Blob:Tt.classes.Blob},validateStatus:function(l){return l>=200&&l<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};P.forEach(["delete","get","head","post","put","patch"],n=>{Ir.headers[n]={}});const Q_=P.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),K_=n=>{const l={};let r,o,c;return n&&n.split(` +`).forEach(function(d){c=d.indexOf(":"),r=d.substring(0,c).trim().toLowerCase(),o=d.substring(c+1).trim(),!(!r||l[r]&&Q_[r])&&(r==="set-cookie"?l[r]?l[r].push(o):l[r]=[o]:l[r]=l[r]?l[r]+", "+o:o)}),l},Lg=Symbol("internals");function zr(n){return n&&String(n).trim().toLowerCase()}function Ac(n){return n===!1||n==null?n:P.isArray(n)?n.map(Ac):String(n)}function Z_(n){const l=Object.create(null),r=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let o;for(;o=r.exec(n);)l[o[1]]=o[2];return l}const W_=n=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(n.trim());function zf(n,l,r,o,c){if(P.isFunction(o))return o.call(this,l,r);if(c&&(l=r),!!P.isString(l)){if(P.isString(o))return l.indexOf(o)!==-1;if(P.isRegExp(o))return o.test(l)}}function J_(n){return n.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(l,r,o)=>r.toUpperCase()+o)}function $_(n,l){const r=P.toCamelCase(" "+l);["get","set","has"].forEach(o=>{Object.defineProperty(n,o+r,{value:function(c,u,d){return this[o].call(this,l,c,u,d)},configurable:!0})})}let Vt=class{constructor(l){l&&this.set(l)}set(l,r,o){const c=this;function u(p,h,m){const v=zr(h);if(!v)throw new Error("header name must be a non-empty string");const y=P.findKey(c,v);(!y||c[y]===void 0||m===!0||m===void 0&&c[y]!==!1)&&(c[y||h]=Ac(p))}const d=(p,h)=>P.forEach(p,(m,v)=>u(m,v,h));if(P.isPlainObject(l)||l instanceof this.constructor)d(l,r);else if(P.isString(l)&&(l=l.trim())&&!W_(l))d(K_(l),r);else if(P.isObject(l)&&P.isIterable(l)){let p={},h,m;for(const v of l){if(!P.isArray(v))throw TypeError("Object iterator must return a key-value pair");p[m=v[0]]=(h=p[m])?P.isArray(h)?[...h,v[1]]:[h,v[1]]:v[1]}d(p,r)}else l!=null&&u(r,l,o);return this}get(l,r){if(l=zr(l),l){const o=P.findKey(this,l);if(o){const c=this[o];if(!r)return c;if(r===!0)return Z_(c);if(P.isFunction(r))return r.call(this,c,o);if(P.isRegExp(r))return r.exec(c);throw new TypeError("parser must be boolean|regexp|function")}}}has(l,r){if(l=zr(l),l){const o=P.findKey(this,l);return!!(o&&this[o]!==void 0&&(!r||zf(this,this[o],o,r)))}return!1}delete(l,r){const o=this;let c=!1;function u(d){if(d=zr(d),d){const p=P.findKey(o,d);p&&(!r||zf(o,o[p],p,r))&&(delete o[p],c=!0)}}return P.isArray(l)?l.forEach(u):u(l),c}clear(l){const r=Object.keys(this);let o=r.length,c=!1;for(;o--;){const u=r[o];(!l||zf(this,this[u],u,l,!0))&&(delete this[u],c=!0)}return c}normalize(l){const r=this,o={};return P.forEach(this,(c,u)=>{const d=P.findKey(o,u);if(d){r[d]=Ac(c),delete r[u];return}const p=l?J_(u):String(u).trim();p!==u&&delete r[u],r[p]=Ac(c),o[p]=!0}),this}concat(...l){return this.constructor.concat(this,...l)}toJSON(l){const r=Object.create(null);return P.forEach(this,(o,c)=>{o!=null&&o!==!1&&(r[c]=l&&P.isArray(o)?o.join(", "):o)}),r}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([l,r])=>l+": "+r).join(` +`)}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(l){return l instanceof this?l:new this(l)}static concat(l,...r){const o=new this(l);return r.forEach(c=>o.set(c)),o}static accessor(l){const o=(this[Lg]=this[Lg]={accessors:{}}).accessors,c=this.prototype;function u(d){const p=zr(d);o[p]||($_(c,d),o[p]=!0)}return P.isArray(l)?l.forEach(u):u(l),this}};Vt.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]);P.reduceDescriptors(Vt.prototype,({value:n},l)=>{let r=l[0].toUpperCase()+l.slice(1);return{get:()=>n,set(o){this[r]=o}}});P.freezeMethods(Vt);function kf(n,l){const r=this||Ir,o=l||r,c=Vt.from(o.headers);let u=o.data;return P.forEach(n,function(p){u=p.call(r,u,c.normalize(),l?l.status:void 0)}),c.normalize(),u}function Ab(n){return!!(n&&n.__CANCEL__)}let Qr=class extends xe{constructor(l,r,o){super(l??"canceled",xe.ERR_CANCELED,r,o),this.name="CanceledError",this.__CANCEL__=!0}};function Tb(n,l,r){const o=r.config.validateStatus;!r.status||!o||o(r.status)?n(r):l(new xe("Request failed with status code "+r.status,[xe.ERR_BAD_REQUEST,xe.ERR_BAD_RESPONSE][Math.floor(r.status/100)-4],r.config,r.request,r))}function eC(n){const l=/^([-+\w]{1,25})(:?\/\/|:)/.exec(n);return l&&l[1]||""}function tC(n,l){n=n||10;const r=new Array(n),o=new Array(n);let c=0,u=0,d;return l=l!==void 0?l:1e3,function(h){const m=Date.now(),v=o[u];d||(d=m),r[c]=h,o[c]=m;let y=u,w=0;for(;y!==c;)w+=r[y++],y=y%n;if(c=(c+1)%n,c===u&&(u=(u+1)%n),m-d{r=v,c=null,u&&(clearTimeout(u),u=null),n(...m)};return[(...m)=>{const v=Date.now(),y=v-r;y>=o?d(m,v):(c=m,u||(u=setTimeout(()=>{u=null,d(c)},o-y)))},()=>c&&d(c)]}const jc=(n,l,r=3)=>{let o=0;const c=tC(50,250);return nC(u=>{const d=u.loaded,p=u.lengthComputable?u.total:void 0,h=d-o,m=c(h),v=d<=p;o=d;const y={loaded:d,total:p,progress:p?d/p:void 0,bytes:h,rate:m||void 0,estimated:m&&p&&v?(p-d)/m:void 0,event:u,lengthComputable:p!=null,[l?"download":"upload"]:!0};n(y)},r)},Ug=(n,l)=>{const r=n!=null;return[o=>l[0]({lengthComputable:r,total:n,loaded:o}),l[1]]},Hg=n=>(...l)=>P.asap(()=>n(...l)),aC=Tt.hasStandardBrowserEnv?((n,l)=>r=>(r=new URL(r,Tt.origin),n.protocol===r.protocol&&n.host===r.host&&(l||n.port===r.port)))(new URL(Tt.origin),Tt.navigator&&/(msie|trident)/i.test(Tt.navigator.userAgent)):()=>!0,lC=Tt.hasStandardBrowserEnv?{write(n,l,r,o,c,u,d){if(typeof document>"u")return;const p=[`${n}=${encodeURIComponent(l)}`];P.isNumber(r)&&p.push(`expires=${new Date(r).toUTCString()}`),P.isString(o)&&p.push(`path=${o}`),P.isString(c)&&p.push(`domain=${c}`),u===!0&&p.push("secure"),P.isString(d)&&p.push(`SameSite=${d}`),document.cookie=p.join("; ")},read(n){if(typeof document>"u")return null;const l=document.cookie.match(new RegExp("(?:^|; )"+n+"=([^;]*)"));return l?decodeURIComponent(l[1]):null},remove(n){this.write(n,"",Date.now()-864e5,"/")}}:{write(){},read(){return null},remove(){}};function iC(n){return typeof n!="string"?!1:/^([a-z][a-z\d+\-.]*:)?\/\//i.test(n)}function rC(n,l){return l?n.replace(/\/?\/$/,"")+"/"+l.replace(/^\/+/,""):n}function Ob(n,l,r){let o=!iC(l);return n&&(o||r==!1)?rC(n,l):l}const Bg=n=>n instanceof Vt?{...n}:n;function Al(n,l){l=l||{};const r={};function o(m,v,y,w){return P.isPlainObject(m)&&P.isPlainObject(v)?P.merge.call({caseless:w},m,v):P.isPlainObject(v)?P.merge({},v):P.isArray(v)?v.slice():v}function c(m,v,y,w){if(P.isUndefined(v)){if(!P.isUndefined(m))return o(void 0,m,y,w)}else return o(m,v,y,w)}function u(m,v){if(!P.isUndefined(v))return o(void 0,v)}function d(m,v){if(P.isUndefined(v)){if(!P.isUndefined(m))return o(void 0,m)}else return o(void 0,v)}function p(m,v,y){if(y in l)return o(m,v);if(y in n)return o(void 0,m)}const h={url:u,method:u,data:u,baseURL:d,transformRequest:d,transformResponse:d,paramsSerializer:d,timeout:d,timeoutMessage:d,withCredentials:d,withXSRFToken:d,adapter:d,responseType:d,xsrfCookieName:d,xsrfHeaderName:d,onUploadProgress:d,onDownloadProgress:d,decompress:d,maxContentLength:d,maxBodyLength:d,beforeRedirect:d,transport:d,httpAgent:d,httpsAgent:d,cancelToken:d,socketPath:d,responseEncoding:d,validateStatus:p,headers:(m,v,y)=>c(Bg(m),Bg(v),y,!0)};return P.forEach(Object.keys({...n,...l}),function(v){if(v==="__proto__"||v==="constructor"||v==="prototype")return;const y=P.hasOwnProp(h,v)?h[v]:c,w=y(n[v],l[v],v);P.isUndefined(w)&&y!==p||(r[v]=w)}),r}const Rb=n=>{const l=Al({},n);let{data:r,withXSRFToken:o,xsrfHeaderName:c,xsrfCookieName:u,headers:d,auth:p}=l;if(l.headers=d=Vt.from(d),l.url=_b(Ob(l.baseURL,l.url,l.allowAbsoluteUrls),n.params,n.paramsSerializer),p&&d.set("Authorization","Basic "+btoa((p.username||"")+":"+(p.password?unescape(encodeURIComponent(p.password)):""))),P.isFormData(r)){if(Tt.hasStandardBrowserEnv||Tt.hasStandardBrowserWebWorkerEnv)d.setContentType(void 0);else if(P.isFunction(r.getHeaders)){const h=r.getHeaders(),m=["content-type","content-length"];Object.entries(h).forEach(([v,y])=>{m.includes(v.toLowerCase())&&d.set(v,y)})}}if(Tt.hasStandardBrowserEnv&&(o&&P.isFunction(o)&&(o=o(l)),o||o!==!1&&aC(l.url))){const h=c&&u&&lC.read(u);h&&d.set(c,h)}return l},oC=typeof XMLHttpRequest<"u",cC=oC&&function(n){return new Promise(function(r,o){const c=Rb(n);let u=c.data;const d=Vt.from(c.headers).normalize();let{responseType:p,onUploadProgress:h,onDownloadProgress:m}=c,v,y,w,_,E;function S(){_&&_(),E&&E(),c.cancelToken&&c.cancelToken.unsubscribe(v),c.signal&&c.signal.removeEventListener("abort",v)}let A=new XMLHttpRequest;A.open(c.method.toUpperCase(),c.url,!0),A.timeout=c.timeout;function T(){if(!A)return;const j=Vt.from("getAllResponseHeaders"in A&&A.getAllResponseHeaders()),k={data:!p||p==="text"||p==="json"?A.responseText:A.response,status:A.status,statusText:A.statusText,headers:j,config:n,request:A};Tb(function(U){r(U),S()},function(U){o(U),S()},k),A=null}"onloadend"in A?A.onloadend=T:A.onreadystatechange=function(){!A||A.readyState!==4||A.status===0&&!(A.responseURL&&A.responseURL.indexOf("file:")===0)||setTimeout(T)},A.onabort=function(){A&&(o(new xe("Request aborted",xe.ECONNABORTED,n,A)),A=null)},A.onerror=function(z){const k=z&&z.message?z.message:"Network Error",Y=new xe(k,xe.ERR_NETWORK,n,A);Y.event=z||null,o(Y),A=null},A.ontimeout=function(){let z=c.timeout?"timeout of "+c.timeout+"ms exceeded":"timeout exceeded";const k=c.transitional||Dd;c.timeoutErrorMessage&&(z=c.timeoutErrorMessage),o(new xe(z,k.clarifyTimeoutError?xe.ETIMEDOUT:xe.ECONNABORTED,n,A)),A=null},u===void 0&&d.setContentType(null),"setRequestHeader"in A&&P.forEach(d.toJSON(),function(z,k){A.setRequestHeader(k,z)}),P.isUndefined(c.withCredentials)||(A.withCredentials=!!c.withCredentials),p&&p!=="json"&&(A.responseType=c.responseType),m&&([w,E]=jc(m,!0),A.addEventListener("progress",w)),h&&A.upload&&([y,_]=jc(h),A.upload.addEventListener("progress",y),A.upload.addEventListener("loadend",_)),(c.cancelToken||c.signal)&&(v=j=>{A&&(o(!j||j.type?new Qr(null,n,A):j),A.abort(),A=null)},c.cancelToken&&c.cancelToken.subscribe(v),c.signal&&(c.signal.aborted?v():c.signal.addEventListener("abort",v)));const O=eC(c.url);if(O&&Tt.protocols.indexOf(O)===-1){o(new xe("Unsupported protocol "+O+":",xe.ERR_BAD_REQUEST,n));return}A.send(u||null)})},sC=(n,l)=>{const{length:r}=n=n?n.filter(Boolean):[];if(l||r){let o=new AbortController,c;const u=function(m){if(!c){c=!0,p();const v=m instanceof Error?m:this.reason;o.abort(v instanceof xe?v:new Qr(v instanceof Error?v.message:v))}};let d=l&&setTimeout(()=>{d=null,u(new xe(`timeout of ${l}ms exceeded`,xe.ETIMEDOUT))},l);const p=()=>{n&&(d&&clearTimeout(d),d=null,n.forEach(m=>{m.unsubscribe?m.unsubscribe(u):m.removeEventListener("abort",u)}),n=null)};n.forEach(m=>m.addEventListener("abort",u));const{signal:h}=o;return h.unsubscribe=()=>P.asap(p),h}},uC=function*(n,l){let r=n.byteLength;if(r{const c=fC(n,l);let u=0,d,p=h=>{d||(d=!0,o&&o(h))};return new ReadableStream({async pull(h){try{const{done:m,value:v}=await c.next();if(m){p(),h.close();return}let y=v.byteLength;if(r){let w=u+=y;r(w)}h.enqueue(new Uint8Array(v))}catch(m){throw p(m),m}},cancel(h){return p(h),c.return()}},{highWaterMark:2})},Vg=64*1024,{isFunction:pc}=P,pC=(({Request:n,Response:l})=>({Request:n,Response:l}))(P.global),{ReadableStream:Pg,TextEncoder:Gg}=P.global,Yg=(n,...l)=>{try{return!!n(...l)}catch{return!1}},mC=n=>{n=P.merge.call({skipUndefined:!0},pC,n);const{fetch:l,Request:r,Response:o}=n,c=l?pc(l):typeof fetch=="function",u=pc(r),d=pc(o);if(!c)return!1;const p=c&&pc(Pg),h=c&&(typeof Gg=="function"?(E=>S=>E.encode(S))(new Gg):async E=>new Uint8Array(await new r(E).arrayBuffer())),m=u&&p&&Yg(()=>{let E=!1;const S=new r(Tt.origin,{body:new Pg,method:"POST",get duplex(){return E=!0,"half"}}).headers.has("Content-Type");return E&&!S}),v=d&&p&&Yg(()=>P.isReadableStream(new o("").body)),y={stream:v&&(E=>E.body)};c&&["text","arrayBuffer","blob","formData","stream"].forEach(E=>{!y[E]&&(y[E]=(S,A)=>{let T=S&&S[E];if(T)return T.call(S);throw new xe(`Response type '${E}' is not supported`,xe.ERR_NOT_SUPPORT,A)})});const w=async E=>{if(E==null)return 0;if(P.isBlob(E))return E.size;if(P.isSpecCompliantForm(E))return(await new r(Tt.origin,{method:"POST",body:E}).arrayBuffer()).byteLength;if(P.isArrayBufferView(E)||P.isArrayBuffer(E))return E.byteLength;if(P.isURLSearchParams(E)&&(E=E+""),P.isString(E))return(await h(E)).byteLength},_=async(E,S)=>{const A=P.toFiniteNumber(E.getContentLength());return A??w(S)};return async E=>{let{url:S,method:A,data:T,signal:O,cancelToken:j,timeout:z,onDownloadProgress:k,onUploadProgress:Y,responseType:U,headers:I,withCredentials:ae="same-origin",fetchOptions:ce}=Rb(E),H=l||fetch;U=U?(U+"").toLowerCase():"text";let le=sC([O,j&&j.toAbortSignal()],z),ve=null;const re=le&&le.unsubscribe&&(()=>{le.unsubscribe()});let de;try{if(Y&&m&&A!=="get"&&A!=="head"&&(de=await _(I,T))!==0){let N=new r(S,{method:"POST",body:T,duplex:"half"}),F;if(P.isFormData(T)&&(F=N.headers.get("content-type"))&&I.setContentType(F),N.body){const[te,ne]=Ug(de,jc(Hg(Y)));T=qg(N.body,Vg,te,ne)}}P.isString(ae)||(ae=ae?"include":"omit");const M=u&&"credentials"in r.prototype,Q={...ce,signal:le,method:A.toUpperCase(),headers:I.normalize().toJSON(),body:T,duplex:"half",credentials:M?ae:void 0};ve=u&&new r(S,Q);let W=await(u?H(ve,ce):H(S,Q));const ee=v&&(U==="stream"||U==="response");if(v&&(k||ee&&re)){const N={};["status","statusText","headers"].forEach(ie=>{N[ie]=W[ie]});const F=P.toFiniteNumber(W.headers.get("content-length")),[te,ne]=k&&Ug(F,jc(Hg(k),!0))||[];W=new o(qg(W.body,Vg,te,()=>{ne&&ne(),re&&re()}),N)}U=U||"text";let J=await y[P.findKey(y,U)||"text"](W,E);return!ee&&re&&re(),await new Promise((N,F)=>{Tb(N,F,{data:J,headers:Vt.from(W.headers),status:W.status,statusText:W.statusText,config:E,request:ve})})}catch(M){throw re&&re(),M&&M.name==="TypeError"&&/Load failed|fetch/i.test(M.message)?Object.assign(new xe("Network Error",xe.ERR_NETWORK,E,ve,M&&M.response),{cause:M.cause||M}):xe.from(M,M&&M.code,E,ve,M&&M.response)}}},hC=new Map,Nb=n=>{let l=n&&n.env||{};const{fetch:r,Request:o,Response:c}=l,u=[o,c,r];let d=u.length,p=d,h,m,v=hC;for(;p--;)h=u[p],m=v.get(h),m===void 0&&v.set(h,m=p?new Map:mC(l)),v=m;return m};Nb();const zd={http:D_,xhr:cC,fetch:{get:Nb}};P.forEach(zd,(n,l)=>{if(n){try{Object.defineProperty(n,"name",{value:l})}catch{}Object.defineProperty(n,"adapterName",{value:l})}});const Fg=n=>`- ${n}`,vC=n=>P.isFunction(n)||n===null||n===!1;function gC(n,l){n=P.isArray(n)?n:[n];const{length:r}=n;let o,c;const u={};for(let d=0;d`adapter ${h} `+(m===!1?"is not supported by the environment":"is not available in the build"));let p=r?d.length>1?`since : +`+d.map(Fg).join(` +`):" "+Fg(d[0]):"as no adapter specified";throw new xe("There is no suitable adapter to dispatch the request "+p,"ERR_NOT_SUPPORT")}return c}const jb={getAdapter:gC,adapters:zd};function Lf(n){if(n.cancelToken&&n.cancelToken.throwIfRequested(),n.signal&&n.signal.aborted)throw new Qr(null,n)}function Xg(n){return Lf(n),n.headers=Vt.from(n.headers),n.data=kf.call(n,n.transformRequest),["post","put","patch"].indexOf(n.method)!==-1&&n.headers.setContentType("application/x-www-form-urlencoded",!1),jb.getAdapter(n.adapter||Ir.adapter,n)(n).then(function(o){return Lf(n),o.data=kf.call(n,n.transformResponse,o),o.headers=Vt.from(o.headers),o},function(o){return Ab(o)||(Lf(n),o&&o.response&&(o.response.data=kf.call(n,n.transformResponse,o.response),o.response.headers=Vt.from(o.response.headers))),Promise.reject(o)})}const Db="1.13.5",Zc={};["object","boolean","number","function","string","symbol"].forEach((n,l)=>{Zc[n]=function(o){return typeof o===n||"a"+(l<1?"n ":" ")+n}});const Ig={};Zc.transitional=function(l,r,o){function c(u,d){return"[Axios v"+Db+"] Transitional option '"+u+"'"+d+(o?". "+o:"")}return(u,d,p)=>{if(l===!1)throw new xe(c(d," has been removed"+(r?" in "+r:"")),xe.ERR_DEPRECATED);return r&&!Ig[d]&&(Ig[d]=!0,console.warn(c(d," has been deprecated since v"+r+" and will be removed in the near future"))),l?l(u,d,p):!0}};Zc.spelling=function(l){return(r,o)=>(console.warn(`${o} is likely a misspelling of ${l}`),!0)};function yC(n,l,r){if(typeof n!="object")throw new xe("options must be an object",xe.ERR_BAD_OPTION_VALUE);const o=Object.keys(n);let c=o.length;for(;c-- >0;){const u=o[c],d=l[u];if(d){const p=n[u],h=p===void 0||d(p,u,n);if(h!==!0)throw new xe("option "+u+" must be "+h,xe.ERR_BAD_OPTION_VALUE);continue}if(r!==!0)throw new xe("Unknown option "+u,xe.ERR_BAD_OPTION)}}const Tc={assertOptions:yC,validators:Zc},fn=Tc.validators;let Cl=class{constructor(l){this.defaults=l||{},this.interceptors={request:new kg,response:new kg}}async request(l,r){try{return await this._request(l,r)}catch(o){if(o instanceof Error){let c={};Error.captureStackTrace?Error.captureStackTrace(c):c=new Error;const u=c.stack?c.stack.replace(/^.+\n/,""):"";try{o.stack?u&&!String(o.stack).endsWith(u.replace(/^.+\n.+\n/,""))&&(o.stack+=` +`+u):o.stack=u}catch{}}throw o}}_request(l,r){typeof l=="string"?(r=r||{},r.url=l):r=l||{},r=Al(this.defaults,r);const{transitional:o,paramsSerializer:c,headers:u}=r;o!==void 0&&Tc.assertOptions(o,{silentJSONParsing:fn.transitional(fn.boolean),forcedJSONParsing:fn.transitional(fn.boolean),clarifyTimeoutError:fn.transitional(fn.boolean),legacyInterceptorReqResOrdering:fn.transitional(fn.boolean)},!1),c!=null&&(P.isFunction(c)?r.paramsSerializer={serialize:c}:Tc.assertOptions(c,{encode:fn.function,serialize:fn.function},!0)),r.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?r.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:r.allowAbsoluteUrls=!0),Tc.assertOptions(r,{baseUrl:fn.spelling("baseURL"),withXsrfToken:fn.spelling("withXSRFToken")},!0),r.method=(r.method||this.defaults.method||"get").toLowerCase();let d=u&&P.merge(u.common,u[r.method]);u&&P.forEach(["delete","get","head","post","put","patch","common"],E=>{delete u[E]}),r.headers=Vt.concat(d,u);const p=[];let h=!0;this.interceptors.request.forEach(function(S){if(typeof S.runWhen=="function"&&S.runWhen(r)===!1)return;h=h&&S.synchronous;const A=r.transitional||Dd;A&&A.legacyInterceptorReqResOrdering?p.unshift(S.fulfilled,S.rejected):p.push(S.fulfilled,S.rejected)});const m=[];this.interceptors.response.forEach(function(S){m.push(S.fulfilled,S.rejected)});let v,y=0,w;if(!h){const E=[Xg.bind(this),void 0];for(E.unshift(...p),E.push(...m),w=E.length,v=Promise.resolve(r);y{if(!o._listeners)return;let u=o._listeners.length;for(;u-- >0;)o._listeners[u](c);o._listeners=null}),this.promise.then=c=>{let u;const d=new Promise(p=>{o.subscribe(p),u=p}).then(c);return d.cancel=function(){o.unsubscribe(u)},d},l(function(u,d,p){o.reason||(o.reason=new Qr(u,d,p),r(o.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(l){if(this.reason){l(this.reason);return}this._listeners?this._listeners.push(l):this._listeners=[l]}unsubscribe(l){if(!this._listeners)return;const r=this._listeners.indexOf(l);r!==-1&&this._listeners.splice(r,1)}toAbortSignal(){const l=new AbortController,r=o=>{l.abort(o)};return this.subscribe(r),l.signal.unsubscribe=()=>this.unsubscribe(r),l.signal}static source(){let l;return{token:new Mb(function(c){l=c}),cancel:l}}};function xC(n){return function(r){return n.apply(null,r)}}function SC(n){return P.isObject(n)&&n.isAxiosError===!0}const od={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(od).forEach(([n,l])=>{od[l]=n});function zb(n){const l=new Cl(n),r=pb(Cl.prototype.request,l);return P.extend(r,Cl.prototype,l,{allOwnKeys:!0}),P.extend(r,l,null,{allOwnKeys:!0}),r.create=function(c){return zb(Al(n,c))},r}const it=zb(Ir);it.Axios=Cl;it.CanceledError=Qr;it.CancelToken=bC;it.isCancel=Ab;it.VERSION=Db;it.toFormData=Kc;it.AxiosError=xe;it.Cancel=it.CanceledError;it.all=function(l){return Promise.all(l)};it.spread=xC;it.isAxiosError=SC;it.mergeConfig=Al;it.AxiosHeaders=Vt;it.formToJSON=n=>Cb(P.isHTMLForm(n)?new FormData(n):n);it.getAdapter=jb.getAdapter;it.HttpStatusCode=od;it.default=it;const{Axios:Wj,AxiosError:Jj,CanceledError:$j,isCancel:eD,CancelToken:tD,VERSION:nD,all:aD,Cancel:lD,isAxiosError:iD,spread:rD,toFormData:oD,AxiosHeaders:cD,HttpStatusCode:sD,formToJSON:uD,getAdapter:fD,mergeConfig:dD}=it,pa=it.create({baseURL:"/api"}),wC=async()=>(await pa.get("/models")).data,EC=async()=>(await pa.get("/controlnets")).data,_C=async n=>{const l=await pa.post("/generate",n);return console.log("Generation response:",l.data),l.data},CC=async()=>{await pa.post("/interrupt")},AC=async()=>(await pa.get("/settings/last")).data,TC=async()=>(await pa.get("/settings/preferences")).data,OC=async n=>(await pa.post("/settings/preferences",n)).data,RC=async(n,l=!1)=>(await pa.post("/settings/history",{settings:n,include_prompt:l})).data,NC=async n=>(await pa.post("/images/metadata",{image:n})).data;function jC(n){return n.find(l=>l.name.toLowerCase().includes("dreamshaper"))??n[0]}function DC(n,l){const r=n.capabilities;return r.supports_hires_fix||(l.hiresfix=!1),r.supports_img2img||(l.img2img_mode=!1),r.supports_controlnet||(l.controlnet_enabled=!1),r.supports_stable_fast||(l.stable_fast=!1),r.supports_deepcache||(l.deepcache_enabled=!1),r.supports_tome||(l.tome_enabled=!1),l}function kb(n,l){const r={model_path:n.path};if(n.type==="Flux2Klein")r.width=1024,r.height=1024,r.sampler="euler",r.scheduler="simple",r.steps=4,r.cfg_scale=1,r.refiner_model_path="";else if(n.type==="SDXL"){r.width=1024,r.height=1024,r.sampler="euler",r.scheduler="simple",r.steps=25;const o=l.find(c=>c.type==="SDXL"&&(c.name.toLowerCase().includes("refiner")||c.path.toLowerCase().includes("refiner")));o&&(r.refiner_model_path=o.path,r.refiner_switch_step=20)}else r.width=512,r.height=512,r.sampler="dpmpp_2m",r.scheduler="karras",r.steps=20,r.refiner_model_path="";return DC(n,r)}function MC(n){const l={};return n.seed!==void 0&&(l.seed=n.seed),n.steps!==void 0&&(l.steps=n.steps),n.cfg_scale!==void 0&&(l.cfg_scale=n.cfg_scale),n.sampler&&(l.sampler=n.sampler),n.scheduler&&(l.scheduler=n.scheduler),n.model_path&&(l.model_path=n.model_path),n.width&&(l.width=n.width),n.height&&(l.height=n.height),n.prompt&&(l.prompt=n.prompt),n.negative_prompt&&(l.negative_prompt=n.negative_prompt),n.denoise!==void 0&&(l.img2img_denoise=n.denoise),n.weight_quantization!==void 0&&(l.weight_quantization=n.weight_quantization),n.torch_compile!==void 0&&(l.torch_compile=n.torch_compile),n.fp8_inference!==void 0&&(l.fp8_inference=n.fp8_inference),n.controlnet_enabled!==void 0&&(l.controlnet_enabled=n.controlnet_enabled),n.controlnet_model!==void 0&&(l.controlnet_model=n.controlnet_model),n.controlnet_strength!==void 0&&(l.controlnet_strength=n.controlnet_strength),n.controlnet_type!==void 0&&(l.controlnet_type=n.controlnet_type),n.enable_multiscale!==void 0&&(l.enable_multiscale=n.enable_multiscale),n.multiscale_preset!==void 0&&(l.multiscale_preset=n.multiscale_preset),n.multiscale_factor!==void 0&&(l.multiscale_factor=n.multiscale_factor),n.multiscale_fullres_start!==void 0&&(l.multiscale_fullres_start=n.multiscale_fullres_start),n.multiscale_fullres_end!==void 0&&(l.multiscale_fullres_end=n.multiscale_fullres_end),n.multiscale_intermittent_fullres!==void 0&&(l.multiscale_intermittent_fullres=n.multiscale_intermittent_fullres),n.deepcache_enabled!==void 0&&(l.deepcache_enabled=n.deepcache_enabled),n.deepcache_interval!==void 0&&(l.deepcache_interval=n.deepcache_interval),n.deepcache_depth!==void 0&&(l.deepcache_depth=n.deepcache_depth),n.cfg_free_enabled!==void 0&&(l.cfg_free_enabled=n.cfg_free_enabled),n.cfg_free_start_percent!==void 0&&(l.cfg_free_start_percent=n.cfg_free_start_percent),n.tome_enabled!==void 0&&(l.tome_enabled=n.tome_enabled),n.tome_ratio!==void 0&&(l.tome_ratio=n.tome_ratio),l}const Qg=n=>{let l;const r=new Set,o=(m,v)=>{const y=typeof m=="function"?m(l):m;if(!Object.is(y,l)){const w=l;l=v??(typeof y!="object"||y===null)?y:Object.assign({},l,y),r.forEach(_=>_(l,w))}},c=()=>l,p={setState:o,getState:c,getInitialState:()=>h,subscribe:m=>(r.add(m),()=>r.delete(m))},h=l=n(o,c,p);return p},zC=(n=>n?Qg(n):Qg),kC=n=>n;function LC(n,l=kC){const r=Qe.useSyncExternalStore(n.subscribe,Qe.useCallback(()=>l(n.getState()),[n,l]),Qe.useCallback(()=>l(n.getInitialState()),[n,l]));return Qe.useDebugValue(r),r}const Kg=n=>{const l=zC(n),r=o=>LC(l,o);return Object.assign(r,l),r},UC=(n=>n?Kg(n):Kg),Ia=UC(n=>({settings:{prompt:"",negative_prompt:"",width:512,height:512,num_images:1,batch_size:1,steps:20,cfg_scale:7,seed:-1,scheduler:"ays",sampler:"dpmpp_sde_cfgpp",model_path:"",refiner_model_path:"",refiner_switch_step:15,img2img_mode:!1,img2img_denoise:.75,img2img_image:void 0,controlnet_enabled:!1,controlnet_strength:1,controlnet_type:"canny",hiresfix:!1,adetailer:!1,enhance_prompt:!1,stable_fast:!1,reuse_seed:!1,keep_models_loaded:!0,enable_preview:!0,preview_fidelity:"balanced",persist_prompt_history:!1,enable_multiscale:!1,multiscale_preset:"disabled",multiscale_factor:.5,multiscale_fullres_start:10,multiscale_fullres_end:8,multiscale_intermittent_fullres:!0,deepcache_enabled:!1,deepcache_interval:3,deepcache_depth:2,cfg_free_enabled:!1,cfg_free_start_percent:70,tome_enabled:!1,tome_ratio:.5,torch_compile:!1,vae_autotune:!1,fp8_inference:!1,weight_quantization:null},availableModels:[],availableControlNets:[],status:"idle",currentImage:null,gallery:[],preview:null,serverStatus:!1,settingsHistory:[],setSettingsHistory:l=>n({settingsHistory:l}),appendSettingsSnapshot:l=>n(r=>({settingsHistory:[l,...r.settingsHistory]})),setSettings:l=>n(r=>({settings:{...r.settings,...l}})),setModels:l=>n({availableModels:l}),setControlNets:l=>n({availableControlNets:l}),setStatus:l=>n({status:l}),setCurrentImage:l=>n({currentImage:l}),addToGallery:l=>n(r=>({gallery:[l,...r.gallery]})),addManyToGallery:l=>n(r=>({gallery:l.length>0?[...l,...r.gallery]:r.gallery})),setPreview:l=>n({preview:l}),setServerStatus:l=>n({serverStatus:l})})),Zg=n=>Symbol.iterator in n,Wg=n=>"entries"in n,Jg=(n,l)=>{const r=n instanceof Map?n:new Map(n.entries()),o=l instanceof Map?l:new Map(l.entries());if(r.size!==o.size)return!1;for(const[c,u]of r)if(!o.has(c)||!Object.is(u,o.get(c)))return!1;return!0},HC=(n,l)=>{const r=n[Symbol.iterator](),o=l[Symbol.iterator]();let c=r.next(),u=o.next();for(;!c.done&&!u.done;){if(!Object.is(c.value,u.value))return!1;c=r.next(),u=o.next()}return!!c.done&&!!u.done};function BC(n,l){return Object.is(n,l)?!0:typeof n!="object"||n===null||typeof l!="object"||l===null||Object.getPrototypeOf(n)!==Object.getPrototypeOf(l)?!1:Zg(n)&&Zg(l)?Wg(n)&&Wg(l)?Jg(n,l):HC(n,l):Jg({entries:()=>Object.entries(n)},{entries:()=>Object.entries(l)})}function Di(n){const l=Qe.useRef(void 0);return r=>{const o=n(r);return BC(l.current,o)?l.current:l.current=o}}function qC(n){return new Promise((l,r)=>{const o=new FileReader;o.onload=c=>{const u=c.target?.result;typeof u=="string"?l(u):r(new Error("Unable to read image file."))},o.onerror=()=>r(o.error??new Error("Unable to read image file.")),o.readAsDataURL(n)})}function kd(){const n=x.useRef(!1),l=x.useRef(0),{settings:r,availableModels:o,status:c,setSettings:u,setStatus:d,setCurrentImage:p,addToGallery:h,addManyToGallery:m,appendSettingsSnapshot:v,setPreview:y}=Ia(Di(O=>({settings:O.settings,availableModels:O.availableModels,status:O.status,setSettings:O.setSettings,setStatus:O.setStatus,setCurrentImage:O.setCurrentImage,addToGallery:O.addToGallery,addManyToGallery:O.addManyToGallery,appendSettingsSnapshot:O.appendSettingsSnapshot,setPreview:O.setPreview}))),w=x.useCallback(async O=>{try{const j=await NC(O),z=MC(j?.metadata??{});return u(z),{ok:!0,message:"Settings imported from image metadata.",warning:z.model_path&&!o.find(Y=>Y.path===z.model_path)?"The imported model is not available locally.":void 0}}catch(j){return console.error("Failed to import settings from image",j),{ok:!1,message:"Could not read settings from that image."}}},[o,u]),_=x.useCallback(async O=>{if(O.length===0)return{ok:!1,message:"Select an image to import settings."};try{const j=await qC(O[0]);return await w(j)}catch(j){return console.error("Failed to read image file",j),{ok:!1,message:"Could not read that file."}}},[w]),E=x.useCallback(async()=>{try{const O=await RC(r,!!r.persist_prompt_history);return O?.snapshot&&v(O.snapshot),{ok:!0,message:"Settings saved to history."}}catch(O){return console.error("Failed to save settings history",O),{ok:!1,message:"Could not save settings history."}}},[v,r]),S=x.useCallback(async()=>{try{const j=(await AC())?.seed??-1;return u({seed:typeof j=="number"?j:-1}),{ok:!0,message:"Seed restored from the last run."}}catch(O){return console.error("Failed to fetch last seed",O),{ok:!1,message:"Could not fetch the last seed."}}},[u]),A=x.useCallback(async O=>{const j=Ia.getState().settings;u(O);try{return await OC({torch_compile:O.torch_compile,vae_autotune:O.vae_autotune}),{ok:!0,message:"Autotune preferences saved."}}catch(z){return console.error("Failed to save autotune preferences",z),u({torch_compile:j.torch_compile,vae_autotune:j.vae_autotune,stable_fast:j.stable_fast}),{ok:!1,message:"Could not save autotune preferences."}}},[u]);return{handleGenerate:x.useCallback(async()=>{if(c==="generating"){try{n.current=!0,await CC()}catch(z){console.error("Failed to interrupt generation",z)}return}const O=l.current+1;l.current=O,n.current=!1,d("generating"),y(null);const j={id:`${Date.now().toString(36)}${Math.random().toString(36).slice(2,8)}`,ts:Math.floor(Date.now()/1e3),settings:{...r}};v(j);try{const z=await _C(r);if(l.current!==O||n.current){y(null),d("idle");return}const k=z.images??(z.image?[z.image]:[]),Y=k[0]??null;Y&&x.startTransition(()=>{p(Y),k.length===1?h(Y):m(k)})}catch(z){if(n.current&&it.isAxiosError(z)&&(z.response?.status===409||String(z.response?.data?.detail??"").toLowerCase().includes("interrupt"))){y(null),d("idle");return}console.error("Generation failed",z),d("error");return}d("idle")},[m,h,v,p,y,d,r,c]),importSettingsFromBase64:w,importSettingsFromFiles:_,saveSettingsSnapshot:E,restoreLastSeed:S,updateAutotuneSettings:A}}function $g(n,l){if(typeof n=="function")return n(l);n!=null&&(n.current=l)}function Mi(...n){return l=>{let r=!1;const o=n.map(c=>{const u=$g(c,l);return!r&&typeof u=="function"&&(r=!0),u});if(r)return()=>{for(let c=0;c{let{children:u,...d}=o;Lb(u)&&typeof Dc=="function"&&(u=Dc(u._payload));const p=x.Children.toArray(u),h=p.find(XC);if(h){const m=h.props.children,v=p.map(y=>y===h?x.Children.count(m)>1?x.Children.only(null):x.isValidElement(m)?m.props.children:null:y);return b.jsx(l,{...d,ref:c,children:x.isValidElement(m)?x.cloneElement(m,void 0,v):null})}return b.jsx(l,{...d,ref:c,children:u})});return r.displayName=`${n}.Slot`,r}var GC=Ub("Slot");function YC(n){const l=x.forwardRef((r,o)=>{let{children:c,...u}=r;if(Lb(c)&&typeof Dc=="function"&&(c=Dc(c._payload)),x.isValidElement(c)){const d=QC(c),p=IC(u,c.props);return c.type!==x.Fragment&&(p.ref=o?Mi(o,d):d),x.cloneElement(c,p)}return x.Children.count(c)>1?x.Children.only(null):null});return l.displayName=`${n}.SlotClone`,l}var FC=Symbol("radix.slottable");function XC(n){return x.isValidElement(n)&&typeof n.type=="function"&&"__radixId"in n.type&&n.type.__radixId===FC}function IC(n,l){const r={...l};for(const o in l){const c=n[o],u=l[o];/^on[A-Z]/.test(o)?c&&u?r[o]=(...p)=>{const h=u(...p);return c(...p),h}:c&&(r[o]=c):o==="style"?r[o]={...c,...u}:o==="className"&&(r[o]=[c,u].filter(Boolean).join(" "))}return{...n,...r}}function QC(n){let l=Object.getOwnPropertyDescriptor(n.props,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning;return r?n.ref:(l=Object.getOwnPropertyDescriptor(n,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning,r?n.props.ref:n.props.ref||n.ref)}function Hb(n){var l,r,o="";if(typeof n=="string"||typeof n=="number")o+=n;else if(typeof n=="object")if(Array.isArray(n)){var c=n.length;for(l=0;ltypeof n=="boolean"?`${n}`:n===0?"0":n,ty=Bb,qb=(n,l)=>r=>{var o;if(l?.variants==null)return ty(n,r?.class,r?.className);const{variants:c,defaultVariants:u}=l,d=Object.keys(c).map(m=>{const v=r?.[m],y=u?.[m];if(v===null)return null;const w=ey(v)||ey(y);return c[m][w]}),p=r&&Object.entries(r).reduce((m,v)=>{let[y,w]=v;return w===void 0||(m[y]=w),m},{}),h=l==null||(o=l.compoundVariants)===null||o===void 0?void 0:o.reduce((m,v)=>{let{class:y,className:w,..._}=v;return Object.entries(_).every(E=>{let[S,A]=E;return Array.isArray(A)?A.includes({...u,...p}[S]):{...u,...p}[S]===A})?[...m,y,w]:m},[]);return ty(n,d,h,r?.class,r?.className)},KC=(n,l)=>{const r=new Array(n.length+l.length);for(let o=0;o({classGroupId:n,validator:l}),Vb=(n=new Map,l=null,r)=>({nextPart:n,validators:l,classGroupId:r}),Mc="-",ny=[],WC="arbitrary..",JC=n=>{const l=eA(n),{conflictingClassGroups:r,conflictingClassGroupModifiers:o}=n;return{getClassGroupId:d=>{if(d.startsWith("[")&&d.endsWith("]"))return $C(d);const p=d.split(Mc),h=p[0]===""&&p.length>1?1:0;return Pb(p,h,l)},getConflictingClassGroupIds:(d,p)=>{if(p){const h=o[d],m=r[d];return h?m?KC(m,h):h:m||ny}return r[d]||ny}}},Pb=(n,l,r)=>{if(n.length-l===0)return r.classGroupId;const c=n[l],u=r.nextPart.get(c);if(u){const m=Pb(n,l+1,u);if(m)return m}const d=r.validators;if(d===null)return;const p=l===0?n.join(Mc):n.slice(l).join(Mc),h=d.length;for(let m=0;mn.slice(1,-1).indexOf(":")===-1?void 0:(()=>{const l=n.slice(1,-1),r=l.indexOf(":"),o=l.slice(0,r);return o?WC+o:void 0})(),eA=n=>{const{theme:l,classGroups:r}=n;return tA(r,l)},tA=(n,l)=>{const r=Vb();for(const o in n){const c=n[o];Ld(c,r,o,l)}return r},Ld=(n,l,r,o)=>{const c=n.length;for(let u=0;u{if(typeof n=="string"){aA(n,l,r);return}if(typeof n=="function"){lA(n,l,r,o);return}iA(n,l,r,o)},aA=(n,l,r)=>{const o=n===""?l:Gb(l,n);o.classGroupId=r},lA=(n,l,r,o)=>{if(rA(n)){Ld(n(o),l,r,o);return}l.validators===null&&(l.validators=[]),l.validators.push(ZC(r,n))},iA=(n,l,r,o)=>{const c=Object.entries(n),u=c.length;for(let d=0;d{let r=n;const o=l.split(Mc),c=o.length;for(let u=0;u"isThemeGetter"in n&&n.isThemeGetter===!0,oA=n=>{if(n<1)return{get:()=>{},set:()=>{}};let l=0,r=Object.create(null),o=Object.create(null);const c=(u,d)=>{r[u]=d,l++,l>n&&(l=0,o=r,r=Object.create(null))};return{get(u){let d=r[u];if(d!==void 0)return d;if((d=o[u])!==void 0)return c(u,d),d},set(u,d){u in r?r[u]=d:c(u,d)}}},cd="!",ay=":",cA=[],ly=(n,l,r,o,c)=>({modifiers:n,hasImportantModifier:l,baseClassName:r,maybePostfixModifierPosition:o,isExternal:c}),sA=n=>{const{prefix:l,experimentalParseClassName:r}=n;let o=c=>{const u=[];let d=0,p=0,h=0,m;const v=c.length;for(let S=0;Sh?m-h:void 0;return ly(u,_,w,E)};if(l){const c=l+ay,u=o;o=d=>d.startsWith(c)?u(d.slice(c.length)):ly(cA,!1,d,void 0,!0)}if(r){const c=o;o=u=>r({className:u,parseClassName:c})}return o},uA=n=>{const l=new Map;return n.orderSensitiveModifiers.forEach((r,o)=>{l.set(r,1e6+o)}),r=>{const o=[];let c=[];for(let u=0;u0&&(c.sort(),o.push(...c),c=[]),o.push(d)):c.push(d)}return c.length>0&&(c.sort(),o.push(...c)),o}},fA=n=>({cache:oA(n.cacheSize),parseClassName:sA(n),sortModifiers:uA(n),...JC(n)}),dA=/\s+/,pA=(n,l)=>{const{parseClassName:r,getClassGroupId:o,getConflictingClassGroupIds:c,sortModifiers:u}=l,d=[],p=n.trim().split(dA);let h="";for(let m=p.length-1;m>=0;m-=1){const v=p[m],{isExternal:y,modifiers:w,hasImportantModifier:_,baseClassName:E,maybePostfixModifierPosition:S}=r(v);if(y){h=v+(h.length>0?" "+h:h);continue}let A=!!S,T=o(A?E.substring(0,S):E);if(!T){if(!A){h=v+(h.length>0?" "+h:h);continue}if(T=o(E),!T){h=v+(h.length>0?" "+h:h);continue}A=!1}const O=w.length===0?"":w.length===1?w[0]:u(w).join(":"),j=_?O+cd:O,z=j+T;if(d.indexOf(z)>-1)continue;d.push(z);const k=c(T,A);for(let Y=0;Y0?" "+h:h)}return h},mA=(...n)=>{let l=0,r,o,c="";for(;l{if(typeof n=="string")return n;let l,r="";for(let o=0;o{let r,o,c,u;const d=h=>{const m=l.reduce((v,y)=>y(v),n());return r=fA(m),o=r.cache.get,c=r.cache.set,u=p,p(h)},p=h=>{const m=o(h);if(m)return m;const v=pA(h,r);return c(h,v),v};return u=d,(...h)=>u(mA(...h))},vA=[],mt=n=>{const l=r=>r[n]||vA;return l.isThemeGetter=!0,l},Fb=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,Xb=/^\((?:(\w[\w-]*):)?(.+)\)$/i,gA=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,yA=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,bA=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,xA=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,SA=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,wA=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,Pa=n=>gA.test(n),Ae=n=>!!n&&!Number.isNaN(Number(n)),Ga=n=>!!n&&Number.isInteger(Number(n)),Uf=n=>n.endsWith("%")&&Ae(n.slice(0,-1)),oa=n=>yA.test(n),Ib=()=>!0,EA=n=>bA.test(n)&&!xA.test(n),Ud=()=>!1,_A=n=>SA.test(n),CA=n=>wA.test(n),AA=n=>!fe(n)&&!me(n),TA=n=>Za(n,Zb,Ud),fe=n=>Fb.test(n),bl=n=>Za(n,Wb,EA),iy=n=>Za(n,kA,Ae),OA=n=>Za(n,$b,Ib),RA=n=>Za(n,Jb,Ud),ry=n=>Za(n,Qb,Ud),NA=n=>Za(n,Kb,CA),mc=n=>Za(n,ex,_A),me=n=>Xb.test(n),kr=n=>Ml(n,Wb),jA=n=>Ml(n,Jb),oy=n=>Ml(n,Qb),DA=n=>Ml(n,Zb),MA=n=>Ml(n,Kb),hc=n=>Ml(n,ex,!0),zA=n=>Ml(n,$b,!0),Za=(n,l,r)=>{const o=Fb.exec(n);return o?o[1]?l(o[1]):r(o[2]):!1},Ml=(n,l,r=!1)=>{const o=Xb.exec(n);return o?o[1]?l(o[1]):r:!1},Qb=n=>n==="position"||n==="percentage",Kb=n=>n==="image"||n==="url",Zb=n=>n==="length"||n==="size"||n==="bg-size",Wb=n=>n==="length",kA=n=>n==="number",Jb=n=>n==="family-name",$b=n=>n==="number"||n==="weight",ex=n=>n==="shadow",LA=()=>{const n=mt("color"),l=mt("font"),r=mt("text"),o=mt("font-weight"),c=mt("tracking"),u=mt("leading"),d=mt("breakpoint"),p=mt("container"),h=mt("spacing"),m=mt("radius"),v=mt("shadow"),y=mt("inset-shadow"),w=mt("text-shadow"),_=mt("drop-shadow"),E=mt("blur"),S=mt("perspective"),A=mt("aspect"),T=mt("ease"),O=mt("animate"),j=()=>["auto","avoid","all","avoid-page","page","left","right","column"],z=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],k=()=>[...z(),me,fe],Y=()=>["auto","hidden","clip","visible","scroll"],U=()=>["auto","contain","none"],I=()=>[me,fe,h],ae=()=>[Pa,"full","auto",...I()],ce=()=>[Ga,"none","subgrid",me,fe],H=()=>["auto",{span:["full",Ga,me,fe]},Ga,me,fe],le=()=>[Ga,"auto",me,fe],ve=()=>["auto","min","max","fr",me,fe],re=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],de=()=>["start","end","center","stretch","center-safe","end-safe"],M=()=>["auto",...I()],Q=()=>[Pa,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...I()],W=()=>[Pa,"screen","full","dvw","lvw","svw","min","max","fit",...I()],ee=()=>[Pa,"screen","full","lh","dvh","lvh","svh","min","max","fit",...I()],J=()=>[n,me,fe],N=()=>[...z(),oy,ry,{position:[me,fe]}],F=()=>["no-repeat",{repeat:["","x","y","space","round"]}],te=()=>["auto","cover","contain",DA,TA,{size:[me,fe]}],ne=()=>[Uf,kr,bl],ie=()=>["","none","full",m,me,fe],se=()=>["",Ae,kr,bl],$=()=>["solid","dashed","dotted","double"],Se=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],pe=()=>[Ae,Uf,oy,ry],Oe=()=>["","none",E,me,fe],Ce=()=>["none",Ae,me,fe],ke=()=>["none",Ae,me,fe],Ke=()=>[Ae,me,fe],nt=()=>[Pa,"full",...I()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[oa],breakpoint:[oa],color:[Ib],container:[oa],"drop-shadow":[oa],ease:["in","out","in-out"],font:[AA],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[oa],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[oa],shadow:[oa],spacing:["px",Ae],text:[oa],"text-shadow":[oa],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",Pa,fe,me,A]}],container:["container"],columns:[{columns:[Ae,fe,me,p]}],"break-after":[{"break-after":j()}],"break-before":[{"break-before":j()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:k()}],overflow:[{overflow:Y()}],"overflow-x":[{"overflow-x":Y()}],"overflow-y":[{"overflow-y":Y()}],overscroll:[{overscroll:U()}],"overscroll-x":[{"overscroll-x":U()}],"overscroll-y":[{"overscroll-y":U()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:ae()}],"inset-x":[{"inset-x":ae()}],"inset-y":[{"inset-y":ae()}],start:[{"inset-s":ae(),start:ae()}],end:[{"inset-e":ae(),end:ae()}],"inset-bs":[{"inset-bs":ae()}],"inset-be":[{"inset-be":ae()}],top:[{top:ae()}],right:[{right:ae()}],bottom:[{bottom:ae()}],left:[{left:ae()}],visibility:["visible","invisible","collapse"],z:[{z:[Ga,"auto",me,fe]}],basis:[{basis:[Pa,"full","auto",p,...I()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[Ae,Pa,"auto","initial","none",fe]}],grow:[{grow:["",Ae,me,fe]}],shrink:[{shrink:["",Ae,me,fe]}],order:[{order:[Ga,"first","last","none",me,fe]}],"grid-cols":[{"grid-cols":ce()}],"col-start-end":[{col:H()}],"col-start":[{"col-start":le()}],"col-end":[{"col-end":le()}],"grid-rows":[{"grid-rows":ce()}],"row-start-end":[{row:H()}],"row-start":[{"row-start":le()}],"row-end":[{"row-end":le()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":ve()}],"auto-rows":[{"auto-rows":ve()}],gap:[{gap:I()}],"gap-x":[{"gap-x":I()}],"gap-y":[{"gap-y":I()}],"justify-content":[{justify:[...re(),"normal"]}],"justify-items":[{"justify-items":[...de(),"normal"]}],"justify-self":[{"justify-self":["auto",...de()]}],"align-content":[{content:["normal",...re()]}],"align-items":[{items:[...de(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...de(),{baseline:["","last"]}]}],"place-content":[{"place-content":re()}],"place-items":[{"place-items":[...de(),"baseline"]}],"place-self":[{"place-self":["auto",...de()]}],p:[{p:I()}],px:[{px:I()}],py:[{py:I()}],ps:[{ps:I()}],pe:[{pe:I()}],pbs:[{pbs:I()}],pbe:[{pbe:I()}],pt:[{pt:I()}],pr:[{pr:I()}],pb:[{pb:I()}],pl:[{pl:I()}],m:[{m:M()}],mx:[{mx:M()}],my:[{my:M()}],ms:[{ms:M()}],me:[{me:M()}],mbs:[{mbs:M()}],mbe:[{mbe:M()}],mt:[{mt:M()}],mr:[{mr:M()}],mb:[{mb:M()}],ml:[{ml:M()}],"space-x":[{"space-x":I()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":I()}],"space-y-reverse":["space-y-reverse"],size:[{size:Q()}],"inline-size":[{inline:["auto",...W()]}],"min-inline-size":[{"min-inline":["auto",...W()]}],"max-inline-size":[{"max-inline":["none",...W()]}],"block-size":[{block:["auto",...ee()]}],"min-block-size":[{"min-block":["auto",...ee()]}],"max-block-size":[{"max-block":["none",...ee()]}],w:[{w:[p,"screen",...Q()]}],"min-w":[{"min-w":[p,"screen","none",...Q()]}],"max-w":[{"max-w":[p,"screen","none","prose",{screen:[d]},...Q()]}],h:[{h:["screen","lh",...Q()]}],"min-h":[{"min-h":["screen","lh","none",...Q()]}],"max-h":[{"max-h":["screen","lh",...Q()]}],"font-size":[{text:["base",r,kr,bl]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[o,zA,OA]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",Uf,fe]}],"font-family":[{font:[jA,RA,l]}],"font-features":[{"font-features":[fe]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:[c,me,fe]}],"line-clamp":[{"line-clamp":[Ae,"none",me,iy]}],leading:[{leading:[u,...I()]}],"list-image":[{"list-image":["none",me,fe]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",me,fe]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:J()}],"text-color":[{text:J()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...$(),"wavy"]}],"text-decoration-thickness":[{decoration:[Ae,"from-font","auto",me,bl]}],"text-decoration-color":[{decoration:J()}],"underline-offset":[{"underline-offset":[Ae,"auto",me,fe]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:I()}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",me,fe]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],wrap:[{wrap:["break-word","anywhere","normal"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",me,fe]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:N()}],"bg-repeat":[{bg:F()}],"bg-size":[{bg:te()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},Ga,me,fe],radial:["",me,fe],conic:[Ga,me,fe]},MA,NA]}],"bg-color":[{bg:J()}],"gradient-from-pos":[{from:ne()}],"gradient-via-pos":[{via:ne()}],"gradient-to-pos":[{to:ne()}],"gradient-from":[{from:J()}],"gradient-via":[{via:J()}],"gradient-to":[{to:J()}],rounded:[{rounded:ie()}],"rounded-s":[{"rounded-s":ie()}],"rounded-e":[{"rounded-e":ie()}],"rounded-t":[{"rounded-t":ie()}],"rounded-r":[{"rounded-r":ie()}],"rounded-b":[{"rounded-b":ie()}],"rounded-l":[{"rounded-l":ie()}],"rounded-ss":[{"rounded-ss":ie()}],"rounded-se":[{"rounded-se":ie()}],"rounded-ee":[{"rounded-ee":ie()}],"rounded-es":[{"rounded-es":ie()}],"rounded-tl":[{"rounded-tl":ie()}],"rounded-tr":[{"rounded-tr":ie()}],"rounded-br":[{"rounded-br":ie()}],"rounded-bl":[{"rounded-bl":ie()}],"border-w":[{border:se()}],"border-w-x":[{"border-x":se()}],"border-w-y":[{"border-y":se()}],"border-w-s":[{"border-s":se()}],"border-w-e":[{"border-e":se()}],"border-w-bs":[{"border-bs":se()}],"border-w-be":[{"border-be":se()}],"border-w-t":[{"border-t":se()}],"border-w-r":[{"border-r":se()}],"border-w-b":[{"border-b":se()}],"border-w-l":[{"border-l":se()}],"divide-x":[{"divide-x":se()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":se()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...$(),"hidden","none"]}],"divide-style":[{divide:[...$(),"hidden","none"]}],"border-color":[{border:J()}],"border-color-x":[{"border-x":J()}],"border-color-y":[{"border-y":J()}],"border-color-s":[{"border-s":J()}],"border-color-e":[{"border-e":J()}],"border-color-bs":[{"border-bs":J()}],"border-color-be":[{"border-be":J()}],"border-color-t":[{"border-t":J()}],"border-color-r":[{"border-r":J()}],"border-color-b":[{"border-b":J()}],"border-color-l":[{"border-l":J()}],"divide-color":[{divide:J()}],"outline-style":[{outline:[...$(),"none","hidden"]}],"outline-offset":[{"outline-offset":[Ae,me,fe]}],"outline-w":[{outline:["",Ae,kr,bl]}],"outline-color":[{outline:J()}],shadow:[{shadow:["","none",v,hc,mc]}],"shadow-color":[{shadow:J()}],"inset-shadow":[{"inset-shadow":["none",y,hc,mc]}],"inset-shadow-color":[{"inset-shadow":J()}],"ring-w":[{ring:se()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:J()}],"ring-offset-w":[{"ring-offset":[Ae,bl]}],"ring-offset-color":[{"ring-offset":J()}],"inset-ring-w":[{"inset-ring":se()}],"inset-ring-color":[{"inset-ring":J()}],"text-shadow":[{"text-shadow":["none",w,hc,mc]}],"text-shadow-color":[{"text-shadow":J()}],opacity:[{opacity:[Ae,me,fe]}],"mix-blend":[{"mix-blend":[...Se(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":Se()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[Ae]}],"mask-image-linear-from-pos":[{"mask-linear-from":pe()}],"mask-image-linear-to-pos":[{"mask-linear-to":pe()}],"mask-image-linear-from-color":[{"mask-linear-from":J()}],"mask-image-linear-to-color":[{"mask-linear-to":J()}],"mask-image-t-from-pos":[{"mask-t-from":pe()}],"mask-image-t-to-pos":[{"mask-t-to":pe()}],"mask-image-t-from-color":[{"mask-t-from":J()}],"mask-image-t-to-color":[{"mask-t-to":J()}],"mask-image-r-from-pos":[{"mask-r-from":pe()}],"mask-image-r-to-pos":[{"mask-r-to":pe()}],"mask-image-r-from-color":[{"mask-r-from":J()}],"mask-image-r-to-color":[{"mask-r-to":J()}],"mask-image-b-from-pos":[{"mask-b-from":pe()}],"mask-image-b-to-pos":[{"mask-b-to":pe()}],"mask-image-b-from-color":[{"mask-b-from":J()}],"mask-image-b-to-color":[{"mask-b-to":J()}],"mask-image-l-from-pos":[{"mask-l-from":pe()}],"mask-image-l-to-pos":[{"mask-l-to":pe()}],"mask-image-l-from-color":[{"mask-l-from":J()}],"mask-image-l-to-color":[{"mask-l-to":J()}],"mask-image-x-from-pos":[{"mask-x-from":pe()}],"mask-image-x-to-pos":[{"mask-x-to":pe()}],"mask-image-x-from-color":[{"mask-x-from":J()}],"mask-image-x-to-color":[{"mask-x-to":J()}],"mask-image-y-from-pos":[{"mask-y-from":pe()}],"mask-image-y-to-pos":[{"mask-y-to":pe()}],"mask-image-y-from-color":[{"mask-y-from":J()}],"mask-image-y-to-color":[{"mask-y-to":J()}],"mask-image-radial":[{"mask-radial":[me,fe]}],"mask-image-radial-from-pos":[{"mask-radial-from":pe()}],"mask-image-radial-to-pos":[{"mask-radial-to":pe()}],"mask-image-radial-from-color":[{"mask-radial-from":J()}],"mask-image-radial-to-color":[{"mask-radial-to":J()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":z()}],"mask-image-conic-pos":[{"mask-conic":[Ae]}],"mask-image-conic-from-pos":[{"mask-conic-from":pe()}],"mask-image-conic-to-pos":[{"mask-conic-to":pe()}],"mask-image-conic-from-color":[{"mask-conic-from":J()}],"mask-image-conic-to-color":[{"mask-conic-to":J()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:N()}],"mask-repeat":[{mask:F()}],"mask-size":[{mask:te()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",me,fe]}],filter:[{filter:["","none",me,fe]}],blur:[{blur:Oe()}],brightness:[{brightness:[Ae,me,fe]}],contrast:[{contrast:[Ae,me,fe]}],"drop-shadow":[{"drop-shadow":["","none",_,hc,mc]}],"drop-shadow-color":[{"drop-shadow":J()}],grayscale:[{grayscale:["",Ae,me,fe]}],"hue-rotate":[{"hue-rotate":[Ae,me,fe]}],invert:[{invert:["",Ae,me,fe]}],saturate:[{saturate:[Ae,me,fe]}],sepia:[{sepia:["",Ae,me,fe]}],"backdrop-filter":[{"backdrop-filter":["","none",me,fe]}],"backdrop-blur":[{"backdrop-blur":Oe()}],"backdrop-brightness":[{"backdrop-brightness":[Ae,me,fe]}],"backdrop-contrast":[{"backdrop-contrast":[Ae,me,fe]}],"backdrop-grayscale":[{"backdrop-grayscale":["",Ae,me,fe]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[Ae,me,fe]}],"backdrop-invert":[{"backdrop-invert":["",Ae,me,fe]}],"backdrop-opacity":[{"backdrop-opacity":[Ae,me,fe]}],"backdrop-saturate":[{"backdrop-saturate":[Ae,me,fe]}],"backdrop-sepia":[{"backdrop-sepia":["",Ae,me,fe]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":I()}],"border-spacing-x":[{"border-spacing-x":I()}],"border-spacing-y":[{"border-spacing-y":I()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",me,fe]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[Ae,"initial",me,fe]}],ease:[{ease:["linear","initial",T,me,fe]}],delay:[{delay:[Ae,me,fe]}],animate:[{animate:["none",O,me,fe]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[S,me,fe]}],"perspective-origin":[{"perspective-origin":k()}],rotate:[{rotate:Ce()}],"rotate-x":[{"rotate-x":Ce()}],"rotate-y":[{"rotate-y":Ce()}],"rotate-z":[{"rotate-z":Ce()}],scale:[{scale:ke()}],"scale-x":[{"scale-x":ke()}],"scale-y":[{"scale-y":ke()}],"scale-z":[{"scale-z":ke()}],"scale-3d":["scale-3d"],skew:[{skew:Ke()}],"skew-x":[{"skew-x":Ke()}],"skew-y":[{"skew-y":Ke()}],transform:[{transform:[me,fe,"","none","gpu","cpu"]}],"transform-origin":[{origin:k()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:nt()}],"translate-x":[{"translate-x":nt()}],"translate-y":[{"translate-y":nt()}],"translate-z":[{"translate-z":nt()}],"translate-none":["translate-none"],accent:[{accent:J()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:J()}],"color-scheme":[{scheme:["normal","dark","light","light-dark","only-dark","only-light"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",me,fe]}],"field-sizing":[{"field-sizing":["fixed","content"]}],"pointer-events":[{"pointer-events":["auto","none"]}],resize:[{resize:["none","","y","x"]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scroll-m":[{"scroll-m":I()}],"scroll-mx":[{"scroll-mx":I()}],"scroll-my":[{"scroll-my":I()}],"scroll-ms":[{"scroll-ms":I()}],"scroll-me":[{"scroll-me":I()}],"scroll-mbs":[{"scroll-mbs":I()}],"scroll-mbe":[{"scroll-mbe":I()}],"scroll-mt":[{"scroll-mt":I()}],"scroll-mr":[{"scroll-mr":I()}],"scroll-mb":[{"scroll-mb":I()}],"scroll-ml":[{"scroll-ml":I()}],"scroll-p":[{"scroll-p":I()}],"scroll-px":[{"scroll-px":I()}],"scroll-py":[{"scroll-py":I()}],"scroll-ps":[{"scroll-ps":I()}],"scroll-pe":[{"scroll-pe":I()}],"scroll-pbs":[{"scroll-pbs":I()}],"scroll-pbe":[{"scroll-pbe":I()}],"scroll-pt":[{"scroll-pt":I()}],"scroll-pr":[{"scroll-pr":I()}],"scroll-pb":[{"scroll-pb":I()}],"scroll-pl":[{"scroll-pl":I()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",me,fe]}],fill:[{fill:["none",...J()]}],"stroke-w":[{stroke:[Ae,kr,bl,iy]}],stroke:[{stroke:["none",...J()]}],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","inset-bs","inset-be","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pbs","pbe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mbs","mbe","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-x","border-w-y","border-w-s","border-w-e","border-w-bs","border-w-be","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-x","border-color-y","border-color-s","border-color-e","border-color-bs","border-color-be","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],translate:["translate-x","translate-y","translate-none"],"translate-none":["translate","translate-x","translate-y","translate-z"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mbs","scroll-mbe","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pbs","scroll-pbe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]},orderSensitiveModifiers:["*","**","after","backdrop","before","details-content","file","first-letter","first-line","marker","placeholder","selection"]}},UA=hA(LA);function Be(...n){return UA(Bb(n))}const HA=qb("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm font-medium transition-[color,background-color,border-color,box-shadow,transform] duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-clay/25 disabled:pointer-events-none disabled:opacity-45 [&_svg]:pointer-events-none [&_svg]:shrink-0",{variants:{variant:{default:"bg-ink text-paper shadow-[0_10px_30px_-18px_color-mix(in_oklab,var(--color-ink)_48%,transparent)] hover:-translate-y-0.5 hover:bg-ink/92",secondary:"bg-sand text-ink hover:bg-oat",outline:"border border-line bg-paper/90 text-ink hover:border-clay/40 hover:bg-paper",ghost:"text-muted hover:bg-sand hover:text-ink",destructive:"bg-clay text-paper hover:bg-clay-strong"},size:{default:"h-11 px-5",sm:"h-9 px-4 text-sm",lg:"h-12 px-6",icon:"h-10 w-10"}},defaultVariants:{variant:"default",size:"default"}}),Tl=x.forwardRef(({className:n,variant:l,size:r,asChild:o=!1,...c},u)=>{const d=o?GC:"button";return b.jsx(d,{className:Be(HA({variant:l,size:r,className:n})),ref:u,...c})});Tl.displayName="Button";var Kr=Od();const BA=Gr(Kr);var qA=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","select","span","svg","ul"],VA=qA.reduce((n,l)=>{const r=Ub(`Primitive.${l}`),o=x.forwardRef((c,u)=>{const{asChild:d,...p}=c,h=d?r:l;return typeof window<"u"&&(window[Symbol.for("radix-ui")]=!0),b.jsx(h,{...p,ref:u})});return o.displayName=`Primitive.${l}`,{...n,[l]:o}},{}),PA="Label",tx=x.forwardRef((n,l)=>b.jsx(VA.label,{...n,ref:l,onMouseDown:r=>{r.target.closest("button, input, select, textarea")||(n.onMouseDown?.(r),!r.defaultPrevented&&r.detail>1&&r.preventDefault())}}));tx.displayName=PA;var nx=tx;const Ei=x.forwardRef(({className:n,...l},r)=>b.jsx(nx,{ref:r,className:Be("text-sm font-medium text-ink",n),...l}));Ei.displayName=nx.displayName;function sd(n,[l,r]){return Math.min(r,Math.max(l,n))}function ze(n,l,{checkForDefaultPrevented:r=!0}={}){return function(c){if(n?.(c),r===!1||!c.defaultPrevented)return l?.(c)}}function GA(n,l){const r=x.createContext(l),o=u=>{const{children:d,...p}=u,h=x.useMemo(()=>p,Object.values(p));return b.jsx(r.Provider,{value:h,children:d})};o.displayName=n+"Provider";function c(u){const d=x.useContext(r);if(d)return d;if(l!==void 0)return l;throw new Error(`\`${u}\` must be used within \`${n}\``)}return[o,c]}function Wa(n,l=[]){let r=[];function o(u,d){const p=x.createContext(d),h=r.length;r=[...r,d];const m=y=>{const{scope:w,children:_,...E}=y,S=w?.[n]?.[h]||p,A=x.useMemo(()=>E,Object.values(E));return b.jsx(S.Provider,{value:A,children:_})};m.displayName=u+"Provider";function v(y,w){const _=w?.[n]?.[h]||p,E=x.useContext(_);if(E)return E;if(d!==void 0)return d;throw new Error(`\`${y}\` must be used within \`${u}\``)}return[m,v]}const c=()=>{const u=r.map(d=>x.createContext(d));return function(p){const h=p?.[n]||u;return x.useMemo(()=>({[`__scope${n}`]:{...p,[n]:h}}),[p,h])}};return c.scopeName=n,[o,YA(c,...l)]}function YA(...n){const l=n[0];if(n.length===1)return l;const r=()=>{const o=n.map(c=>({useScope:c(),scopeName:c.scopeName}));return function(u){const d=o.reduce((p,{useScope:h,scopeName:m})=>{const y=h(u)[`__scope${m}`];return{...p,...y}},{});return x.useMemo(()=>({[`__scope${l.scopeName}`]:d}),[d])}};return r.scopeName=l.scopeName,r}function cy(n){const l=FA(n),r=x.forwardRef((o,c)=>{const{children:u,...d}=o,p=x.Children.toArray(u),h=p.find(IA);if(h){const m=h.props.children,v=p.map(y=>y===h?x.Children.count(m)>1?x.Children.only(null):x.isValidElement(m)?m.props.children:null:y);return b.jsx(l,{...d,ref:c,children:x.isValidElement(m)?x.cloneElement(m,void 0,v):null})}return b.jsx(l,{...d,ref:c,children:u})});return r.displayName=`${n}.Slot`,r}function FA(n){const l=x.forwardRef((r,o)=>{const{children:c,...u}=r;if(x.isValidElement(c)){const d=KA(c),p=QA(u,c.props);return c.type!==x.Fragment&&(p.ref=o?Mi(o,d):d),x.cloneElement(c,p)}return x.Children.count(c)>1?x.Children.only(null):null});return l.displayName=`${n}.SlotClone`,l}var XA=Symbol("radix.slottable");function IA(n){return x.isValidElement(n)&&typeof n.type=="function"&&"__radixId"in n.type&&n.type.__radixId===XA}function QA(n,l){const r={...l};for(const o in l){const c=n[o],u=l[o];/^on[A-Z]/.test(o)?c&&u?r[o]=(...p)=>{const h=u(...p);return c(...p),h}:c&&(r[o]=c):o==="style"?r[o]={...c,...u}:o==="className"&&(r[o]=[c,u].filter(Boolean).join(" "))}return{...n,...r}}function KA(n){let l=Object.getOwnPropertyDescriptor(n.props,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning;return r?n.ref:(l=Object.getOwnPropertyDescriptor(n,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning,r?n.props.ref:n.props.ref||n.ref)}function ax(n){const l=n+"CollectionProvider",[r,o]=Wa(l),[c,u]=r(l,{collectionRef:{current:null},itemMap:new Map}),d=S=>{const{scope:A,children:T}=S,O=Qe.useRef(null),j=Qe.useRef(new Map).current;return b.jsx(c,{scope:A,itemMap:j,collectionRef:O,children:T})};d.displayName=l;const p=n+"CollectionSlot",h=cy(p),m=Qe.forwardRef((S,A)=>{const{scope:T,children:O}=S,j=u(p,T),z=qe(A,j.collectionRef);return b.jsx(h,{ref:z,children:O})});m.displayName=p;const v=n+"CollectionItemSlot",y="data-radix-collection-item",w=cy(v),_=Qe.forwardRef((S,A)=>{const{scope:T,children:O,...j}=S,z=Qe.useRef(null),k=qe(A,z),Y=u(v,T);return Qe.useEffect(()=>(Y.itemMap.set(z,{ref:z,...j}),()=>{Y.itemMap.delete(z)})),b.jsx(w,{[y]:"",ref:k,children:O})});_.displayName=v;function E(S){const A=u(n+"CollectionConsumer",S);return Qe.useCallback(()=>{const O=A.collectionRef.current;if(!O)return[];const j=Array.from(O.querySelectorAll(`[${y}]`));return Array.from(A.itemMap.values()).sort((Y,U)=>j.indexOf(Y.ref.current)-j.indexOf(U.ref.current))},[A.collectionRef,A.itemMap])}return[{Provider:d,Slot:m,ItemSlot:_},E,o]}var ZA=x.createContext(void 0);function Hd(n){const l=x.useContext(ZA);return n||l||"ltr"}function WA(n){const l=JA(n),r=x.forwardRef((o,c)=>{const{children:u,...d}=o,p=x.Children.toArray(u),h=p.find(e2);if(h){const m=h.props.children,v=p.map(y=>y===h?x.Children.count(m)>1?x.Children.only(null):x.isValidElement(m)?m.props.children:null:y);return b.jsx(l,{...d,ref:c,children:x.isValidElement(m)?x.cloneElement(m,void 0,v):null})}return b.jsx(l,{...d,ref:c,children:u})});return r.displayName=`${n}.Slot`,r}function JA(n){const l=x.forwardRef((r,o)=>{const{children:c,...u}=r;if(x.isValidElement(c)){const d=n2(c),p=t2(u,c.props);return c.type!==x.Fragment&&(p.ref=o?Mi(o,d):d),x.cloneElement(c,p)}return x.Children.count(c)>1?x.Children.only(null):null});return l.displayName=`${n}.SlotClone`,l}var $A=Symbol("radix.slottable");function e2(n){return x.isValidElement(n)&&typeof n.type=="function"&&"__radixId"in n.type&&n.type.__radixId===$A}function t2(n,l){const r={...l};for(const o in l){const c=n[o],u=l[o];/^on[A-Z]/.test(o)?c&&u?r[o]=(...p)=>{const h=u(...p);return c(...p),h}:c&&(r[o]=c):o==="style"?r[o]={...c,...u}:o==="className"&&(r[o]=[c,u].filter(Boolean).join(" "))}return{...n,...r}}function n2(n){let l=Object.getOwnPropertyDescriptor(n.props,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning;return r?n.ref:(l=Object.getOwnPropertyDescriptor(n,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning,r?n.props.ref:n.props.ref||n.ref)}var a2=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","select","span","svg","ul"],Te=a2.reduce((n,l)=>{const r=WA(`Primitive.${l}`),o=x.forwardRef((c,u)=>{const{asChild:d,...p}=c,h=d?r:l;return typeof window<"u"&&(window[Symbol.for("radix-ui")]=!0),b.jsx(h,{...p,ref:u})});return o.displayName=`Primitive.${l}`,{...n,[l]:o}},{});function l2(n,l){n&&Kr.flushSync(()=>n.dispatchEvent(l))}function Bt(n){const l=x.useRef(n);return x.useEffect(()=>{l.current=n}),x.useMemo(()=>(...r)=>l.current?.(...r),[])}function i2(n,l=globalThis?.document){const r=Bt(n);x.useEffect(()=>{const o=c=>{c.key==="Escape"&&r(c)};return l.addEventListener("keydown",o,{capture:!0}),()=>l.removeEventListener("keydown",o,{capture:!0})},[r,l])}var r2="DismissableLayer",ud="dismissableLayer.update",o2="dismissableLayer.pointerDownOutside",c2="dismissableLayer.focusOutside",sy,lx=x.createContext({layers:new Set,layersWithOutsidePointerEventsDisabled:new Set,branches:new Set}),Bd=x.forwardRef((n,l)=>{const{disableOutsidePointerEvents:r=!1,onEscapeKeyDown:o,onPointerDownOutside:c,onFocusOutside:u,onInteractOutside:d,onDismiss:p,...h}=n,m=x.useContext(lx),[v,y]=x.useState(null),w=v?.ownerDocument??globalThis?.document,[,_]=x.useState({}),E=qe(l,U=>y(U)),S=Array.from(m.layers),[A]=[...m.layersWithOutsidePointerEventsDisabled].slice(-1),T=S.indexOf(A),O=v?S.indexOf(v):-1,j=m.layersWithOutsidePointerEventsDisabled.size>0,z=O>=T,k=f2(U=>{const I=U.target,ae=[...m.branches].some(ce=>ce.contains(I));!z||ae||(c?.(U),d?.(U),U.defaultPrevented||p?.())},w),Y=d2(U=>{const I=U.target;[...m.branches].some(ce=>ce.contains(I))||(u?.(U),d?.(U),U.defaultPrevented||p?.())},w);return i2(U=>{O===m.layers.size-1&&(o?.(U),!U.defaultPrevented&&p&&(U.preventDefault(),p()))},w),x.useEffect(()=>{if(v)return r&&(m.layersWithOutsidePointerEventsDisabled.size===0&&(sy=w.body.style.pointerEvents,w.body.style.pointerEvents="none"),m.layersWithOutsidePointerEventsDisabled.add(v)),m.layers.add(v),uy(),()=>{r&&m.layersWithOutsidePointerEventsDisabled.size===1&&(w.body.style.pointerEvents=sy)}},[v,w,r,m]),x.useEffect(()=>()=>{v&&(m.layers.delete(v),m.layersWithOutsidePointerEventsDisabled.delete(v),uy())},[v,m]),x.useEffect(()=>{const U=()=>_({});return document.addEventListener(ud,U),()=>document.removeEventListener(ud,U)},[]),b.jsx(Te.div,{...h,ref:E,style:{pointerEvents:j?z?"auto":"none":void 0,...n.style},onFocusCapture:ze(n.onFocusCapture,Y.onFocusCapture),onBlurCapture:ze(n.onBlurCapture,Y.onBlurCapture),onPointerDownCapture:ze(n.onPointerDownCapture,k.onPointerDownCapture)})});Bd.displayName=r2;var s2="DismissableLayerBranch",u2=x.forwardRef((n,l)=>{const r=x.useContext(lx),o=x.useRef(null),c=qe(l,o);return x.useEffect(()=>{const u=o.current;if(u)return r.branches.add(u),()=>{r.branches.delete(u)}},[r.branches]),b.jsx(Te.div,{...n,ref:c})});u2.displayName=s2;function f2(n,l=globalThis?.document){const r=Bt(n),o=x.useRef(!1),c=x.useRef(()=>{});return x.useEffect(()=>{const u=p=>{if(p.target&&!o.current){let h=function(){ix(o2,r,m,{discrete:!0})};const m={originalEvent:p};p.pointerType==="touch"?(l.removeEventListener("click",c.current),c.current=h,l.addEventListener("click",c.current,{once:!0})):h()}else l.removeEventListener("click",c.current);o.current=!1},d=window.setTimeout(()=>{l.addEventListener("pointerdown",u)},0);return()=>{window.clearTimeout(d),l.removeEventListener("pointerdown",u),l.removeEventListener("click",c.current)}},[l,r]),{onPointerDownCapture:()=>o.current=!0}}function d2(n,l=globalThis?.document){const r=Bt(n),o=x.useRef(!1);return x.useEffect(()=>{const c=u=>{u.target&&!o.current&&ix(c2,r,{originalEvent:u},{discrete:!1})};return l.addEventListener("focusin",c),()=>l.removeEventListener("focusin",c)},[l,r]),{onFocusCapture:()=>o.current=!0,onBlurCapture:()=>o.current=!1}}function uy(){const n=new CustomEvent(ud);document.dispatchEvent(n)}function ix(n,l,r,{discrete:o}){const c=r.originalEvent.target,u=new CustomEvent(n,{bubbles:!1,cancelable:!0,detail:r});l&&c.addEventListener(n,l,{once:!0}),o?l2(c,u):c.dispatchEvent(u)}var Hf=0;function rx(){x.useEffect(()=>{const n=document.querySelectorAll("[data-radix-focus-guard]");return document.body.insertAdjacentElement("afterbegin",n[0]??fy()),document.body.insertAdjacentElement("beforeend",n[1]??fy()),Hf++,()=>{Hf===1&&document.querySelectorAll("[data-radix-focus-guard]").forEach(l=>l.remove()),Hf--}},[])}function fy(){const n=document.createElement("span");return n.setAttribute("data-radix-focus-guard",""),n.tabIndex=0,n.style.outline="none",n.style.opacity="0",n.style.position="fixed",n.style.pointerEvents="none",n}var Bf="focusScope.autoFocusOnMount",qf="focusScope.autoFocusOnUnmount",dy={bubbles:!1,cancelable:!0},p2="FocusScope",qd=x.forwardRef((n,l)=>{const{loop:r=!1,trapped:o=!1,onMountAutoFocus:c,onUnmountAutoFocus:u,...d}=n,[p,h]=x.useState(null),m=Bt(c),v=Bt(u),y=x.useRef(null),w=qe(l,S=>h(S)),_=x.useRef({paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}}).current;x.useEffect(()=>{if(o){let S=function(j){if(_.paused||!p)return;const z=j.target;p.contains(z)?y.current=z:Fa(y.current,{select:!0})},A=function(j){if(_.paused||!p)return;const z=j.relatedTarget;z!==null&&(p.contains(z)||Fa(y.current,{select:!0}))},T=function(j){if(document.activeElement===document.body)for(const k of j)k.removedNodes.length>0&&Fa(p)};document.addEventListener("focusin",S),document.addEventListener("focusout",A);const O=new MutationObserver(T);return p&&O.observe(p,{childList:!0,subtree:!0}),()=>{document.removeEventListener("focusin",S),document.removeEventListener("focusout",A),O.disconnect()}}},[o,p,_.paused]),x.useEffect(()=>{if(p){my.add(_);const S=document.activeElement;if(!p.contains(S)){const T=new CustomEvent(Bf,dy);p.addEventListener(Bf,m),p.dispatchEvent(T),T.defaultPrevented||(m2(b2(ox(p)),{select:!0}),document.activeElement===S&&Fa(p))}return()=>{p.removeEventListener(Bf,m),setTimeout(()=>{const T=new CustomEvent(qf,dy);p.addEventListener(qf,v),p.dispatchEvent(T),T.defaultPrevented||Fa(S??document.body,{select:!0}),p.removeEventListener(qf,v),my.remove(_)},0)}}},[p,m,v,_]);const E=x.useCallback(S=>{if(!r&&!o||_.paused)return;const A=S.key==="Tab"&&!S.altKey&&!S.ctrlKey&&!S.metaKey,T=document.activeElement;if(A&&T){const O=S.currentTarget,[j,z]=h2(O);j&&z?!S.shiftKey&&T===z?(S.preventDefault(),r&&Fa(j,{select:!0})):S.shiftKey&&T===j&&(S.preventDefault(),r&&Fa(z,{select:!0})):T===O&&S.preventDefault()}},[r,o,_.paused]);return b.jsx(Te.div,{tabIndex:-1,...d,ref:w,onKeyDown:E})});qd.displayName=p2;function m2(n,{select:l=!1}={}){const r=document.activeElement;for(const o of n)if(Fa(o,{select:l}),document.activeElement!==r)return}function h2(n){const l=ox(n),r=py(l,n),o=py(l.reverse(),n);return[r,o]}function ox(n){const l=[],r=document.createTreeWalker(n,NodeFilter.SHOW_ELEMENT,{acceptNode:o=>{const c=o.tagName==="INPUT"&&o.type==="hidden";return o.disabled||o.hidden||c?NodeFilter.FILTER_SKIP:o.tabIndex>=0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;r.nextNode();)l.push(r.currentNode);return l}function py(n,l){for(const r of n)if(!v2(r,{upTo:l}))return r}function v2(n,{upTo:l}){if(getComputedStyle(n).visibility==="hidden")return!0;for(;n;){if(l!==void 0&&n===l)return!1;if(getComputedStyle(n).display==="none")return!0;n=n.parentElement}return!1}function g2(n){return n instanceof HTMLInputElement&&"select"in n}function Fa(n,{select:l=!1}={}){if(n&&n.focus){const r=document.activeElement;n.focus({preventScroll:!0}),n!==r&&g2(n)&&l&&n.select()}}var my=y2();function y2(){let n=[];return{add(l){const r=n[0];l!==r&&r?.pause(),n=hy(n,l),n.unshift(l)},remove(l){n=hy(n,l),n[0]?.resume()}}}function hy(n,l){const r=[...n],o=r.indexOf(l);return o!==-1&&r.splice(o,1),r}function b2(n){return n.filter(l=>l.tagName!=="A")}var yt=globalThis?.document?x.useLayoutEffect:()=>{},x2=Td[" useId ".trim().toString()]||(()=>{}),S2=0;function Xa(n){const[l,r]=x.useState(x2());return yt(()=>{r(o=>o??String(S2++))},[n]),l?`radix-${l}`:""}const w2=["top","right","bottom","left"],Qa=Math.min,Jt=Math.max,zc=Math.round,vc=Math.floor,Ln=n=>({x:n,y:n}),E2={left:"right",right:"left",bottom:"top",top:"bottom"},_2={start:"end",end:"start"};function fd(n,l,r){return Jt(n,Qa(l,r))}function fa(n,l){return typeof n=="function"?n(l):n}function da(n){return n.split("-")[0]}function zi(n){return n.split("-")[1]}function Vd(n){return n==="x"?"y":"x"}function Pd(n){return n==="y"?"height":"width"}const C2=new Set(["top","bottom"]);function kn(n){return C2.has(da(n))?"y":"x"}function Gd(n){return Vd(kn(n))}function A2(n,l,r){r===void 0&&(r=!1);const o=zi(n),c=Gd(n),u=Pd(c);let d=c==="x"?o===(r?"end":"start")?"right":"left":o==="start"?"bottom":"top";return l.reference[u]>l.floating[u]&&(d=kc(d)),[d,kc(d)]}function T2(n){const l=kc(n);return[dd(n),l,dd(l)]}function dd(n){return n.replace(/start|end/g,l=>_2[l])}const vy=["left","right"],gy=["right","left"],O2=["top","bottom"],R2=["bottom","top"];function N2(n,l,r){switch(n){case"top":case"bottom":return r?l?gy:vy:l?vy:gy;case"left":case"right":return l?O2:R2;default:return[]}}function j2(n,l,r,o){const c=zi(n);let u=N2(da(n),r==="start",o);return c&&(u=u.map(d=>d+"-"+c),l&&(u=u.concat(u.map(dd)))),u}function kc(n){return n.replace(/left|right|bottom|top/g,l=>E2[l])}function D2(n){return{top:0,right:0,bottom:0,left:0,...n}}function cx(n){return typeof n!="number"?D2(n):{top:n,right:n,bottom:n,left:n}}function Lc(n){const{x:l,y:r,width:o,height:c}=n;return{width:o,height:c,top:r,left:l,right:l+o,bottom:r+c,x:l,y:r}}function yy(n,l,r){let{reference:o,floating:c}=n;const u=kn(l),d=Gd(l),p=Pd(d),h=da(l),m=u==="y",v=o.x+o.width/2-c.width/2,y=o.y+o.height/2-c.height/2,w=o[p]/2-c[p]/2;let _;switch(h){case"top":_={x:v,y:o.y-c.height};break;case"bottom":_={x:v,y:o.y+o.height};break;case"right":_={x:o.x+o.width,y};break;case"left":_={x:o.x-c.width,y};break;default:_={x:o.x,y:o.y}}switch(zi(l)){case"start":_[d]-=w*(r&&m?-1:1);break;case"end":_[d]+=w*(r&&m?-1:1);break}return _}async function M2(n,l){var r;l===void 0&&(l={});const{x:o,y:c,platform:u,rects:d,elements:p,strategy:h}=n,{boundary:m="clippingAncestors",rootBoundary:v="viewport",elementContext:y="floating",altBoundary:w=!1,padding:_=0}=fa(l,n),E=cx(_),A=p[w?y==="floating"?"reference":"floating":y],T=Lc(await u.getClippingRect({element:(r=await(u.isElement==null?void 0:u.isElement(A)))==null||r?A:A.contextElement||await(u.getDocumentElement==null?void 0:u.getDocumentElement(p.floating)),boundary:m,rootBoundary:v,strategy:h})),O=y==="floating"?{x:o,y:c,width:d.floating.width,height:d.floating.height}:d.reference,j=await(u.getOffsetParent==null?void 0:u.getOffsetParent(p.floating)),z=await(u.isElement==null?void 0:u.isElement(j))?await(u.getScale==null?void 0:u.getScale(j))||{x:1,y:1}:{x:1,y:1},k=Lc(u.convertOffsetParentRelativeRectToViewportRelativeRect?await u.convertOffsetParentRelativeRectToViewportRelativeRect({elements:p,rect:O,offsetParent:j,strategy:h}):O);return{top:(T.top-k.top+E.top)/z.y,bottom:(k.bottom-T.bottom+E.bottom)/z.y,left:(T.left-k.left+E.left)/z.x,right:(k.right-T.right+E.right)/z.x}}const z2=async(n,l,r)=>{const{placement:o="bottom",strategy:c="absolute",middleware:u=[],platform:d}=r,p=u.filter(Boolean),h=await(d.isRTL==null?void 0:d.isRTL(l));let m=await d.getElementRects({reference:n,floating:l,strategy:c}),{x:v,y}=yy(m,o,h),w=o,_={},E=0;for(let A=0;A({name:"arrow",options:n,async fn(l){const{x:r,y:o,placement:c,rects:u,platform:d,elements:p,middlewareData:h}=l,{element:m,padding:v=0}=fa(n,l)||{};if(m==null)return{};const y=cx(v),w={x:r,y:o},_=Gd(c),E=Pd(_),S=await d.getDimensions(m),A=_==="y",T=A?"top":"left",O=A?"bottom":"right",j=A?"clientHeight":"clientWidth",z=u.reference[E]+u.reference[_]-w[_]-u.floating[E],k=w[_]-u.reference[_],Y=await(d.getOffsetParent==null?void 0:d.getOffsetParent(m));let U=Y?Y[j]:0;(!U||!await(d.isElement==null?void 0:d.isElement(Y)))&&(U=p.floating[j]||u.floating[E]);const I=z/2-k/2,ae=U/2-S[E]/2-1,ce=Qa(y[T],ae),H=Qa(y[O],ae),le=ce,ve=U-S[E]-H,re=U/2-S[E]/2+I,de=fd(le,re,ve),M=!h.arrow&&zi(c)!=null&&re!==de&&u.reference[E]/2-(rere<=0)){var H,le;const re=(((H=u.flip)==null?void 0:H.index)||0)+1,de=U[re];if(de&&(!(y==="alignment"?O!==kn(de):!1)||ce.every(W=>kn(W.placement)===O?W.overflows[0]>0:!0)))return{data:{index:re,overflows:ce},reset:{placement:de}};let M=(le=ce.filter(Q=>Q.overflows[0]<=0).sort((Q,W)=>Q.overflows[1]-W.overflows[1])[0])==null?void 0:le.placement;if(!M)switch(_){case"bestFit":{var ve;const Q=(ve=ce.filter(W=>{if(Y){const ee=kn(W.placement);return ee===O||ee==="y"}return!0}).map(W=>[W.placement,W.overflows.filter(ee=>ee>0).reduce((ee,J)=>ee+J,0)]).sort((W,ee)=>W[1]-ee[1])[0])==null?void 0:ve[0];Q&&(M=Q);break}case"initialPlacement":M=p;break}if(c!==M)return{reset:{placement:M}}}return{}}}};function by(n,l){return{top:n.top-l.height,right:n.right-l.width,bottom:n.bottom-l.height,left:n.left-l.width}}function xy(n){return w2.some(l=>n[l]>=0)}const U2=function(n){return n===void 0&&(n={}),{name:"hide",options:n,async fn(l){const{rects:r,platform:o}=l,{strategy:c="referenceHidden",...u}=fa(n,l);switch(c){case"referenceHidden":{const d=await o.detectOverflow(l,{...u,elementContext:"reference"}),p=by(d,r.reference);return{data:{referenceHiddenOffsets:p,referenceHidden:xy(p)}}}case"escaped":{const d=await o.detectOverflow(l,{...u,altBoundary:!0}),p=by(d,r.floating);return{data:{escapedOffsets:p,escaped:xy(p)}}}default:return{}}}}},sx=new Set(["left","top"]);async function H2(n,l){const{placement:r,platform:o,elements:c}=n,u=await(o.isRTL==null?void 0:o.isRTL(c.floating)),d=da(r),p=zi(r),h=kn(r)==="y",m=sx.has(d)?-1:1,v=u&&h?-1:1,y=fa(l,n);let{mainAxis:w,crossAxis:_,alignmentAxis:E}=typeof y=="number"?{mainAxis:y,crossAxis:0,alignmentAxis:null}:{mainAxis:y.mainAxis||0,crossAxis:y.crossAxis||0,alignmentAxis:y.alignmentAxis};return p&&typeof E=="number"&&(_=p==="end"?E*-1:E),h?{x:_*v,y:w*m}:{x:w*m,y:_*v}}const B2=function(n){return n===void 0&&(n=0),{name:"offset",options:n,async fn(l){var r,o;const{x:c,y:u,placement:d,middlewareData:p}=l,h=await H2(l,n);return d===((r=p.offset)==null?void 0:r.placement)&&(o=p.arrow)!=null&&o.alignmentOffset?{}:{x:c+h.x,y:u+h.y,data:{...h,placement:d}}}}},q2=function(n){return n===void 0&&(n={}),{name:"shift",options:n,async fn(l){const{x:r,y:o,placement:c,platform:u}=l,{mainAxis:d=!0,crossAxis:p=!1,limiter:h={fn:T=>{let{x:O,y:j}=T;return{x:O,y:j}}},...m}=fa(n,l),v={x:r,y:o},y=await u.detectOverflow(l,m),w=kn(da(c)),_=Vd(w);let E=v[_],S=v[w];if(d){const T=_==="y"?"top":"left",O=_==="y"?"bottom":"right",j=E+y[T],z=E-y[O];E=fd(j,E,z)}if(p){const T=w==="y"?"top":"left",O=w==="y"?"bottom":"right",j=S+y[T],z=S-y[O];S=fd(j,S,z)}const A=h.fn({...l,[_]:E,[w]:S});return{...A,data:{x:A.x-r,y:A.y-o,enabled:{[_]:d,[w]:p}}}}}},V2=function(n){return n===void 0&&(n={}),{options:n,fn(l){const{x:r,y:o,placement:c,rects:u,middlewareData:d}=l,{offset:p=0,mainAxis:h=!0,crossAxis:m=!0}=fa(n,l),v={x:r,y:o},y=kn(c),w=Vd(y);let _=v[w],E=v[y];const S=fa(p,l),A=typeof S=="number"?{mainAxis:S,crossAxis:0}:{mainAxis:0,crossAxis:0,...S};if(h){const j=w==="y"?"height":"width",z=u.reference[w]-u.floating[j]+A.mainAxis,k=u.reference[w]+u.reference[j]-A.mainAxis;_k&&(_=k)}if(m){var T,O;const j=w==="y"?"width":"height",z=sx.has(da(c)),k=u.reference[y]-u.floating[j]+(z&&((T=d.offset)==null?void 0:T[y])||0)+(z?0:A.crossAxis),Y=u.reference[y]+u.reference[j]+(z?0:((O=d.offset)==null?void 0:O[y])||0)-(z?A.crossAxis:0);EY&&(E=Y)}return{[w]:_,[y]:E}}}},P2=function(n){return n===void 0&&(n={}),{name:"size",options:n,async fn(l){var r,o;const{placement:c,rects:u,platform:d,elements:p}=l,{apply:h=()=>{},...m}=fa(n,l),v=await d.detectOverflow(l,m),y=da(c),w=zi(c),_=kn(c)==="y",{width:E,height:S}=u.floating;let A,T;y==="top"||y==="bottom"?(A=y,T=w===(await(d.isRTL==null?void 0:d.isRTL(p.floating))?"start":"end")?"left":"right"):(T=y,A=w==="end"?"top":"bottom");const O=S-v.top-v.bottom,j=E-v.left-v.right,z=Qa(S-v[A],O),k=Qa(E-v[T],j),Y=!l.middlewareData.shift;let U=z,I=k;if((r=l.middlewareData.shift)!=null&&r.enabled.x&&(I=j),(o=l.middlewareData.shift)!=null&&o.enabled.y&&(U=O),Y&&!w){const ce=Jt(v.left,0),H=Jt(v.right,0),le=Jt(v.top,0),ve=Jt(v.bottom,0);_?I=E-2*(ce!==0||H!==0?ce+H:Jt(v.left,v.right)):U=S-2*(le!==0||ve!==0?le+ve:Jt(v.top,v.bottom))}await h({...l,availableWidth:I,availableHeight:U});const ae=await d.getDimensions(p.floating);return E!==ae.width||S!==ae.height?{reset:{rects:!0}}:{}}}};function Wc(){return typeof window<"u"}function ki(n){return ux(n)?(n.nodeName||"").toLowerCase():"#document"}function $t(n){var l;return(n==null||(l=n.ownerDocument)==null?void 0:l.defaultView)||window}function Hn(n){var l;return(l=(ux(n)?n.ownerDocument:n.document)||window.document)==null?void 0:l.documentElement}function ux(n){return Wc()?n instanceof Node||n instanceof $t(n).Node:!1}function bn(n){return Wc()?n instanceof Element||n instanceof $t(n).Element:!1}function Un(n){return Wc()?n instanceof HTMLElement||n instanceof $t(n).HTMLElement:!1}function Sy(n){return!Wc()||typeof ShadowRoot>"u"?!1:n instanceof ShadowRoot||n instanceof $t(n).ShadowRoot}const G2=new Set(["inline","contents"]);function Zr(n){const{overflow:l,overflowX:r,overflowY:o,display:c}=xn(n);return/auto|scroll|overlay|hidden|clip/.test(l+o+r)&&!G2.has(c)}const Y2=new Set(["table","td","th"]);function F2(n){return Y2.has(ki(n))}const X2=[":popover-open",":modal"];function Jc(n){return X2.some(l=>{try{return n.matches(l)}catch{return!1}})}const I2=["transform","translate","scale","rotate","perspective"],Q2=["transform","translate","scale","rotate","perspective","filter"],K2=["paint","layout","strict","content"];function Yd(n){const l=Fd(),r=bn(n)?xn(n):n;return I2.some(o=>r[o]?r[o]!=="none":!1)||(r.containerType?r.containerType!=="normal":!1)||!l&&(r.backdropFilter?r.backdropFilter!=="none":!1)||!l&&(r.filter?r.filter!=="none":!1)||Q2.some(o=>(r.willChange||"").includes(o))||K2.some(o=>(r.contain||"").includes(o))}function Z2(n){let l=Ka(n);for(;Un(l)&&!Ti(l);){if(Yd(l))return l;if(Jc(l))return null;l=Ka(l)}return null}function Fd(){return typeof CSS>"u"||!CSS.supports?!1:CSS.supports("-webkit-backdrop-filter","none")}const W2=new Set(["html","body","#document"]);function Ti(n){return W2.has(ki(n))}function xn(n){return $t(n).getComputedStyle(n)}function $c(n){return bn(n)?{scrollLeft:n.scrollLeft,scrollTop:n.scrollTop}:{scrollLeft:n.scrollX,scrollTop:n.scrollY}}function Ka(n){if(ki(n)==="html")return n;const l=n.assignedSlot||n.parentNode||Sy(n)&&n.host||Hn(n);return Sy(l)?l.host:l}function fx(n){const l=Ka(n);return Ti(l)?n.ownerDocument?n.ownerDocument.body:n.body:Un(l)&&Zr(l)?l:fx(l)}function Vr(n,l,r){var o;l===void 0&&(l=[]),r===void 0&&(r=!0);const c=fx(n),u=c===((o=n.ownerDocument)==null?void 0:o.body),d=$t(c);if(u){const p=pd(d);return l.concat(d,d.visualViewport||[],Zr(c)?c:[],p&&r?Vr(p):[])}return l.concat(c,Vr(c,[],r))}function pd(n){return n.parent&&Object.getPrototypeOf(n.parent)?n.frameElement:null}function dx(n){const l=xn(n);let r=parseFloat(l.width)||0,o=parseFloat(l.height)||0;const c=Un(n),u=c?n.offsetWidth:r,d=c?n.offsetHeight:o,p=zc(r)!==u||zc(o)!==d;return p&&(r=u,o=d),{width:r,height:o,$:p}}function Xd(n){return bn(n)?n:n.contextElement}function _i(n){const l=Xd(n);if(!Un(l))return Ln(1);const r=l.getBoundingClientRect(),{width:o,height:c,$:u}=dx(l);let d=(u?zc(r.width):r.width)/o,p=(u?zc(r.height):r.height)/c;return(!d||!Number.isFinite(d))&&(d=1),(!p||!Number.isFinite(p))&&(p=1),{x:d,y:p}}const J2=Ln(0);function px(n){const l=$t(n);return!Fd()||!l.visualViewport?J2:{x:l.visualViewport.offsetLeft,y:l.visualViewport.offsetTop}}function $2(n,l,r){return l===void 0&&(l=!1),!r||l&&r!==$t(n)?!1:l}function Ol(n,l,r,o){l===void 0&&(l=!1),r===void 0&&(r=!1);const c=n.getBoundingClientRect(),u=Xd(n);let d=Ln(1);l&&(o?bn(o)&&(d=_i(o)):d=_i(n));const p=$2(u,r,o)?px(u):Ln(0);let h=(c.left+p.x)/d.x,m=(c.top+p.y)/d.y,v=c.width/d.x,y=c.height/d.y;if(u){const w=$t(u),_=o&&bn(o)?$t(o):o;let E=w,S=pd(E);for(;S&&o&&_!==E;){const A=_i(S),T=S.getBoundingClientRect(),O=xn(S),j=T.left+(S.clientLeft+parseFloat(O.paddingLeft))*A.x,z=T.top+(S.clientTop+parseFloat(O.paddingTop))*A.y;h*=A.x,m*=A.y,v*=A.x,y*=A.y,h+=j,m+=z,E=$t(S),S=pd(E)}}return Lc({width:v,height:y,x:h,y:m})}function es(n,l){const r=$c(n).scrollLeft;return l?l.left+r:Ol(Hn(n)).left+r}function mx(n,l){const r=n.getBoundingClientRect(),o=r.left+l.scrollLeft-es(n,r),c=r.top+l.scrollTop;return{x:o,y:c}}function eT(n){let{elements:l,rect:r,offsetParent:o,strategy:c}=n;const u=c==="fixed",d=Hn(o),p=l?Jc(l.floating):!1;if(o===d||p&&u)return r;let h={scrollLeft:0,scrollTop:0},m=Ln(1);const v=Ln(0),y=Un(o);if((y||!y&&!u)&&((ki(o)!=="body"||Zr(d))&&(h=$c(o)),Un(o))){const _=Ol(o);m=_i(o),v.x=_.x+o.clientLeft,v.y=_.y+o.clientTop}const w=d&&!y&&!u?mx(d,h):Ln(0);return{width:r.width*m.x,height:r.height*m.y,x:r.x*m.x-h.scrollLeft*m.x+v.x+w.x,y:r.y*m.y-h.scrollTop*m.y+v.y+w.y}}function tT(n){return Array.from(n.getClientRects())}function nT(n){const l=Hn(n),r=$c(n),o=n.ownerDocument.body,c=Jt(l.scrollWidth,l.clientWidth,o.scrollWidth,o.clientWidth),u=Jt(l.scrollHeight,l.clientHeight,o.scrollHeight,o.clientHeight);let d=-r.scrollLeft+es(n);const p=-r.scrollTop;return xn(o).direction==="rtl"&&(d+=Jt(l.clientWidth,o.clientWidth)-c),{width:c,height:u,x:d,y:p}}const wy=25;function aT(n,l){const r=$t(n),o=Hn(n),c=r.visualViewport;let u=o.clientWidth,d=o.clientHeight,p=0,h=0;if(c){u=c.width,d=c.height;const v=Fd();(!v||v&&l==="fixed")&&(p=c.offsetLeft,h=c.offsetTop)}const m=es(o);if(m<=0){const v=o.ownerDocument,y=v.body,w=getComputedStyle(y),_=v.compatMode==="CSS1Compat"&&parseFloat(w.marginLeft)+parseFloat(w.marginRight)||0,E=Math.abs(o.clientWidth-y.clientWidth-_);E<=wy&&(u-=E)}else m<=wy&&(u+=m);return{width:u,height:d,x:p,y:h}}const lT=new Set(["absolute","fixed"]);function iT(n,l){const r=Ol(n,!0,l==="fixed"),o=r.top+n.clientTop,c=r.left+n.clientLeft,u=Un(n)?_i(n):Ln(1),d=n.clientWidth*u.x,p=n.clientHeight*u.y,h=c*u.x,m=o*u.y;return{width:d,height:p,x:h,y:m}}function Ey(n,l,r){let o;if(l==="viewport")o=aT(n,r);else if(l==="document")o=nT(Hn(n));else if(bn(l))o=iT(l,r);else{const c=px(n);o={x:l.x-c.x,y:l.y-c.y,width:l.width,height:l.height}}return Lc(o)}function hx(n,l){const r=Ka(n);return r===l||!bn(r)||Ti(r)?!1:xn(r).position==="fixed"||hx(r,l)}function rT(n,l){const r=l.get(n);if(r)return r;let o=Vr(n,[],!1).filter(p=>bn(p)&&ki(p)!=="body"),c=null;const u=xn(n).position==="fixed";let d=u?Ka(n):n;for(;bn(d)&&!Ti(d);){const p=xn(d),h=Yd(d);!h&&p.position==="fixed"&&(c=null),(u?!h&&!c:!h&&p.position==="static"&&!!c&&lT.has(c.position)||Zr(d)&&!h&&hx(n,d))?o=o.filter(v=>v!==d):c=p,d=Ka(d)}return l.set(n,o),o}function oT(n){let{element:l,boundary:r,rootBoundary:o,strategy:c}=n;const d=[...r==="clippingAncestors"?Jc(l)?[]:rT(l,this._c):[].concat(r),o],p=d[0],h=d.reduce((m,v)=>{const y=Ey(l,v,c);return m.top=Jt(y.top,m.top),m.right=Qa(y.right,m.right),m.bottom=Qa(y.bottom,m.bottom),m.left=Jt(y.left,m.left),m},Ey(l,p,c));return{width:h.right-h.left,height:h.bottom-h.top,x:h.left,y:h.top}}function cT(n){const{width:l,height:r}=dx(n);return{width:l,height:r}}function sT(n,l,r){const o=Un(l),c=Hn(l),u=r==="fixed",d=Ol(n,!0,u,l);let p={scrollLeft:0,scrollTop:0};const h=Ln(0);function m(){h.x=es(c)}if(o||!o&&!u)if((ki(l)!=="body"||Zr(c))&&(p=$c(l)),o){const _=Ol(l,!0,u,l);h.x=_.x+l.clientLeft,h.y=_.y+l.clientTop}else c&&m();u&&!o&&c&&m();const v=c&&!o&&!u?mx(c,p):Ln(0),y=d.left+p.scrollLeft-h.x-v.x,w=d.top+p.scrollTop-h.y-v.y;return{x:y,y:w,width:d.width,height:d.height}}function Vf(n){return xn(n).position==="static"}function _y(n,l){if(!Un(n)||xn(n).position==="fixed")return null;if(l)return l(n);let r=n.offsetParent;return Hn(n)===r&&(r=r.ownerDocument.body),r}function vx(n,l){const r=$t(n);if(Jc(n))return r;if(!Un(n)){let c=Ka(n);for(;c&&!Ti(c);){if(bn(c)&&!Vf(c))return c;c=Ka(c)}return r}let o=_y(n,l);for(;o&&F2(o)&&Vf(o);)o=_y(o,l);return o&&Ti(o)&&Vf(o)&&!Yd(o)?r:o||Z2(n)||r}const uT=async function(n){const l=this.getOffsetParent||vx,r=this.getDimensions,o=await r(n.floating);return{reference:sT(n.reference,await l(n.floating),n.strategy),floating:{x:0,y:0,width:o.width,height:o.height}}};function fT(n){return xn(n).direction==="rtl"}const dT={convertOffsetParentRelativeRectToViewportRelativeRect:eT,getDocumentElement:Hn,getClippingRect:oT,getOffsetParent:vx,getElementRects:uT,getClientRects:tT,getDimensions:cT,getScale:_i,isElement:bn,isRTL:fT};function gx(n,l){return n.x===l.x&&n.y===l.y&&n.width===l.width&&n.height===l.height}function pT(n,l){let r=null,o;const c=Hn(n);function u(){var p;clearTimeout(o),(p=r)==null||p.disconnect(),r=null}function d(p,h){p===void 0&&(p=!1),h===void 0&&(h=1),u();const m=n.getBoundingClientRect(),{left:v,top:y,width:w,height:_}=m;if(p||l(),!w||!_)return;const E=vc(y),S=vc(c.clientWidth-(v+w)),A=vc(c.clientHeight-(y+_)),T=vc(v),j={rootMargin:-E+"px "+-S+"px "+-A+"px "+-T+"px",threshold:Jt(0,Qa(1,h))||1};let z=!0;function k(Y){const U=Y[0].intersectionRatio;if(U!==h){if(!z)return d();U?d(!1,U):o=setTimeout(()=>{d(!1,1e-7)},1e3)}U===1&&!gx(m,n.getBoundingClientRect())&&d(),z=!1}try{r=new IntersectionObserver(k,{...j,root:c.ownerDocument})}catch{r=new IntersectionObserver(k,j)}r.observe(n)}return d(!0),u}function mT(n,l,r,o){o===void 0&&(o={});const{ancestorScroll:c=!0,ancestorResize:u=!0,elementResize:d=typeof ResizeObserver=="function",layoutShift:p=typeof IntersectionObserver=="function",animationFrame:h=!1}=o,m=Xd(n),v=c||u?[...m?Vr(m):[],...Vr(l)]:[];v.forEach(T=>{c&&T.addEventListener("scroll",r,{passive:!0}),u&&T.addEventListener("resize",r)});const y=m&&p?pT(m,r):null;let w=-1,_=null;d&&(_=new ResizeObserver(T=>{let[O]=T;O&&O.target===m&&_&&(_.unobserve(l),cancelAnimationFrame(w),w=requestAnimationFrame(()=>{var j;(j=_)==null||j.observe(l)})),r()}),m&&!h&&_.observe(m),_.observe(l));let E,S=h?Ol(n):null;h&&A();function A(){const T=Ol(n);S&&!gx(S,T)&&r(),S=T,E=requestAnimationFrame(A)}return r(),()=>{var T;v.forEach(O=>{c&&O.removeEventListener("scroll",r),u&&O.removeEventListener("resize",r)}),y?.(),(T=_)==null||T.disconnect(),_=null,h&&cancelAnimationFrame(E)}}const hT=B2,vT=q2,gT=L2,yT=P2,bT=U2,Cy=k2,xT=V2,ST=(n,l,r)=>{const o=new Map,c={platform:dT,...r},u={...c.platform,_c:o};return z2(n,l,{...c,platform:u})};var wT=typeof document<"u",ET=function(){},Oc=wT?x.useLayoutEffect:ET;function Uc(n,l){if(n===l)return!0;if(typeof n!=typeof l)return!1;if(typeof n=="function"&&n.toString()===l.toString())return!0;let r,o,c;if(n&&l&&typeof n=="object"){if(Array.isArray(n)){if(r=n.length,r!==l.length)return!1;for(o=r;o--!==0;)if(!Uc(n[o],l[o]))return!1;return!0}if(c=Object.keys(n),r=c.length,r!==Object.keys(l).length)return!1;for(o=r;o--!==0;)if(!{}.hasOwnProperty.call(l,c[o]))return!1;for(o=r;o--!==0;){const u=c[o];if(!(u==="_owner"&&n.$$typeof)&&!Uc(n[u],l[u]))return!1}return!0}return n!==n&&l!==l}function yx(n){return typeof window>"u"?1:(n.ownerDocument.defaultView||window).devicePixelRatio||1}function Ay(n,l){const r=yx(n);return Math.round(l*r)/r}function Pf(n){const l=x.useRef(n);return Oc(()=>{l.current=n}),l}function _T(n){n===void 0&&(n={});const{placement:l="bottom",strategy:r="absolute",middleware:o=[],platform:c,elements:{reference:u,floating:d}={},transform:p=!0,whileElementsMounted:h,open:m}=n,[v,y]=x.useState({x:0,y:0,strategy:r,placement:l,middlewareData:{},isPositioned:!1}),[w,_]=x.useState(o);Uc(w,o)||_(o);const[E,S]=x.useState(null),[A,T]=x.useState(null),O=x.useCallback(W=>{W!==Y.current&&(Y.current=W,S(W))},[]),j=x.useCallback(W=>{W!==U.current&&(U.current=W,T(W))},[]),z=u||E,k=d||A,Y=x.useRef(null),U=x.useRef(null),I=x.useRef(v),ae=h!=null,ce=Pf(h),H=Pf(c),le=Pf(m),ve=x.useCallback(()=>{if(!Y.current||!U.current)return;const W={placement:l,strategy:r,middleware:w};H.current&&(W.platform=H.current),ST(Y.current,U.current,W).then(ee=>{const J={...ee,isPositioned:le.current!==!1};re.current&&!Uc(I.current,J)&&(I.current=J,Kr.flushSync(()=>{y(J)}))})},[w,l,r,H,le]);Oc(()=>{m===!1&&I.current.isPositioned&&(I.current.isPositioned=!1,y(W=>({...W,isPositioned:!1})))},[m]);const re=x.useRef(!1);Oc(()=>(re.current=!0,()=>{re.current=!1}),[]),Oc(()=>{if(z&&(Y.current=z),k&&(U.current=k),z&&k){if(ce.current)return ce.current(z,k,ve);ve()}},[z,k,ve,ce,ae]);const de=x.useMemo(()=>({reference:Y,floating:U,setReference:O,setFloating:j}),[O,j]),M=x.useMemo(()=>({reference:z,floating:k}),[z,k]),Q=x.useMemo(()=>{const W={position:r,left:0,top:0};if(!M.floating)return W;const ee=Ay(M.floating,v.x),J=Ay(M.floating,v.y);return p?{...W,transform:"translate("+ee+"px, "+J+"px)",...yx(M.floating)>=1.5&&{willChange:"transform"}}:{position:r,left:ee,top:J}},[r,p,M.floating,v.x,v.y]);return x.useMemo(()=>({...v,update:ve,refs:de,elements:M,floatingStyles:Q}),[v,ve,de,M,Q])}const CT=n=>{function l(r){return{}.hasOwnProperty.call(r,"current")}return{name:"arrow",options:n,fn(r){const{element:o,padding:c}=typeof n=="function"?n(r):n;return o&&l(o)?o.current!=null?Cy({element:o.current,padding:c}).fn(r):{}:o?Cy({element:o,padding:c}).fn(r):{}}}},AT=(n,l)=>({...hT(n),options:[n,l]}),TT=(n,l)=>({...vT(n),options:[n,l]}),OT=(n,l)=>({...xT(n),options:[n,l]}),RT=(n,l)=>({...gT(n),options:[n,l]}),NT=(n,l)=>({...yT(n),options:[n,l]}),jT=(n,l)=>({...bT(n),options:[n,l]}),DT=(n,l)=>({...CT(n),options:[n,l]});var MT="Arrow",bx=x.forwardRef((n,l)=>{const{children:r,width:o=10,height:c=5,...u}=n;return b.jsx(Te.svg,{...u,ref:l,width:o,height:c,viewBox:"0 0 30 10",preserveAspectRatio:"none",children:n.asChild?r:b.jsx("polygon",{points:"0,0 30,0 15,10"})})});bx.displayName=MT;var zT=bx;function xx(n){const[l,r]=x.useState(void 0);return yt(()=>{if(n){r({width:n.offsetWidth,height:n.offsetHeight});const o=new ResizeObserver(c=>{if(!Array.isArray(c)||!c.length)return;const u=c[0];let d,p;if("borderBoxSize"in u){const h=u.borderBoxSize,m=Array.isArray(h)?h[0]:h;d=m.inlineSize,p=m.blockSize}else d=n.offsetWidth,p=n.offsetHeight;r({width:d,height:p})});return o.observe(n,{box:"border-box"}),()=>o.unobserve(n)}else r(void 0)},[n]),l}var Id="Popper",[Sx,wx]=Wa(Id),[kT,Ex]=Sx(Id),_x=n=>{const{__scopePopper:l,children:r}=n,[o,c]=x.useState(null);return b.jsx(kT,{scope:l,anchor:o,onAnchorChange:c,children:r})};_x.displayName=Id;var Cx="PopperAnchor",Ax=x.forwardRef((n,l)=>{const{__scopePopper:r,virtualRef:o,...c}=n,u=Ex(Cx,r),d=x.useRef(null),p=qe(l,d),h=x.useRef(null);return x.useEffect(()=>{const m=h.current;h.current=o?.current||d.current,m!==h.current&&u.onAnchorChange(h.current)}),o?null:b.jsx(Te.div,{...c,ref:p})});Ax.displayName=Cx;var Qd="PopperContent",[LT,UT]=Sx(Qd),Tx=x.forwardRef((n,l)=>{const{__scopePopper:r,side:o="bottom",sideOffset:c=0,align:u="center",alignOffset:d=0,arrowPadding:p=0,avoidCollisions:h=!0,collisionBoundary:m=[],collisionPadding:v=0,sticky:y="partial",hideWhenDetached:w=!1,updatePositionStrategy:_="optimized",onPlaced:E,...S}=n,A=Ex(Qd,r),[T,O]=x.useState(null),j=qe(l,$=>O($)),[z,k]=x.useState(null),Y=xx(z),U=Y?.width??0,I=Y?.height??0,ae=o+(u!=="center"?"-"+u:""),ce=typeof v=="number"?v:{top:0,right:0,bottom:0,left:0,...v},H=Array.isArray(m)?m:[m],le=H.length>0,ve={padding:ce,boundary:H.filter(BT),altBoundary:le},{refs:re,floatingStyles:de,placement:M,isPositioned:Q,middlewareData:W}=_T({strategy:"fixed",placement:ae,whileElementsMounted:(...$)=>mT(...$,{animationFrame:_==="always"}),elements:{reference:A.anchor},middleware:[AT({mainAxis:c+I,alignmentAxis:d}),h&&TT({mainAxis:!0,crossAxis:!1,limiter:y==="partial"?OT():void 0,...ve}),h&&RT({...ve}),NT({...ve,apply:({elements:$,rects:Se,availableWidth:pe,availableHeight:Oe})=>{const{width:Ce,height:ke}=Se.reference,Ke=$.floating.style;Ke.setProperty("--radix-popper-available-width",`${pe}px`),Ke.setProperty("--radix-popper-available-height",`${Oe}px`),Ke.setProperty("--radix-popper-anchor-width",`${Ce}px`),Ke.setProperty("--radix-popper-anchor-height",`${ke}px`)}}),z&&DT({element:z,padding:p}),qT({arrowWidth:U,arrowHeight:I}),w&&jT({strategy:"referenceHidden",...ve})]}),[ee,J]=Nx(M),N=Bt(E);yt(()=>{Q&&N?.()},[Q,N]);const F=W.arrow?.x,te=W.arrow?.y,ne=W.arrow?.centerOffset!==0,[ie,se]=x.useState();return yt(()=>{T&&se(window.getComputedStyle(T).zIndex)},[T]),b.jsx("div",{ref:re.setFloating,"data-radix-popper-content-wrapper":"",style:{...de,transform:Q?de.transform:"translate(0, -200%)",minWidth:"max-content",zIndex:ie,"--radix-popper-transform-origin":[W.transformOrigin?.x,W.transformOrigin?.y].join(" "),...W.hide?.referenceHidden&&{visibility:"hidden",pointerEvents:"none"}},dir:n.dir,children:b.jsx(LT,{scope:r,placedSide:ee,onArrowChange:k,arrowX:F,arrowY:te,shouldHideArrow:ne,children:b.jsx(Te.div,{"data-side":ee,"data-align":J,...S,ref:j,style:{...S.style,animation:Q?void 0:"none"}})})})});Tx.displayName=Qd;var Ox="PopperArrow",HT={top:"bottom",right:"left",bottom:"top",left:"right"},Rx=x.forwardRef(function(l,r){const{__scopePopper:o,...c}=l,u=UT(Ox,o),d=HT[u.placedSide];return b.jsx("span",{ref:u.onArrowChange,style:{position:"absolute",left:u.arrowX,top:u.arrowY,[d]:0,transformOrigin:{top:"",right:"0 0",bottom:"center 0",left:"100% 0"}[u.placedSide],transform:{top:"translateY(100%)",right:"translateY(50%) rotate(90deg) translateX(-50%)",bottom:"rotate(180deg)",left:"translateY(50%) rotate(-90deg) translateX(50%)"}[u.placedSide],visibility:u.shouldHideArrow?"hidden":void 0},children:b.jsx(zT,{...c,ref:r,style:{...c.style,display:"block"}})})});Rx.displayName=Ox;function BT(n){return n!==null}var qT=n=>({name:"transformOrigin",options:n,fn(l){const{placement:r,rects:o,middlewareData:c}=l,d=c.arrow?.centerOffset!==0,p=d?0:n.arrowWidth,h=d?0:n.arrowHeight,[m,v]=Nx(r),y={start:"0%",center:"50%",end:"100%"}[v],w=(c.arrow?.x??0)+p/2,_=(c.arrow?.y??0)+h/2;let E="",S="";return m==="bottom"?(E=d?y:`${w}px`,S=`${-h}px`):m==="top"?(E=d?y:`${w}px`,S=`${o.floating.height+h}px`):m==="right"?(E=`${-h}px`,S=d?y:`${_}px`):m==="left"&&(E=`${o.floating.width+h}px`,S=d?y:`${_}px`),{data:{x:E,y:S}}}});function Nx(n){const[l,r="center"]=n.split("-");return[l,r]}var VT=_x,PT=Ax,GT=Tx,YT=Rx,FT="Portal",Kd=x.forwardRef((n,l)=>{const{container:r,...o}=n,[c,u]=x.useState(!1);yt(()=>u(!0),[]);const d=r||c&&globalThis?.document?.body;return d?BA.createPortal(b.jsx(Te.div,{...o,ref:l}),d):null});Kd.displayName=FT;function XT(n){const l=IT(n),r=x.forwardRef((o,c)=>{const{children:u,...d}=o,p=x.Children.toArray(u),h=p.find(KT);if(h){const m=h.props.children,v=p.map(y=>y===h?x.Children.count(m)>1?x.Children.only(null):x.isValidElement(m)?m.props.children:null:y);return b.jsx(l,{...d,ref:c,children:x.isValidElement(m)?x.cloneElement(m,void 0,v):null})}return b.jsx(l,{...d,ref:c,children:u})});return r.displayName=`${n}.Slot`,r}function IT(n){const l=x.forwardRef((r,o)=>{const{children:c,...u}=r;if(x.isValidElement(c)){const d=WT(c),p=ZT(u,c.props);return c.type!==x.Fragment&&(p.ref=o?Mi(o,d):d),x.cloneElement(c,p)}return x.Children.count(c)>1?x.Children.only(null):null});return l.displayName=`${n}.SlotClone`,l}var QT=Symbol("radix.slottable");function KT(n){return x.isValidElement(n)&&typeof n.type=="function"&&"__radixId"in n.type&&n.type.__radixId===QT}function ZT(n,l){const r={...l};for(const o in l){const c=n[o],u=l[o];/^on[A-Z]/.test(o)?c&&u?r[o]=(...p)=>{const h=u(...p);return c(...p),h}:c&&(r[o]=c):o==="style"?r[o]={...c,...u}:o==="className"&&(r[o]=[c,u].filter(Boolean).join(" "))}return{...n,...r}}function WT(n){let l=Object.getOwnPropertyDescriptor(n.props,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning;return r?n.ref:(l=Object.getOwnPropertyDescriptor(n,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning,r?n.props.ref:n.props.ref||n.ref)}var JT=Td[" useInsertionEffect ".trim().toString()]||yt;function Rl({prop:n,defaultProp:l,onChange:r=()=>{},caller:o}){const[c,u,d]=$T({defaultProp:l,onChange:r}),p=n!==void 0,h=p?n:c;{const v=x.useRef(n!==void 0);x.useEffect(()=>{const y=v.current;y!==p&&console.warn(`${o} is changing from ${y?"controlled":"uncontrolled"} to ${p?"controlled":"uncontrolled"}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`),v.current=p},[p,o])}const m=x.useCallback(v=>{if(p){const y=eO(v)?v(n):v;y!==n&&d.current?.(y)}else u(v)},[p,n,u,d]);return[h,m]}function $T({defaultProp:n,onChange:l}){const[r,o]=x.useState(n),c=x.useRef(r),u=x.useRef(l);return JT(()=>{u.current=l},[l]),x.useEffect(()=>{c.current!==r&&(u.current?.(r),c.current=r)},[r,c]),[r,o,u]}function eO(n){return typeof n=="function"}function jx(n){const l=x.useRef({value:n,previous:n});return x.useMemo(()=>(l.current.value!==n&&(l.current.previous=l.current.value,l.current.value=n),l.current.previous),[n])}var Dx=Object.freeze({position:"absolute",border:0,width:1,height:1,padding:0,margin:-1,overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",wordWrap:"normal"}),tO="VisuallyHidden",nO=x.forwardRef((n,l)=>b.jsx(Te.span,{...n,ref:l,style:{...Dx,...n.style}}));nO.displayName=tO;var aO=function(n){if(typeof document>"u")return null;var l=Array.isArray(n)?n[0]:n;return l.ownerDocument.body},xi=new WeakMap,gc=new WeakMap,yc={},Gf=0,Mx=function(n){return n&&(n.host||Mx(n.parentNode))},lO=function(n,l){return l.map(function(r){if(n.contains(r))return r;var o=Mx(r);return o&&n.contains(o)?o:(console.error("aria-hidden",r,"in not contained inside",n,". Doing nothing"),null)}).filter(function(r){return!!r})},iO=function(n,l,r,o){var c=lO(l,Array.isArray(n)?n:[n]);yc[r]||(yc[r]=new WeakMap);var u=yc[r],d=[],p=new Set,h=new Set(c),m=function(y){!y||p.has(y)||(p.add(y),m(y.parentNode))};c.forEach(m);var v=function(y){!y||h.has(y)||Array.prototype.forEach.call(y.children,function(w){if(p.has(w))v(w);else try{var _=w.getAttribute(o),E=_!==null&&_!=="false",S=(xi.get(w)||0)+1,A=(u.get(w)||0)+1;xi.set(w,S),u.set(w,A),d.push(w),S===1&&E&&gc.set(w,!0),A===1&&w.setAttribute(r,"true"),E||w.setAttribute(o,"true")}catch(T){console.error("aria-hidden: cannot operate on ",w,T)}})};return v(l),p.clear(),Gf++,function(){d.forEach(function(y){var w=xi.get(y)-1,_=u.get(y)-1;xi.set(y,w),u.set(y,_),w||(gc.has(y)||y.removeAttribute(o),gc.delete(y)),_||y.removeAttribute(r)}),Gf--,Gf||(xi=new WeakMap,xi=new WeakMap,gc=new WeakMap,yc={})}},zx=function(n,l,r){r===void 0&&(r="data-aria-hidden");var o=Array.from(Array.isArray(n)?n:[n]),c=aO(n);return c?(o.push.apply(o,Array.from(c.querySelectorAll("[aria-live], script"))),iO(o,c,r,"aria-hidden")):function(){return null}},zn=function(){return zn=Object.assign||function(l){for(var r,o=1,c=arguments.length;o"u")return wO;var l=EO(n),r=document.documentElement.clientWidth,o=window.innerWidth;return{left:l[0],top:l[1],right:l[2],gap:Math.max(0,o-r+l[2]-l[0])}},CO=Hx(),Ci="data-scroll-locked",AO=function(n,l,r,o){var c=n.left,u=n.top,d=n.right,p=n.gap;return r===void 0&&(r="margin"),` + .`.concat(oO,` { + overflow: hidden `).concat(o,`; + padding-right: `).concat(p,"px ").concat(o,`; + } + body[`).concat(Ci,`] { + overflow: hidden `).concat(o,`; + overscroll-behavior: contain; + `).concat([l&&"position: relative ".concat(o,";"),r==="margin"&&` + padding-left: `.concat(c,`px; + padding-top: `).concat(u,`px; + padding-right: `).concat(d,`px; + margin-left:0; + margin-top:0; + margin-right: `).concat(p,"px ").concat(o,`; + `),r==="padding"&&"padding-right: ".concat(p,"px ").concat(o,";")].filter(Boolean).join(""),` + } + + .`).concat(Rc,` { + right: `).concat(p,"px ").concat(o,`; + } + + .`).concat(Nc,` { + margin-right: `).concat(p,"px ").concat(o,`; + } + + .`).concat(Rc," .").concat(Rc,` { + right: 0 `).concat(o,`; + } + + .`).concat(Nc," .").concat(Nc,` { + margin-right: 0 `).concat(o,`; + } + + body[`).concat(Ci,`] { + `).concat(cO,": ").concat(p,`px; + } +`)},Oy=function(){var n=parseInt(document.body.getAttribute(Ci)||"0",10);return isFinite(n)?n:0},TO=function(){x.useEffect(function(){return document.body.setAttribute(Ci,(Oy()+1).toString()),function(){var n=Oy()-1;n<=0?document.body.removeAttribute(Ci):document.body.setAttribute(Ci,n.toString())}},[])},OO=function(n){var l=n.noRelative,r=n.noImportant,o=n.gapMode,c=o===void 0?"margin":o;TO();var u=x.useMemo(function(){return _O(c)},[c]);return x.createElement(CO,{styles:AO(u,!l,c,r?"":"!important")})},md=!1;if(typeof window<"u")try{var bc=Object.defineProperty({},"passive",{get:function(){return md=!0,!0}});window.addEventListener("test",bc,bc),window.removeEventListener("test",bc,bc)}catch{md=!1}var Si=md?{passive:!1}:!1,RO=function(n){return n.tagName==="TEXTAREA"},Bx=function(n,l){if(!(n instanceof Element))return!1;var r=window.getComputedStyle(n);return r[l]!=="hidden"&&!(r.overflowY===r.overflowX&&!RO(n)&&r[l]==="visible")},NO=function(n){return Bx(n,"overflowY")},jO=function(n){return Bx(n,"overflowX")},Ry=function(n,l){var r=l.ownerDocument,o=l;do{typeof ShadowRoot<"u"&&o instanceof ShadowRoot&&(o=o.host);var c=qx(n,o);if(c){var u=Vx(n,o),d=u[1],p=u[2];if(d>p)return!0}o=o.parentNode}while(o&&o!==r.body);return!1},DO=function(n){var l=n.scrollTop,r=n.scrollHeight,o=n.clientHeight;return[l,r,o]},MO=function(n){var l=n.scrollLeft,r=n.scrollWidth,o=n.clientWidth;return[l,r,o]},qx=function(n,l){return n==="v"?NO(l):jO(l)},Vx=function(n,l){return n==="v"?DO(l):MO(l)},zO=function(n,l){return n==="h"&&l==="rtl"?-1:1},kO=function(n,l,r,o,c){var u=zO(n,window.getComputedStyle(l).direction),d=u*o,p=r.target,h=l.contains(p),m=!1,v=d>0,y=0,w=0;do{if(!p)break;var _=Vx(n,p),E=_[0],S=_[1],A=_[2],T=S-A-u*E;(E||T)&&qx(n,p)&&(y+=T,w+=E);var O=p.parentNode;p=O&&O.nodeType===Node.DOCUMENT_FRAGMENT_NODE?O.host:O}while(!h&&p!==document.body||h&&(l.contains(p)||l===p));return(v&&Math.abs(y)<1||!v&&Math.abs(w)<1)&&(m=!0),m},xc=function(n){return"changedTouches"in n?[n.changedTouches[0].clientX,n.changedTouches[0].clientY]:[0,0]},Ny=function(n){return[n.deltaX,n.deltaY]},jy=function(n){return n&&"current"in n?n.current:n},LO=function(n,l){return n[0]===l[0]&&n[1]===l[1]},UO=function(n){return` + .block-interactivity-`.concat(n,` {pointer-events: none;} + .allow-interactivity-`).concat(n,` {pointer-events: all;} +`)},HO=0,wi=[];function BO(n){var l=x.useRef([]),r=x.useRef([0,0]),o=x.useRef(),c=x.useState(HO++)[0],u=x.useState(Hx)[0],d=x.useRef(n);x.useEffect(function(){d.current=n},[n]),x.useEffect(function(){if(n.inert){document.body.classList.add("block-interactivity-".concat(c));var S=rO([n.lockRef.current],(n.shards||[]).map(jy),!0).filter(Boolean);return S.forEach(function(A){return A.classList.add("allow-interactivity-".concat(c))}),function(){document.body.classList.remove("block-interactivity-".concat(c)),S.forEach(function(A){return A.classList.remove("allow-interactivity-".concat(c))})}}},[n.inert,n.lockRef.current,n.shards]);var p=x.useCallback(function(S,A){if("touches"in S&&S.touches.length===2||S.type==="wheel"&&S.ctrlKey)return!d.current.allowPinchZoom;var T=xc(S),O=r.current,j="deltaX"in S?S.deltaX:O[0]-T[0],z="deltaY"in S?S.deltaY:O[1]-T[1],k,Y=S.target,U=Math.abs(j)>Math.abs(z)?"h":"v";if("touches"in S&&U==="h"&&Y.type==="range")return!1;var I=window.getSelection(),ae=I&&I.anchorNode,ce=ae?ae===Y||ae.contains(Y):!1;if(ce)return!1;var H=Ry(U,Y);if(!H)return!0;if(H?k=U:(k=U==="v"?"h":"v",H=Ry(U,Y)),!H)return!1;if(!o.current&&"changedTouches"in S&&(j||z)&&(o.current=k),!k)return!0;var le=o.current||k;return kO(le,A,S,le==="h"?j:z)},[]),h=x.useCallback(function(S){var A=S;if(!(!wi.length||wi[wi.length-1]!==u)){var T="deltaY"in A?Ny(A):xc(A),O=l.current.filter(function(k){return k.name===A.type&&(k.target===A.target||A.target===k.shadowParent)&&LO(k.delta,T)})[0];if(O&&O.should){A.cancelable&&A.preventDefault();return}if(!O){var j=(d.current.shards||[]).map(jy).filter(Boolean).filter(function(k){return k.contains(A.target)}),z=j.length>0?p(A,j[0]):!d.current.noIsolation;z&&A.cancelable&&A.preventDefault()}}},[]),m=x.useCallback(function(S,A,T,O){var j={name:S,delta:A,target:T,should:O,shadowParent:qO(T)};l.current.push(j),setTimeout(function(){l.current=l.current.filter(function(z){return z!==j})},1)},[]),v=x.useCallback(function(S){r.current=xc(S),o.current=void 0},[]),y=x.useCallback(function(S){m(S.type,Ny(S),S.target,p(S,n.lockRef.current))},[]),w=x.useCallback(function(S){m(S.type,xc(S),S.target,p(S,n.lockRef.current))},[]);x.useEffect(function(){return wi.push(u),n.setCallbacks({onScrollCapture:y,onWheelCapture:y,onTouchMoveCapture:w}),document.addEventListener("wheel",h,Si),document.addEventListener("touchmove",h,Si),document.addEventListener("touchstart",v,Si),function(){wi=wi.filter(function(S){return S!==u}),document.removeEventListener("wheel",h,Si),document.removeEventListener("touchmove",h,Si),document.removeEventListener("touchstart",v,Si)}},[]);var _=n.removeScrollBar,E=n.inert;return x.createElement(x.Fragment,null,E?x.createElement(u,{styles:UO(c)}):null,_?x.createElement(OO,{noRelative:n.noRelative,gapMode:n.gapMode}):null)}function qO(n){for(var l=null;n!==null;)n instanceof ShadowRoot&&(l=n.host,n=n.host),n=n.parentNode;return l}const VO=hO(Ux,BO);var Zd=x.forwardRef(function(n,l){return x.createElement(ts,zn({},n,{ref:l,sideCar:VO}))});Zd.classNames=ts.classNames;var PO=[" ","Enter","ArrowUp","ArrowDown"],GO=[" ","Enter"],Nl="Select",[ns,as,YO]=ax(Nl),[Li]=Wa(Nl,[YO,wx]),ls=wx(),[FO,Ja]=Li(Nl),[XO,IO]=Li(Nl),Px=n=>{const{__scopeSelect:l,children:r,open:o,defaultOpen:c,onOpenChange:u,value:d,defaultValue:p,onValueChange:h,dir:m,name:v,autoComplete:y,disabled:w,required:_,form:E}=n,S=ls(l),[A,T]=x.useState(null),[O,j]=x.useState(null),[z,k]=x.useState(!1),Y=Hd(m),[U,I]=Rl({prop:o,defaultProp:c??!1,onChange:u,caller:Nl}),[ae,ce]=Rl({prop:d,defaultProp:p,onChange:h,caller:Nl}),H=x.useRef(null),le=A?E||!!A.closest("form"):!0,[ve,re]=x.useState(new Set),de=Array.from(ve).map(M=>M.props.value).join(";");return b.jsx(VT,{...S,children:b.jsxs(FO,{required:_,scope:l,trigger:A,onTriggerChange:T,valueNode:O,onValueNodeChange:j,valueNodeHasChildren:z,onValueNodeHasChildrenChange:k,contentId:Xa(),value:ae,onValueChange:ce,open:U,onOpenChange:I,dir:Y,triggerPointerDownPosRef:H,disabled:w,children:[b.jsx(ns.Provider,{scope:l,children:b.jsx(XO,{scope:n.__scopeSelect,onNativeOptionAdd:x.useCallback(M=>{re(Q=>new Set(Q).add(M))},[]),onNativeOptionRemove:x.useCallback(M=>{re(Q=>{const W=new Set(Q);return W.delete(M),W})},[]),children:r})}),le?b.jsxs(d0,{"aria-hidden":!0,required:_,tabIndex:-1,name:v,autoComplete:y,value:ae,onChange:M=>ce(M.target.value),disabled:w,form:E,children:[ae===void 0?b.jsx("option",{value:""}):null,Array.from(ve)]},de):null]})})};Px.displayName=Nl;var Gx="SelectTrigger",Yx=x.forwardRef((n,l)=>{const{__scopeSelect:r,disabled:o=!1,...c}=n,u=ls(r),d=Ja(Gx,r),p=d.disabled||o,h=qe(l,d.onTriggerChange),m=as(r),v=x.useRef("touch"),[y,w,_]=m0(S=>{const A=m().filter(j=>!j.disabled),T=A.find(j=>j.value===d.value),O=h0(A,S,T);O!==void 0&&d.onValueChange(O.value)}),E=S=>{p||(d.onOpenChange(!0),_()),S&&(d.triggerPointerDownPosRef.current={x:Math.round(S.pageX),y:Math.round(S.pageY)})};return b.jsx(PT,{asChild:!0,...u,children:b.jsx(Te.button,{type:"button",role:"combobox","aria-controls":d.contentId,"aria-expanded":d.open,"aria-required":d.required,"aria-autocomplete":"none",dir:d.dir,"data-state":d.open?"open":"closed",disabled:p,"data-disabled":p?"":void 0,"data-placeholder":p0(d.value)?"":void 0,...c,ref:h,onClick:ze(c.onClick,S=>{S.currentTarget.focus(),v.current!=="mouse"&&E(S)}),onPointerDown:ze(c.onPointerDown,S=>{v.current=S.pointerType;const A=S.target;A.hasPointerCapture(S.pointerId)&&A.releasePointerCapture(S.pointerId),S.button===0&&S.ctrlKey===!1&&S.pointerType==="mouse"&&(E(S),S.preventDefault())}),onKeyDown:ze(c.onKeyDown,S=>{const A=y.current!=="";!(S.ctrlKey||S.altKey||S.metaKey)&&S.key.length===1&&w(S.key),!(A&&S.key===" ")&&PO.includes(S.key)&&(E(),S.preventDefault())})})})});Yx.displayName=Gx;var Fx="SelectValue",Xx=x.forwardRef((n,l)=>{const{__scopeSelect:r,className:o,style:c,children:u,placeholder:d="",...p}=n,h=Ja(Fx,r),{onValueNodeHasChildrenChange:m}=h,v=u!==void 0,y=qe(l,h.onValueNodeChange);return yt(()=>{m(v)},[m,v]),b.jsx(Te.span,{...p,ref:y,style:{pointerEvents:"none"},children:p0(h.value)?b.jsx(b.Fragment,{children:d}):u})});Xx.displayName=Fx;var QO="SelectIcon",Ix=x.forwardRef((n,l)=>{const{__scopeSelect:r,children:o,...c}=n;return b.jsx(Te.span,{"aria-hidden":!0,...c,ref:l,children:o||"▼"})});Ix.displayName=QO;var KO="SelectPortal",Qx=n=>b.jsx(Kd,{asChild:!0,...n});Qx.displayName=KO;var jl="SelectContent",Kx=x.forwardRef((n,l)=>{const r=Ja(jl,n.__scopeSelect),[o,c]=x.useState();if(yt(()=>{c(new DocumentFragment)},[]),!r.open){const u=o;return u?Kr.createPortal(b.jsx(Zx,{scope:n.__scopeSelect,children:b.jsx(ns.Slot,{scope:n.__scopeSelect,children:b.jsx("div",{children:n.children})})}),u):null}return b.jsx(Wx,{...n,ref:l})});Kx.displayName=jl;var yn=10,[Zx,$a]=Li(jl),ZO="SelectContentImpl",WO=XT("SelectContent.RemoveScroll"),Wx=x.forwardRef((n,l)=>{const{__scopeSelect:r,position:o="item-aligned",onCloseAutoFocus:c,onEscapeKeyDown:u,onPointerDownOutside:d,side:p,sideOffset:h,align:m,alignOffset:v,arrowPadding:y,collisionBoundary:w,collisionPadding:_,sticky:E,hideWhenDetached:S,avoidCollisions:A,...T}=n,O=Ja(jl,r),[j,z]=x.useState(null),[k,Y]=x.useState(null),U=qe(l,$=>z($)),[I,ae]=x.useState(null),[ce,H]=x.useState(null),le=as(r),[ve,re]=x.useState(!1),de=x.useRef(!1);x.useEffect(()=>{if(j)return zx(j)},[j]),rx();const M=x.useCallback($=>{const[Se,...pe]=le().map(ke=>ke.ref.current),[Oe]=pe.slice(-1),Ce=document.activeElement;for(const ke of $)if(ke===Ce||(ke?.scrollIntoView({block:"nearest"}),ke===Se&&k&&(k.scrollTop=0),ke===Oe&&k&&(k.scrollTop=k.scrollHeight),ke?.focus(),document.activeElement!==Ce))return},[le,k]),Q=x.useCallback(()=>M([I,j]),[M,I,j]);x.useEffect(()=>{ve&&Q()},[ve,Q]);const{onOpenChange:W,triggerPointerDownPosRef:ee}=O;x.useEffect(()=>{if(j){let $={x:0,y:0};const Se=Oe=>{$={x:Math.abs(Math.round(Oe.pageX)-(ee.current?.x??0)),y:Math.abs(Math.round(Oe.pageY)-(ee.current?.y??0))}},pe=Oe=>{$.x<=10&&$.y<=10?Oe.preventDefault():j.contains(Oe.target)||W(!1),document.removeEventListener("pointermove",Se),ee.current=null};return ee.current!==null&&(document.addEventListener("pointermove",Se),document.addEventListener("pointerup",pe,{capture:!0,once:!0})),()=>{document.removeEventListener("pointermove",Se),document.removeEventListener("pointerup",pe,{capture:!0})}}},[j,W,ee]),x.useEffect(()=>{const $=()=>W(!1);return window.addEventListener("blur",$),window.addEventListener("resize",$),()=>{window.removeEventListener("blur",$),window.removeEventListener("resize",$)}},[W]);const[J,N]=m0($=>{const Se=le().filter(Ce=>!Ce.disabled),pe=Se.find(Ce=>Ce.ref.current===document.activeElement),Oe=h0(Se,$,pe);Oe&&setTimeout(()=>Oe.ref.current.focus())}),F=x.useCallback(($,Se,pe)=>{const Oe=!de.current&&!pe;(O.value!==void 0&&O.value===Se||Oe)&&(ae($),Oe&&(de.current=!0))},[O.value]),te=x.useCallback(()=>j?.focus(),[j]),ne=x.useCallback(($,Se,pe)=>{const Oe=!de.current&&!pe;(O.value!==void 0&&O.value===Se||Oe)&&H($)},[O.value]),ie=o==="popper"?hd:Jx,se=ie===hd?{side:p,sideOffset:h,align:m,alignOffset:v,arrowPadding:y,collisionBoundary:w,collisionPadding:_,sticky:E,hideWhenDetached:S,avoidCollisions:A}:{};return b.jsx(Zx,{scope:r,content:j,viewport:k,onViewportChange:Y,itemRefCallback:F,selectedItem:I,onItemLeave:te,itemTextRefCallback:ne,focusSelectedItem:Q,selectedItemText:ce,position:o,isPositioned:ve,searchRef:J,children:b.jsx(Zd,{as:WO,allowPinchZoom:!0,children:b.jsx(qd,{asChild:!0,trapped:O.open,onMountAutoFocus:$=>{$.preventDefault()},onUnmountAutoFocus:ze(c,$=>{O.trigger?.focus({preventScroll:!0}),$.preventDefault()}),children:b.jsx(Bd,{asChild:!0,disableOutsidePointerEvents:!0,onEscapeKeyDown:u,onPointerDownOutside:d,onFocusOutside:$=>$.preventDefault(),onDismiss:()=>O.onOpenChange(!1),children:b.jsx(ie,{role:"listbox",id:O.contentId,"data-state":O.open?"open":"closed",dir:O.dir,onContextMenu:$=>$.preventDefault(),...T,...se,onPlaced:()=>re(!0),ref:U,style:{display:"flex",flexDirection:"column",outline:"none",...T.style},onKeyDown:ze(T.onKeyDown,$=>{const Se=$.ctrlKey||$.altKey||$.metaKey;if($.key==="Tab"&&$.preventDefault(),!Se&&$.key.length===1&&N($.key),["ArrowUp","ArrowDown","Home","End"].includes($.key)){let Oe=le().filter(Ce=>!Ce.disabled).map(Ce=>Ce.ref.current);if(["ArrowUp","End"].includes($.key)&&(Oe=Oe.slice().reverse()),["ArrowUp","ArrowDown"].includes($.key)){const Ce=$.target,ke=Oe.indexOf(Ce);Oe=Oe.slice(ke+1)}setTimeout(()=>M(Oe)),$.preventDefault()}})})})})})})});Wx.displayName=ZO;var JO="SelectItemAlignedPosition",Jx=x.forwardRef((n,l)=>{const{__scopeSelect:r,onPlaced:o,...c}=n,u=Ja(jl,r),d=$a(jl,r),[p,h]=x.useState(null),[m,v]=x.useState(null),y=qe(l,U=>v(U)),w=as(r),_=x.useRef(!1),E=x.useRef(!0),{viewport:S,selectedItem:A,selectedItemText:T,focusSelectedItem:O}=d,j=x.useCallback(()=>{if(u.trigger&&u.valueNode&&p&&m&&S&&A&&T){const U=u.trigger.getBoundingClientRect(),I=m.getBoundingClientRect(),ae=u.valueNode.getBoundingClientRect(),ce=T.getBoundingClientRect();if(u.dir!=="rtl"){const Ce=ce.left-I.left,ke=ae.left-Ce,Ke=U.left-ke,nt=U.width+Ke,_n=Math.max(nt,I.width),Cn=window.innerWidth-yn,ha=sd(ke,[yn,Math.max(yn,Cn-_n)]);p.style.minWidth=nt+"px",p.style.left=ha+"px"}else{const Ce=I.right-ce.right,ke=window.innerWidth-ae.right-Ce,Ke=window.innerWidth-U.right-ke,nt=U.width+Ke,_n=Math.max(nt,I.width),Cn=window.innerWidth-yn,ha=sd(ke,[yn,Math.max(yn,Cn-_n)]);p.style.minWidth=nt+"px",p.style.right=ha+"px"}const H=w(),le=window.innerHeight-yn*2,ve=S.scrollHeight,re=window.getComputedStyle(m),de=parseInt(re.borderTopWidth,10),M=parseInt(re.paddingTop,10),Q=parseInt(re.borderBottomWidth,10),W=parseInt(re.paddingBottom,10),ee=de+M+ve+W+Q,J=Math.min(A.offsetHeight*5,ee),N=window.getComputedStyle(S),F=parseInt(N.paddingTop,10),te=parseInt(N.paddingBottom,10),ne=U.top+U.height/2-yn,ie=le-ne,se=A.offsetHeight/2,$=A.offsetTop+se,Se=de+M+$,pe=ee-Se;if(Se<=ne){const Ce=H.length>0&&A===H[H.length-1].ref.current;p.style.bottom="0px";const ke=m.clientHeight-S.offsetTop-S.offsetHeight,Ke=Math.max(ie,se+(Ce?te:0)+ke+Q),nt=Se+Ke;p.style.height=nt+"px"}else{const Ce=H.length>0&&A===H[0].ref.current;p.style.top="0px";const Ke=Math.max(ne,de+S.offsetTop+(Ce?F:0)+se)+pe;p.style.height=Ke+"px",S.scrollTop=Se-ne+S.offsetTop}p.style.margin=`${yn}px 0`,p.style.minHeight=J+"px",p.style.maxHeight=le+"px",o?.(),requestAnimationFrame(()=>_.current=!0)}},[w,u.trigger,u.valueNode,p,m,S,A,T,u.dir,o]);yt(()=>j(),[j]);const[z,k]=x.useState();yt(()=>{m&&k(window.getComputedStyle(m).zIndex)},[m]);const Y=x.useCallback(U=>{U&&E.current===!0&&(j(),O?.(),E.current=!1)},[j,O]);return b.jsx(eR,{scope:r,contentWrapper:p,shouldExpandOnScrollRef:_,onScrollButtonChange:Y,children:b.jsx("div",{ref:h,style:{display:"flex",flexDirection:"column",position:"fixed",zIndex:z},children:b.jsx(Te.div,{...c,ref:y,style:{boxSizing:"border-box",maxHeight:"100%",...c.style}})})})});Jx.displayName=JO;var $O="SelectPopperPosition",hd=x.forwardRef((n,l)=>{const{__scopeSelect:r,align:o="start",collisionPadding:c=yn,...u}=n,d=ls(r);return b.jsx(GT,{...d,...u,ref:l,align:o,collisionPadding:c,style:{boxSizing:"border-box",...u.style,"--radix-select-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-select-content-available-width":"var(--radix-popper-available-width)","--radix-select-content-available-height":"var(--radix-popper-available-height)","--radix-select-trigger-width":"var(--radix-popper-anchor-width)","--radix-select-trigger-height":"var(--radix-popper-anchor-height)"}})});hd.displayName=$O;var[eR,Wd]=Li(jl,{}),vd="SelectViewport",$x=x.forwardRef((n,l)=>{const{__scopeSelect:r,nonce:o,...c}=n,u=$a(vd,r),d=Wd(vd,r),p=qe(l,u.onViewportChange),h=x.useRef(0);return b.jsxs(b.Fragment,{children:[b.jsx("style",{dangerouslySetInnerHTML:{__html:"[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}"},nonce:o}),b.jsx(ns.Slot,{scope:r,children:b.jsx(Te.div,{"data-radix-select-viewport":"",role:"presentation",...c,ref:p,style:{position:"relative",flex:1,overflow:"hidden auto",...c.style},onScroll:ze(c.onScroll,m=>{const v=m.currentTarget,{contentWrapper:y,shouldExpandOnScrollRef:w}=d;if(w?.current&&y){const _=Math.abs(h.current-v.scrollTop);if(_>0){const E=window.innerHeight-yn*2,S=parseFloat(y.style.minHeight),A=parseFloat(y.style.height),T=Math.max(S,A);if(T0?z:0,y.style.justifyContent="flex-end")}}}h.current=v.scrollTop})})})]})});$x.displayName=vd;var e0="SelectGroup",[tR,nR]=Li(e0),aR=x.forwardRef((n,l)=>{const{__scopeSelect:r,...o}=n,c=Xa();return b.jsx(tR,{scope:r,id:c,children:b.jsx(Te.div,{role:"group","aria-labelledby":c,...o,ref:l})})});aR.displayName=e0;var t0="SelectLabel",n0=x.forwardRef((n,l)=>{const{__scopeSelect:r,...o}=n,c=nR(t0,r);return b.jsx(Te.div,{id:c.id,...o,ref:l})});n0.displayName=t0;var Hc="SelectItem",[lR,a0]=Li(Hc),l0=x.forwardRef((n,l)=>{const{__scopeSelect:r,value:o,disabled:c=!1,textValue:u,...d}=n,p=Ja(Hc,r),h=$a(Hc,r),m=p.value===o,[v,y]=x.useState(u??""),[w,_]=x.useState(!1),E=qe(l,O=>h.itemRefCallback?.(O,o,c)),S=Xa(),A=x.useRef("touch"),T=()=>{c||(p.onValueChange(o),p.onOpenChange(!1))};if(o==="")throw new Error("A must have a value prop that is not an empty string. This is because the Select value can be set to an empty string to clear the selection and show the placeholder.");return b.jsx(lR,{scope:r,value:o,disabled:c,textId:S,isSelected:m,onItemTextChange:x.useCallback(O=>{y(j=>j||(O?.textContent??"").trim())},[]),children:b.jsx(ns.ItemSlot,{scope:r,value:o,disabled:c,textValue:v,children:b.jsx(Te.div,{role:"option","aria-labelledby":S,"data-highlighted":w?"":void 0,"aria-selected":m&&w,"data-state":m?"checked":"unchecked","aria-disabled":c||void 0,"data-disabled":c?"":void 0,tabIndex:c?void 0:-1,...d,ref:E,onFocus:ze(d.onFocus,()=>_(!0)),onBlur:ze(d.onBlur,()=>_(!1)),onClick:ze(d.onClick,()=>{A.current!=="mouse"&&T()}),onPointerUp:ze(d.onPointerUp,()=>{A.current==="mouse"&&T()}),onPointerDown:ze(d.onPointerDown,O=>{A.current=O.pointerType}),onPointerMove:ze(d.onPointerMove,O=>{A.current=O.pointerType,c?h.onItemLeave?.():A.current==="mouse"&&O.currentTarget.focus({preventScroll:!0})}),onPointerLeave:ze(d.onPointerLeave,O=>{O.currentTarget===document.activeElement&&h.onItemLeave?.()}),onKeyDown:ze(d.onKeyDown,O=>{h.searchRef?.current!==""&&O.key===" "||(GO.includes(O.key)&&T(),O.key===" "&&O.preventDefault())})})})})});l0.displayName=Hc;var qr="SelectItemText",i0=x.forwardRef((n,l)=>{const{__scopeSelect:r,className:o,style:c,...u}=n,d=Ja(qr,r),p=$a(qr,r),h=a0(qr,r),m=IO(qr,r),[v,y]=x.useState(null),w=qe(l,T=>y(T),h.onItemTextChange,T=>p.itemTextRefCallback?.(T,h.value,h.disabled)),_=v?.textContent,E=x.useMemo(()=>b.jsx("option",{value:h.value,disabled:h.disabled,children:_},h.value),[h.disabled,h.value,_]),{onNativeOptionAdd:S,onNativeOptionRemove:A}=m;return yt(()=>(S(E),()=>A(E)),[S,A,E]),b.jsxs(b.Fragment,{children:[b.jsx(Te.span,{id:h.textId,...u,ref:w}),h.isSelected&&d.valueNode&&!d.valueNodeHasChildren?Kr.createPortal(u.children,d.valueNode):null]})});i0.displayName=qr;var r0="SelectItemIndicator",o0=x.forwardRef((n,l)=>{const{__scopeSelect:r,...o}=n;return a0(r0,r).isSelected?b.jsx(Te.span,{"aria-hidden":!0,...o,ref:l}):null});o0.displayName=r0;var gd="SelectScrollUpButton",c0=x.forwardRef((n,l)=>{const r=$a(gd,n.__scopeSelect),o=Wd(gd,n.__scopeSelect),[c,u]=x.useState(!1),d=qe(l,o.onScrollButtonChange);return yt(()=>{if(r.viewport&&r.isPositioned){let p=function(){const m=h.scrollTop>0;u(m)};const h=r.viewport;return p(),h.addEventListener("scroll",p),()=>h.removeEventListener("scroll",p)}},[r.viewport,r.isPositioned]),c?b.jsx(u0,{...n,ref:d,onAutoScroll:()=>{const{viewport:p,selectedItem:h}=r;p&&h&&(p.scrollTop=p.scrollTop-h.offsetHeight)}}):null});c0.displayName=gd;var yd="SelectScrollDownButton",s0=x.forwardRef((n,l)=>{const r=$a(yd,n.__scopeSelect),o=Wd(yd,n.__scopeSelect),[c,u]=x.useState(!1),d=qe(l,o.onScrollButtonChange);return yt(()=>{if(r.viewport&&r.isPositioned){let p=function(){const m=h.scrollHeight-h.clientHeight,v=Math.ceil(h.scrollTop)h.removeEventListener("scroll",p)}},[r.viewport,r.isPositioned]),c?b.jsx(u0,{...n,ref:d,onAutoScroll:()=>{const{viewport:p,selectedItem:h}=r;p&&h&&(p.scrollTop=p.scrollTop+h.offsetHeight)}}):null});s0.displayName=yd;var u0=x.forwardRef((n,l)=>{const{__scopeSelect:r,onAutoScroll:o,...c}=n,u=$a("SelectScrollButton",r),d=x.useRef(null),p=as(r),h=x.useCallback(()=>{d.current!==null&&(window.clearInterval(d.current),d.current=null)},[]);return x.useEffect(()=>()=>h(),[h]),yt(()=>{p().find(v=>v.ref.current===document.activeElement)?.ref.current?.scrollIntoView({block:"nearest"})},[p]),b.jsx(Te.div,{"aria-hidden":!0,...c,ref:l,style:{flexShrink:0,...c.style},onPointerDown:ze(c.onPointerDown,()=>{d.current===null&&(d.current=window.setInterval(o,50))}),onPointerMove:ze(c.onPointerMove,()=>{u.onItemLeave?.(),d.current===null&&(d.current=window.setInterval(o,50))}),onPointerLeave:ze(c.onPointerLeave,()=>{h()})})}),iR="SelectSeparator",f0=x.forwardRef((n,l)=>{const{__scopeSelect:r,...o}=n;return b.jsx(Te.div,{"aria-hidden":!0,...o,ref:l})});f0.displayName=iR;var bd="SelectArrow",rR=x.forwardRef((n,l)=>{const{__scopeSelect:r,...o}=n,c=ls(r),u=Ja(bd,r),d=$a(bd,r);return u.open&&d.position==="popper"?b.jsx(YT,{...c,...o,ref:l}):null});rR.displayName=bd;var oR="SelectBubbleInput",d0=x.forwardRef(({__scopeSelect:n,value:l,...r},o)=>{const c=x.useRef(null),u=qe(o,c),d=jx(l);return x.useEffect(()=>{const p=c.current;if(!p)return;const h=window.HTMLSelectElement.prototype,v=Object.getOwnPropertyDescriptor(h,"value").set;if(d!==l&&v){const y=new Event("change",{bubbles:!0});v.call(p,l),p.dispatchEvent(y)}},[d,l]),b.jsx(Te.select,{...r,style:{...Dx,...r.style},ref:u,defaultValue:l})});d0.displayName=oR;function p0(n){return n===""||n===void 0}function m0(n){const l=Bt(n),r=x.useRef(""),o=x.useRef(0),c=x.useCallback(d=>{const p=r.current+d;l(p),(function h(m){r.current=m,window.clearTimeout(o.current),m!==""&&(o.current=window.setTimeout(()=>h(""),1e3))})(p)},[l]),u=x.useCallback(()=>{r.current="",window.clearTimeout(o.current)},[]);return x.useEffect(()=>()=>window.clearTimeout(o.current),[]),[r,c,u]}function h0(n,l,r){const c=l.length>1&&Array.from(l).every(m=>m===l[0])?l[0]:l,u=r?n.indexOf(r):-1;let d=cR(n,Math.max(u,0));c.length===1&&(d=d.filter(m=>m!==r));const h=d.find(m=>m.textValue.toLowerCase().startsWith(c.toLowerCase()));return h!==r?h:void 0}function cR(n,l){return n.map((r,o)=>n[(l+o)%n.length])}var sR=Px,v0=Yx,uR=Xx,fR=Ix,dR=Qx,g0=Kx,pR=$x,y0=n0,b0=l0,mR=i0,hR=o0,x0=c0,S0=s0,w0=f0;const E0=sR,_0=uR,Jd=x.forwardRef(({className:n,children:l,...r},o)=>b.jsxs(v0,{ref:o,className:Be("flex h-11 w-full items-center justify-between rounded-2xl border border-line bg-paper px-4 py-2 text-sm text-ink shadow-[inset_0_1px_0_color-mix(in_oklab,var(--color-paper)_40%,white)] placeholder:text-muted focus:outline-none focus:ring-2 focus:ring-clay/20 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",n),...r,children:[l,b.jsx(fR,{asChild:!0,children:b.jsx(Rd,{className:"h-4 w-4 text-muted"})})]}));Jd.displayName=v0.displayName;const C0=x.forwardRef(({className:n,...l},r)=>b.jsx(x0,{ref:r,className:Be("flex cursor-default items-center justify-center py-1 text-muted",n),...l,children:b.jsx(_E,{className:"h-4 w-4"})}));C0.displayName=x0.displayName;const A0=x.forwardRef(({className:n,...l},r)=>b.jsx(S0,{ref:r,className:Be("flex cursor-default items-center justify-center py-1 text-muted",n),...l,children:b.jsx(Rd,{className:"h-4 w-4"})}));A0.displayName=S0.displayName;const $d=x.forwardRef(({className:n,children:l,position:r="popper",...o},c)=>b.jsx(dR,{children:b.jsxs(g0,{ref:c,className:Be("relative z-50 max-h-80 min-w-[8rem] overflow-hidden rounded-3xl border border-line bg-paper shadow-[0_28px_80px_-28px_color-mix(in_oklab,var(--color-ink)_20%,transparent)] data-[state=open]:animate-in data-[state=closed]:animate-out",r==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1",n),position:r,...o,children:[b.jsx(C0,{}),b.jsx(pR,{className:Be("p-1.5",r==="popper"&&"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),children:l}),b.jsx(A0,{})]})}));$d.displayName=g0.displayName;const vR=x.forwardRef(({className:n,...l},r)=>b.jsx(y0,{ref:r,className:Be("px-8 py-2 text-xs font-medium text-muted",n),...l}));vR.displayName=y0.displayName;const ep=x.forwardRef(({className:n,children:l,...r},o)=>b.jsxs(b0,{ref:o,className:Be("relative flex w-full cursor-default select-none items-center rounded-2xl py-2.5 pl-8 pr-3 text-sm text-ink outline-none transition data-[disabled]:pointer-events-none data-[disabled]:opacity-40 data-[highlighted]:bg-sand",n),...r,children:[b.jsx("span",{className:"absolute left-3 flex h-3.5 w-3.5 items-center justify-center",children:b.jsx(hR,{children:b.jsx(SE,{className:"h-4 w-4 text-clay"})})}),b.jsx(mR,{children:l})]}));ep.displayName=b0.displayName;const gR=x.forwardRef(({className:n,...l},r)=>b.jsx(w0,{ref:r,className:Be("-mx-1 my-1 h-px bg-line",n),...l}));gR.displayName=w0.displayName;const xd=x.forwardRef(({className:n,...l},r)=>b.jsx("textarea",{className:Be("flex min-h-[124px] w-full rounded-[1.5rem] border border-line bg-paper px-4 py-3 text-sm text-ink shadow-[inset_0_1px_0_color-mix(in_oklab,var(--color-paper)_40%,white)] transition placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-clay/20 disabled:cursor-not-allowed disabled:opacity-50",n),ref:r,...l}));xd.displayName="Textarea";function yR({onOpenAdvanced:n}){const{handleGenerate:l}=kd(),{availableModels:r,serverStatus:o,setSettings:c,settings:u,status:d}=Ia(Di(w=>({availableModels:w.availableModels,serverStatus:w.serverStatus,setSettings:w.setSettings,settings:w.settings,status:w.status}))),[p,h]=x.useState(!1),m=x.useMemo(()=>r.map(w=>({label:w.name,value:w.path})),[r]),v=r.find(w=>w.path===u.model_path),y=w=>{const _=r.find(E=>E.path===w);if(!_){c({model_path:w});return}c(kb(_,r))};return b.jsxs("section",{className:"relative overflow-hidden rounded-[2.1rem] border border-line bg-paper/97 px-5 py-5 shadow-[0_20px_48px_-36px_color-mix(in_oklab,var(--color-ink)_16%,transparent)] sm:px-7 sm:py-7",children:[b.jsx("div",{className:"pointer-events-none absolute inset-x-0 top-0 h-28 bg-[radial-gradient(circle_at_top_left,color-mix(in_oklab,var(--color-oat)_86%,transparent),transparent_66%)]"}),b.jsxs("div",{className:"relative flex flex-col gap-6",children:[b.jsxs("div",{className:"grid gap-5 lg:grid-cols-[minmax(0,1.2fr)_minmax(0,1fr)] lg:items-start",children:[b.jsxs("div",{className:"space-y-2",children:[b.jsxs("div",{className:"inline-flex items-center gap-2 text-[11px] uppercase tracking-[0.16em] text-muted",children:[b.jsx(ad,{className:"h-3.5 w-3.5 text-clay"}),"Generate"]}),b.jsxs("div",{className:"space-y-1.5",children:[b.jsx("h1",{className:"max-w-4xl font-serif text-[clamp(2.75rem,5.2vw,5rem)] leading-[0.92] tracking-[-0.055em] text-ink",children:"Generate the next frame."}),b.jsx("p",{className:"max-w-3xl text-[15px] leading-6 text-muted",children:"Choose a model, write the prompt, and run. Advanced controls stay out of the way until you need them."})]}),b.jsxs("div",{className:"flex flex-wrap items-center gap-2 pt-2",children:[b.jsxs(Tl,{variant:"outline",size:"sm",onClick:n,children:[b.jsx(UE,{className:"h-4 w-4"}),"Advanced"]}),o?null:b.jsx("span",{className:"rounded-full bg-sand px-3 py-1.5 text-xs text-clay-strong",children:"Engine offline"})]})]}),b.jsxs("div",{className:"space-y-3 rounded-[1.75rem] border border-line/75 bg-canvas/34 p-4 lg:p-5",children:[b.jsx(Ei,{children:"Model"}),b.jsxs(E0,{onValueChange:y,value:u.model_path||void 0,children:[b.jsx(Jd,{className:"h-12 rounded-[1.2rem] border-line/80 bg-paper",children:b.jsx(_0,{placeholder:"Select a model"})}),b.jsx($d,{children:m.length>0?m.map(w=>b.jsx(ep,{value:w.value,children:w.label},w.value)):b.jsx("div",{className:"px-4 py-3 text-sm text-muted",children:"No models available"})})]}),b.jsx("p",{className:"text-xs leading-5 text-muted",children:v?`${v.type} ready`:"Models load automatically when the backend is available."})]})]}),b.jsxs("div",{className:"grid gap-4 lg:grid-cols-[minmax(0,1fr)_15rem] lg:items-stretch",children:[b.jsxs("div",{className:"space-y-3 rounded-[1.9rem] border border-line/65 bg-canvas/48 p-4 lg:p-5",children:[b.jsxs("div",{className:"flex items-center justify-between gap-3",children:[b.jsx(Ei,{children:"Prompt"}),b.jsx("button",{type:"button",onClick:()=>h(w=>!w),className:"text-xs font-medium text-muted transition hover:text-ink",children:p?"Hide negative prompt":"Add negative prompt"})]}),b.jsx(xd,{className:"min-h-[172px] rounded-[1.5rem] border-line/70 bg-paper px-5 py-4 text-[16px] leading-7 shadow-none",placeholder:"Portrait lit by late afternoon sun, soft grain, calm expression, editorial composition...",value:u.prompt,onChange:w=>c({prompt:w.currentTarget.value})}),p?b.jsxs("div",{className:"grid gap-2 border-t border-line/70 pt-3",children:[b.jsx(Ei,{children:"Negative prompt"}),b.jsx(xd,{className:"min-h-[108px] rounded-[1.4rem] border-line/70 bg-paper shadow-none",placeholder:"Things to avoid: low detail, extra limbs, blown highlights...",value:u.negative_prompt,onChange:w=>c({negative_prompt:w.currentTarget.value})})]}):null]}),b.jsxs("div",{className:"flex flex-col gap-3 rounded-[1.75rem] border border-line/75 bg-ink/[0.04] p-4 lg:justify-between",children:[b.jsx(Ei,{children:"Prompt"}),b.jsxs("div",{className:"space-y-2",children:[b.jsx("p",{className:"font-serif text-[1.35rem] leading-tight tracking-[-0.03em] text-ink",children:"Run the current prompt"}),b.jsx("p",{className:"text-xs leading-5 text-muted",children:o?"The next run uses the current prompt and advanced settings.":"Reconnect the engine before generating."})]}),b.jsx(Tl,{className:"h-14 w-full text-[15px]",size:"lg",variant:d==="generating"?"destructive":"default",onClick:()=>{l()},children:d==="generating"?"Interrupt":"Generate"})]})]}),d==="error"?b.jsx("p",{className:"text-sm text-clay-strong",children:"Generation failed. Check the backend logs, then try again."}):null]})]})}var If={exports:{}},Qf,Dy;function bR(){if(Dy)return Qf;Dy=1;var n="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";return Qf=n,Qf}var Kf,My;function xR(){if(My)return Kf;My=1;var n=bR();function l(){}function r(){}return r.resetWarningCache=l,Kf=function(){function o(d,p,h,m,v,y){if(y!==n){var w=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw w.name="Invariant Violation",w}}o.isRequired=o;function c(){return o}var u={array:o,bigint:o,bool:o,func:o,number:o,object:o,string:o,symbol:o,any:o,arrayOf:c,element:o,elementType:o,instanceOf:c,node:o,objectOf:c,oneOf:c,oneOfType:c,shape:c,exact:c,checkPropTypes:r,resetWarningCache:l};return u.PropTypes=u,u},Kf}var zy;function SR(){return zy||(zy=1,If.exports=xR()()),If.exports}var wR=SR();const Ie=Gr(wR),ER=new Map([["1km","application/vnd.1000minds.decision-model+xml"],["3dml","text/vnd.in3d.3dml"],["3ds","image/x-3ds"],["3g2","video/3gpp2"],["3gp","video/3gp"],["3gpp","video/3gpp"],["3mf","model/3mf"],["7z","application/x-7z-compressed"],["7zip","application/x-7z-compressed"],["123","application/vnd.lotus-1-2-3"],["aab","application/x-authorware-bin"],["aac","audio/x-acc"],["aam","application/x-authorware-map"],["aas","application/x-authorware-seg"],["abw","application/x-abiword"],["ac","application/vnd.nokia.n-gage.ac+xml"],["ac3","audio/ac3"],["acc","application/vnd.americandynamics.acc"],["ace","application/x-ace-compressed"],["acu","application/vnd.acucobol"],["acutc","application/vnd.acucorp"],["adp","audio/adpcm"],["aep","application/vnd.audiograph"],["afm","application/x-font-type1"],["afp","application/vnd.ibm.modcap"],["ahead","application/vnd.ahead.space"],["ai","application/pdf"],["aif","audio/x-aiff"],["aifc","audio/x-aiff"],["aiff","audio/x-aiff"],["air","application/vnd.adobe.air-application-installer-package+zip"],["ait","application/vnd.dvb.ait"],["ami","application/vnd.amiga.ami"],["amr","audio/amr"],["apk","application/vnd.android.package-archive"],["apng","image/apng"],["appcache","text/cache-manifest"],["application","application/x-ms-application"],["apr","application/vnd.lotus-approach"],["arc","application/x-freearc"],["arj","application/x-arj"],["asc","application/pgp-signature"],["asf","video/x-ms-asf"],["asm","text/x-asm"],["aso","application/vnd.accpac.simply.aso"],["asx","video/x-ms-asf"],["atc","application/vnd.acucorp"],["atom","application/atom+xml"],["atomcat","application/atomcat+xml"],["atomdeleted","application/atomdeleted+xml"],["atomsvc","application/atomsvc+xml"],["atx","application/vnd.antix.game-component"],["au","audio/x-au"],["avi","video/x-msvideo"],["avif","image/avif"],["aw","application/applixware"],["azf","application/vnd.airzip.filesecure.azf"],["azs","application/vnd.airzip.filesecure.azs"],["azv","image/vnd.airzip.accelerator.azv"],["azw","application/vnd.amazon.ebook"],["b16","image/vnd.pco.b16"],["bat","application/x-msdownload"],["bcpio","application/x-bcpio"],["bdf","application/x-font-bdf"],["bdm","application/vnd.syncml.dm+wbxml"],["bdoc","application/x-bdoc"],["bed","application/vnd.realvnc.bed"],["bh2","application/vnd.fujitsu.oasysprs"],["bin","application/octet-stream"],["blb","application/x-blorb"],["blorb","application/x-blorb"],["bmi","application/vnd.bmi"],["bmml","application/vnd.balsamiq.bmml+xml"],["bmp","image/bmp"],["book","application/vnd.framemaker"],["box","application/vnd.previewsystems.box"],["boz","application/x-bzip2"],["bpk","application/octet-stream"],["bpmn","application/octet-stream"],["bsp","model/vnd.valve.source.compiled-map"],["btif","image/prs.btif"],["buffer","application/octet-stream"],["bz","application/x-bzip"],["bz2","application/x-bzip2"],["c","text/x-c"],["c4d","application/vnd.clonk.c4group"],["c4f","application/vnd.clonk.c4group"],["c4g","application/vnd.clonk.c4group"],["c4p","application/vnd.clonk.c4group"],["c4u","application/vnd.clonk.c4group"],["c11amc","application/vnd.cluetrust.cartomobile-config"],["c11amz","application/vnd.cluetrust.cartomobile-config-pkg"],["cab","application/vnd.ms-cab-compressed"],["caf","audio/x-caf"],["cap","application/vnd.tcpdump.pcap"],["car","application/vnd.curl.car"],["cat","application/vnd.ms-pki.seccat"],["cb7","application/x-cbr"],["cba","application/x-cbr"],["cbr","application/x-cbr"],["cbt","application/x-cbr"],["cbz","application/x-cbr"],["cc","text/x-c"],["cco","application/x-cocoa"],["cct","application/x-director"],["ccxml","application/ccxml+xml"],["cdbcmsg","application/vnd.contact.cmsg"],["cda","application/x-cdf"],["cdf","application/x-netcdf"],["cdfx","application/cdfx+xml"],["cdkey","application/vnd.mediastation.cdkey"],["cdmia","application/cdmi-capability"],["cdmic","application/cdmi-container"],["cdmid","application/cdmi-domain"],["cdmio","application/cdmi-object"],["cdmiq","application/cdmi-queue"],["cdr","application/cdr"],["cdx","chemical/x-cdx"],["cdxml","application/vnd.chemdraw+xml"],["cdy","application/vnd.cinderella"],["cer","application/pkix-cert"],["cfs","application/x-cfs-compressed"],["cgm","image/cgm"],["chat","application/x-chat"],["chm","application/vnd.ms-htmlhelp"],["chrt","application/vnd.kde.kchart"],["cif","chemical/x-cif"],["cii","application/vnd.anser-web-certificate-issue-initiation"],["cil","application/vnd.ms-artgalry"],["cjs","application/node"],["cla","application/vnd.claymore"],["class","application/octet-stream"],["clkk","application/vnd.crick.clicker.keyboard"],["clkp","application/vnd.crick.clicker.palette"],["clkt","application/vnd.crick.clicker.template"],["clkw","application/vnd.crick.clicker.wordbank"],["clkx","application/vnd.crick.clicker"],["clp","application/x-msclip"],["cmc","application/vnd.cosmocaller"],["cmdf","chemical/x-cmdf"],["cml","chemical/x-cml"],["cmp","application/vnd.yellowriver-custom-menu"],["cmx","image/x-cmx"],["cod","application/vnd.rim.cod"],["coffee","text/coffeescript"],["com","application/x-msdownload"],["conf","text/plain"],["cpio","application/x-cpio"],["cpp","text/x-c"],["cpt","application/mac-compactpro"],["crd","application/x-mscardfile"],["crl","application/pkix-crl"],["crt","application/x-x509-ca-cert"],["crx","application/x-chrome-extension"],["cryptonote","application/vnd.rig.cryptonote"],["csh","application/x-csh"],["csl","application/vnd.citationstyles.style+xml"],["csml","chemical/x-csml"],["csp","application/vnd.commonspace"],["csr","application/octet-stream"],["css","text/css"],["cst","application/x-director"],["csv","text/csv"],["cu","application/cu-seeme"],["curl","text/vnd.curl"],["cww","application/prs.cww"],["cxt","application/x-director"],["cxx","text/x-c"],["dae","model/vnd.collada+xml"],["daf","application/vnd.mobius.daf"],["dart","application/vnd.dart"],["dataless","application/vnd.fdsn.seed"],["davmount","application/davmount+xml"],["dbf","application/vnd.dbf"],["dbk","application/docbook+xml"],["dcr","application/x-director"],["dcurl","text/vnd.curl.dcurl"],["dd2","application/vnd.oma.dd2+xml"],["ddd","application/vnd.fujixerox.ddd"],["ddf","application/vnd.syncml.dmddf+xml"],["dds","image/vnd.ms-dds"],["deb","application/x-debian-package"],["def","text/plain"],["deploy","application/octet-stream"],["der","application/x-x509-ca-cert"],["dfac","application/vnd.dreamfactory"],["dgc","application/x-dgc-compressed"],["dic","text/x-c"],["dir","application/x-director"],["dis","application/vnd.mobius.dis"],["disposition-notification","message/disposition-notification"],["dist","application/octet-stream"],["distz","application/octet-stream"],["djv","image/vnd.djvu"],["djvu","image/vnd.djvu"],["dll","application/octet-stream"],["dmg","application/x-apple-diskimage"],["dmn","application/octet-stream"],["dmp","application/vnd.tcpdump.pcap"],["dms","application/octet-stream"],["dna","application/vnd.dna"],["doc","application/msword"],["docm","application/vnd.ms-word.template.macroEnabled.12"],["docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document"],["dot","application/msword"],["dotm","application/vnd.ms-word.template.macroEnabled.12"],["dotx","application/vnd.openxmlformats-officedocument.wordprocessingml.template"],["dp","application/vnd.osgi.dp"],["dpg","application/vnd.dpgraph"],["dra","audio/vnd.dra"],["drle","image/dicom-rle"],["dsc","text/prs.lines.tag"],["dssc","application/dssc+der"],["dtb","application/x-dtbook+xml"],["dtd","application/xml-dtd"],["dts","audio/vnd.dts"],["dtshd","audio/vnd.dts.hd"],["dump","application/octet-stream"],["dvb","video/vnd.dvb.file"],["dvi","application/x-dvi"],["dwd","application/atsc-dwd+xml"],["dwf","model/vnd.dwf"],["dwg","image/vnd.dwg"],["dxf","image/vnd.dxf"],["dxp","application/vnd.spotfire.dxp"],["dxr","application/x-director"],["ear","application/java-archive"],["ecelp4800","audio/vnd.nuera.ecelp4800"],["ecelp7470","audio/vnd.nuera.ecelp7470"],["ecelp9600","audio/vnd.nuera.ecelp9600"],["ecma","application/ecmascript"],["edm","application/vnd.novadigm.edm"],["edx","application/vnd.novadigm.edx"],["efif","application/vnd.picsel"],["ei6","application/vnd.pg.osasli"],["elc","application/octet-stream"],["emf","image/emf"],["eml","message/rfc822"],["emma","application/emma+xml"],["emotionml","application/emotionml+xml"],["emz","application/x-msmetafile"],["eol","audio/vnd.digital-winds"],["eot","application/vnd.ms-fontobject"],["eps","application/postscript"],["epub","application/epub+zip"],["es","application/ecmascript"],["es3","application/vnd.eszigno3+xml"],["esa","application/vnd.osgi.subsystem"],["esf","application/vnd.epson.esf"],["et3","application/vnd.eszigno3+xml"],["etx","text/x-setext"],["eva","application/x-eva"],["evy","application/x-envoy"],["exe","application/octet-stream"],["exi","application/exi"],["exp","application/express"],["exr","image/aces"],["ext","application/vnd.novadigm.ext"],["ez","application/andrew-inset"],["ez2","application/vnd.ezpix-album"],["ez3","application/vnd.ezpix-package"],["f","text/x-fortran"],["f4v","video/mp4"],["f77","text/x-fortran"],["f90","text/x-fortran"],["fbs","image/vnd.fastbidsheet"],["fcdt","application/vnd.adobe.formscentral.fcdt"],["fcs","application/vnd.isac.fcs"],["fdf","application/vnd.fdf"],["fdt","application/fdt+xml"],["fe_launch","application/vnd.denovo.fcselayout-link"],["fg5","application/vnd.fujitsu.oasysgp"],["fgd","application/x-director"],["fh","image/x-freehand"],["fh4","image/x-freehand"],["fh5","image/x-freehand"],["fh7","image/x-freehand"],["fhc","image/x-freehand"],["fig","application/x-xfig"],["fits","image/fits"],["flac","audio/x-flac"],["fli","video/x-fli"],["flo","application/vnd.micrografx.flo"],["flv","video/x-flv"],["flw","application/vnd.kde.kivio"],["flx","text/vnd.fmi.flexstor"],["fly","text/vnd.fly"],["fm","application/vnd.framemaker"],["fnc","application/vnd.frogans.fnc"],["fo","application/vnd.software602.filler.form+xml"],["for","text/x-fortran"],["fpx","image/vnd.fpx"],["frame","application/vnd.framemaker"],["fsc","application/vnd.fsc.weblaunch"],["fst","image/vnd.fst"],["ftc","application/vnd.fluxtime.clip"],["fti","application/vnd.anser-web-funds-transfer-initiation"],["fvt","video/vnd.fvt"],["fxp","application/vnd.adobe.fxp"],["fxpl","application/vnd.adobe.fxp"],["fzs","application/vnd.fuzzysheet"],["g2w","application/vnd.geoplan"],["g3","image/g3fax"],["g3w","application/vnd.geospace"],["gac","application/vnd.groove-account"],["gam","application/x-tads"],["gbr","application/rpki-ghostbusters"],["gca","application/x-gca-compressed"],["gdl","model/vnd.gdl"],["gdoc","application/vnd.google-apps.document"],["geo","application/vnd.dynageo"],["geojson","application/geo+json"],["gex","application/vnd.geometry-explorer"],["ggb","application/vnd.geogebra.file"],["ggt","application/vnd.geogebra.tool"],["ghf","application/vnd.groove-help"],["gif","image/gif"],["gim","application/vnd.groove-identity-message"],["glb","model/gltf-binary"],["gltf","model/gltf+json"],["gml","application/gml+xml"],["gmx","application/vnd.gmx"],["gnumeric","application/x-gnumeric"],["gpg","application/gpg-keys"],["gph","application/vnd.flographit"],["gpx","application/gpx+xml"],["gqf","application/vnd.grafeq"],["gqs","application/vnd.grafeq"],["gram","application/srgs"],["gramps","application/x-gramps-xml"],["gre","application/vnd.geometry-explorer"],["grv","application/vnd.groove-injector"],["grxml","application/srgs+xml"],["gsf","application/x-font-ghostscript"],["gsheet","application/vnd.google-apps.spreadsheet"],["gslides","application/vnd.google-apps.presentation"],["gtar","application/x-gtar"],["gtm","application/vnd.groove-tool-message"],["gtw","model/vnd.gtw"],["gv","text/vnd.graphviz"],["gxf","application/gxf"],["gxt","application/vnd.geonext"],["gz","application/gzip"],["gzip","application/gzip"],["h","text/x-c"],["h261","video/h261"],["h263","video/h263"],["h264","video/h264"],["hal","application/vnd.hal+xml"],["hbci","application/vnd.hbci"],["hbs","text/x-handlebars-template"],["hdd","application/x-virtualbox-hdd"],["hdf","application/x-hdf"],["heic","image/heic"],["heics","image/heic-sequence"],["heif","image/heif"],["heifs","image/heif-sequence"],["hej2","image/hej2k"],["held","application/atsc-held+xml"],["hh","text/x-c"],["hjson","application/hjson"],["hlp","application/winhlp"],["hpgl","application/vnd.hp-hpgl"],["hpid","application/vnd.hp-hpid"],["hps","application/vnd.hp-hps"],["hqx","application/mac-binhex40"],["hsj2","image/hsj2"],["htc","text/x-component"],["htke","application/vnd.kenameaapp"],["htm","text/html"],["html","text/html"],["hvd","application/vnd.yamaha.hv-dic"],["hvp","application/vnd.yamaha.hv-voice"],["hvs","application/vnd.yamaha.hv-script"],["i2g","application/vnd.intergeo"],["icc","application/vnd.iccprofile"],["ice","x-conference/x-cooltalk"],["icm","application/vnd.iccprofile"],["ico","image/x-icon"],["ics","text/calendar"],["ief","image/ief"],["ifb","text/calendar"],["ifm","application/vnd.shana.informed.formdata"],["iges","model/iges"],["igl","application/vnd.igloader"],["igm","application/vnd.insors.igm"],["igs","model/iges"],["igx","application/vnd.micrografx.igx"],["iif","application/vnd.shana.informed.interchange"],["img","application/octet-stream"],["imp","application/vnd.accpac.simply.imp"],["ims","application/vnd.ms-ims"],["in","text/plain"],["ini","text/plain"],["ink","application/inkml+xml"],["inkml","application/inkml+xml"],["install","application/x-install-instructions"],["iota","application/vnd.astraea-software.iota"],["ipfix","application/ipfix"],["ipk","application/vnd.shana.informed.package"],["irm","application/vnd.ibm.rights-management"],["irp","application/vnd.irepository.package+xml"],["iso","application/x-iso9660-image"],["itp","application/vnd.shana.informed.formtemplate"],["its","application/its+xml"],["ivp","application/vnd.immervision-ivp"],["ivu","application/vnd.immervision-ivu"],["jad","text/vnd.sun.j2me.app-descriptor"],["jade","text/jade"],["jam","application/vnd.jam"],["jar","application/java-archive"],["jardiff","application/x-java-archive-diff"],["java","text/x-java-source"],["jhc","image/jphc"],["jisp","application/vnd.jisp"],["jls","image/jls"],["jlt","application/vnd.hp-jlyt"],["jng","image/x-jng"],["jnlp","application/x-java-jnlp-file"],["joda","application/vnd.joost.joda-archive"],["jp2","image/jp2"],["jpe","image/jpeg"],["jpeg","image/jpeg"],["jpf","image/jpx"],["jpg","image/jpeg"],["jpg2","image/jp2"],["jpgm","video/jpm"],["jpgv","video/jpeg"],["jph","image/jph"],["jpm","video/jpm"],["jpx","image/jpx"],["js","application/javascript"],["json","application/json"],["json5","application/json5"],["jsonld","application/ld+json"],["jsonl","application/jsonl"],["jsonml","application/jsonml+json"],["jsx","text/jsx"],["jxr","image/jxr"],["jxra","image/jxra"],["jxrs","image/jxrs"],["jxs","image/jxs"],["jxsc","image/jxsc"],["jxsi","image/jxsi"],["jxss","image/jxss"],["kar","audio/midi"],["karbon","application/vnd.kde.karbon"],["kdb","application/octet-stream"],["kdbx","application/x-keepass2"],["key","application/x-iwork-keynote-sffkey"],["kfo","application/vnd.kde.kformula"],["kia","application/vnd.kidspiration"],["kml","application/vnd.google-earth.kml+xml"],["kmz","application/vnd.google-earth.kmz"],["kne","application/vnd.kinar"],["knp","application/vnd.kinar"],["kon","application/vnd.kde.kontour"],["kpr","application/vnd.kde.kpresenter"],["kpt","application/vnd.kde.kpresenter"],["kpxx","application/vnd.ds-keypoint"],["ksp","application/vnd.kde.kspread"],["ktr","application/vnd.kahootz"],["ktx","image/ktx"],["ktx2","image/ktx2"],["ktz","application/vnd.kahootz"],["kwd","application/vnd.kde.kword"],["kwt","application/vnd.kde.kword"],["lasxml","application/vnd.las.las+xml"],["latex","application/x-latex"],["lbd","application/vnd.llamagraphics.life-balance.desktop"],["lbe","application/vnd.llamagraphics.life-balance.exchange+xml"],["les","application/vnd.hhe.lesson-player"],["less","text/less"],["lgr","application/lgr+xml"],["lha","application/octet-stream"],["link66","application/vnd.route66.link66+xml"],["list","text/plain"],["list3820","application/vnd.ibm.modcap"],["listafp","application/vnd.ibm.modcap"],["litcoffee","text/coffeescript"],["lnk","application/x-ms-shortcut"],["log","text/plain"],["lostxml","application/lost+xml"],["lrf","application/octet-stream"],["lrm","application/vnd.ms-lrm"],["ltf","application/vnd.frogans.ltf"],["lua","text/x-lua"],["luac","application/x-lua-bytecode"],["lvp","audio/vnd.lucent.voice"],["lwp","application/vnd.lotus-wordpro"],["lzh","application/octet-stream"],["m1v","video/mpeg"],["m2a","audio/mpeg"],["m2v","video/mpeg"],["m3a","audio/mpeg"],["m3u","text/plain"],["m3u8","application/vnd.apple.mpegurl"],["m4a","audio/x-m4a"],["m4p","application/mp4"],["m4s","video/iso.segment"],["m4u","application/vnd.mpegurl"],["m4v","video/x-m4v"],["m13","application/x-msmediaview"],["m14","application/x-msmediaview"],["m21","application/mp21"],["ma","application/mathematica"],["mads","application/mads+xml"],["maei","application/mmt-aei+xml"],["mag","application/vnd.ecowin.chart"],["maker","application/vnd.framemaker"],["man","text/troff"],["manifest","text/cache-manifest"],["map","application/json"],["mar","application/octet-stream"],["markdown","text/markdown"],["mathml","application/mathml+xml"],["mb","application/mathematica"],["mbk","application/vnd.mobius.mbk"],["mbox","application/mbox"],["mc1","application/vnd.medcalcdata"],["mcd","application/vnd.mcd"],["mcurl","text/vnd.curl.mcurl"],["md","text/markdown"],["mdb","application/x-msaccess"],["mdi","image/vnd.ms-modi"],["mdx","text/mdx"],["me","text/troff"],["mesh","model/mesh"],["meta4","application/metalink4+xml"],["metalink","application/metalink+xml"],["mets","application/mets+xml"],["mfm","application/vnd.mfmp"],["mft","application/rpki-manifest"],["mgp","application/vnd.osgeo.mapguide.package"],["mgz","application/vnd.proteus.magazine"],["mid","audio/midi"],["midi","audio/midi"],["mie","application/x-mie"],["mif","application/vnd.mif"],["mime","message/rfc822"],["mj2","video/mj2"],["mjp2","video/mj2"],["mjs","application/javascript"],["mk3d","video/x-matroska"],["mka","audio/x-matroska"],["mkd","text/x-markdown"],["mks","video/x-matroska"],["mkv","video/x-matroska"],["mlp","application/vnd.dolby.mlp"],["mmd","application/vnd.chipnuts.karaoke-mmd"],["mmf","application/vnd.smaf"],["mml","text/mathml"],["mmr","image/vnd.fujixerox.edmics-mmr"],["mng","video/x-mng"],["mny","application/x-msmoney"],["mobi","application/x-mobipocket-ebook"],["mods","application/mods+xml"],["mov","video/quicktime"],["movie","video/x-sgi-movie"],["mp2","audio/mpeg"],["mp2a","audio/mpeg"],["mp3","audio/mpeg"],["mp4","video/mp4"],["mp4a","audio/mp4"],["mp4s","application/mp4"],["mp4v","video/mp4"],["mp21","application/mp21"],["mpc","application/vnd.mophun.certificate"],["mpd","application/dash+xml"],["mpe","video/mpeg"],["mpeg","video/mpeg"],["mpg","video/mpeg"],["mpg4","video/mp4"],["mpga","audio/mpeg"],["mpkg","application/vnd.apple.installer+xml"],["mpm","application/vnd.blueice.multipass"],["mpn","application/vnd.mophun.application"],["mpp","application/vnd.ms-project"],["mpt","application/vnd.ms-project"],["mpy","application/vnd.ibm.minipay"],["mqy","application/vnd.mobius.mqy"],["mrc","application/marc"],["mrcx","application/marcxml+xml"],["ms","text/troff"],["mscml","application/mediaservercontrol+xml"],["mseed","application/vnd.fdsn.mseed"],["mseq","application/vnd.mseq"],["msf","application/vnd.epson.msf"],["msg","application/vnd.ms-outlook"],["msh","model/mesh"],["msi","application/x-msdownload"],["msl","application/vnd.mobius.msl"],["msm","application/octet-stream"],["msp","application/octet-stream"],["msty","application/vnd.muvee.style"],["mtl","model/mtl"],["mts","model/vnd.mts"],["mus","application/vnd.musician"],["musd","application/mmt-usd+xml"],["musicxml","application/vnd.recordare.musicxml+xml"],["mvb","application/x-msmediaview"],["mvt","application/vnd.mapbox-vector-tile"],["mwf","application/vnd.mfer"],["mxf","application/mxf"],["mxl","application/vnd.recordare.musicxml"],["mxmf","audio/mobile-xmf"],["mxml","application/xv+xml"],["mxs","application/vnd.triscape.mxs"],["mxu","video/vnd.mpegurl"],["n-gage","application/vnd.nokia.n-gage.symbian.install"],["n3","text/n3"],["nb","application/mathematica"],["nbp","application/vnd.wolfram.player"],["nc","application/x-netcdf"],["ncx","application/x-dtbncx+xml"],["nfo","text/x-nfo"],["ngdat","application/vnd.nokia.n-gage.data"],["nitf","application/vnd.nitf"],["nlu","application/vnd.neurolanguage.nlu"],["nml","application/vnd.enliven"],["nnd","application/vnd.noblenet-directory"],["nns","application/vnd.noblenet-sealer"],["nnw","application/vnd.noblenet-web"],["npx","image/vnd.net-fpx"],["nq","application/n-quads"],["nsc","application/x-conference"],["nsf","application/vnd.lotus-notes"],["nt","application/n-triples"],["ntf","application/vnd.nitf"],["numbers","application/x-iwork-numbers-sffnumbers"],["nzb","application/x-nzb"],["oa2","application/vnd.fujitsu.oasys2"],["oa3","application/vnd.fujitsu.oasys3"],["oas","application/vnd.fujitsu.oasys"],["obd","application/x-msbinder"],["obgx","application/vnd.openblox.game+xml"],["obj","model/obj"],["oda","application/oda"],["odb","application/vnd.oasis.opendocument.database"],["odc","application/vnd.oasis.opendocument.chart"],["odf","application/vnd.oasis.opendocument.formula"],["odft","application/vnd.oasis.opendocument.formula-template"],["odg","application/vnd.oasis.opendocument.graphics"],["odi","application/vnd.oasis.opendocument.image"],["odm","application/vnd.oasis.opendocument.text-master"],["odp","application/vnd.oasis.opendocument.presentation"],["ods","application/vnd.oasis.opendocument.spreadsheet"],["odt","application/vnd.oasis.opendocument.text"],["oga","audio/ogg"],["ogex","model/vnd.opengex"],["ogg","audio/ogg"],["ogv","video/ogg"],["ogx","application/ogg"],["omdoc","application/omdoc+xml"],["onepkg","application/onenote"],["onetmp","application/onenote"],["onetoc","application/onenote"],["onetoc2","application/onenote"],["opf","application/oebps-package+xml"],["opml","text/x-opml"],["oprc","application/vnd.palm"],["opus","audio/ogg"],["org","text/x-org"],["osf","application/vnd.yamaha.openscoreformat"],["osfpvg","application/vnd.yamaha.openscoreformat.osfpvg+xml"],["osm","application/vnd.openstreetmap.data+xml"],["otc","application/vnd.oasis.opendocument.chart-template"],["otf","font/otf"],["otg","application/vnd.oasis.opendocument.graphics-template"],["oth","application/vnd.oasis.opendocument.text-web"],["oti","application/vnd.oasis.opendocument.image-template"],["otp","application/vnd.oasis.opendocument.presentation-template"],["ots","application/vnd.oasis.opendocument.spreadsheet-template"],["ott","application/vnd.oasis.opendocument.text-template"],["ova","application/x-virtualbox-ova"],["ovf","application/x-virtualbox-ovf"],["owl","application/rdf+xml"],["oxps","application/oxps"],["oxt","application/vnd.openofficeorg.extension"],["p","text/x-pascal"],["p7a","application/x-pkcs7-signature"],["p7b","application/x-pkcs7-certificates"],["p7c","application/pkcs7-mime"],["p7m","application/pkcs7-mime"],["p7r","application/x-pkcs7-certreqresp"],["p7s","application/pkcs7-signature"],["p8","application/pkcs8"],["p10","application/x-pkcs10"],["p12","application/x-pkcs12"],["pac","application/x-ns-proxy-autoconfig"],["pages","application/x-iwork-pages-sffpages"],["pas","text/x-pascal"],["paw","application/vnd.pawaafile"],["pbd","application/vnd.powerbuilder6"],["pbm","image/x-portable-bitmap"],["pcap","application/vnd.tcpdump.pcap"],["pcf","application/x-font-pcf"],["pcl","application/vnd.hp-pcl"],["pclxl","application/vnd.hp-pclxl"],["pct","image/x-pict"],["pcurl","application/vnd.curl.pcurl"],["pcx","image/x-pcx"],["pdb","application/x-pilot"],["pde","text/x-processing"],["pdf","application/pdf"],["pem","application/x-x509-user-cert"],["pfa","application/x-font-type1"],["pfb","application/x-font-type1"],["pfm","application/x-font-type1"],["pfr","application/font-tdpfr"],["pfx","application/x-pkcs12"],["pgm","image/x-portable-graymap"],["pgn","application/x-chess-pgn"],["pgp","application/pgp"],["php","application/x-httpd-php"],["php3","application/x-httpd-php"],["php4","application/x-httpd-php"],["phps","application/x-httpd-php-source"],["phtml","application/x-httpd-php"],["pic","image/x-pict"],["pkg","application/octet-stream"],["pki","application/pkixcmp"],["pkipath","application/pkix-pkipath"],["pkpass","application/vnd.apple.pkpass"],["pl","application/x-perl"],["plb","application/vnd.3gpp.pic-bw-large"],["plc","application/vnd.mobius.plc"],["plf","application/vnd.pocketlearn"],["pls","application/pls+xml"],["pm","application/x-perl"],["pml","application/vnd.ctc-posml"],["png","image/png"],["pnm","image/x-portable-anymap"],["portpkg","application/vnd.macports.portpkg"],["pot","application/vnd.ms-powerpoint"],["potm","application/vnd.ms-powerpoint.presentation.macroEnabled.12"],["potx","application/vnd.openxmlformats-officedocument.presentationml.template"],["ppa","application/vnd.ms-powerpoint"],["ppam","application/vnd.ms-powerpoint.addin.macroEnabled.12"],["ppd","application/vnd.cups-ppd"],["ppm","image/x-portable-pixmap"],["pps","application/vnd.ms-powerpoint"],["ppsm","application/vnd.ms-powerpoint.slideshow.macroEnabled.12"],["ppsx","application/vnd.openxmlformats-officedocument.presentationml.slideshow"],["ppt","application/powerpoint"],["pptm","application/vnd.ms-powerpoint.presentation.macroEnabled.12"],["pptx","application/vnd.openxmlformats-officedocument.presentationml.presentation"],["pqa","application/vnd.palm"],["prc","application/x-pilot"],["pre","application/vnd.lotus-freelance"],["prf","application/pics-rules"],["provx","application/provenance+xml"],["ps","application/postscript"],["psb","application/vnd.3gpp.pic-bw-small"],["psd","application/x-photoshop"],["psf","application/x-font-linux-psf"],["pskcxml","application/pskc+xml"],["pti","image/prs.pti"],["ptid","application/vnd.pvi.ptid1"],["pub","application/x-mspublisher"],["pvb","application/vnd.3gpp.pic-bw-var"],["pwn","application/vnd.3m.post-it-notes"],["pya","audio/vnd.ms-playready.media.pya"],["pyv","video/vnd.ms-playready.media.pyv"],["qam","application/vnd.epson.quickanime"],["qbo","application/vnd.intu.qbo"],["qfx","application/vnd.intu.qfx"],["qps","application/vnd.publishare-delta-tree"],["qt","video/quicktime"],["qwd","application/vnd.quark.quarkxpress"],["qwt","application/vnd.quark.quarkxpress"],["qxb","application/vnd.quark.quarkxpress"],["qxd","application/vnd.quark.quarkxpress"],["qxl","application/vnd.quark.quarkxpress"],["qxt","application/vnd.quark.quarkxpress"],["ra","audio/x-realaudio"],["ram","audio/x-pn-realaudio"],["raml","application/raml+yaml"],["rapd","application/route-apd+xml"],["rar","application/x-rar"],["ras","image/x-cmu-raster"],["rcprofile","application/vnd.ipunplugged.rcprofile"],["rdf","application/rdf+xml"],["rdz","application/vnd.data-vision.rdz"],["relo","application/p2p-overlay+xml"],["rep","application/vnd.businessobjects"],["res","application/x-dtbresource+xml"],["rgb","image/x-rgb"],["rif","application/reginfo+xml"],["rip","audio/vnd.rip"],["ris","application/x-research-info-systems"],["rl","application/resource-lists+xml"],["rlc","image/vnd.fujixerox.edmics-rlc"],["rld","application/resource-lists-diff+xml"],["rm","audio/x-pn-realaudio"],["rmi","audio/midi"],["rmp","audio/x-pn-realaudio-plugin"],["rms","application/vnd.jcp.javame.midlet-rms"],["rmvb","application/vnd.rn-realmedia-vbr"],["rnc","application/relax-ng-compact-syntax"],["rng","application/xml"],["roa","application/rpki-roa"],["roff","text/troff"],["rp9","application/vnd.cloanto.rp9"],["rpm","audio/x-pn-realaudio-plugin"],["rpss","application/vnd.nokia.radio-presets"],["rpst","application/vnd.nokia.radio-preset"],["rq","application/sparql-query"],["rs","application/rls-services+xml"],["rsa","application/x-pkcs7"],["rsat","application/atsc-rsat+xml"],["rsd","application/rsd+xml"],["rsheet","application/urc-ressheet+xml"],["rss","application/rss+xml"],["rtf","text/rtf"],["rtx","text/richtext"],["run","application/x-makeself"],["rusd","application/route-usd+xml"],["rv","video/vnd.rn-realvideo"],["s","text/x-asm"],["s3m","audio/s3m"],["saf","application/vnd.yamaha.smaf-audio"],["sass","text/x-sass"],["sbml","application/sbml+xml"],["sc","application/vnd.ibm.secure-container"],["scd","application/x-msschedule"],["scm","application/vnd.lotus-screencam"],["scq","application/scvp-cv-request"],["scs","application/scvp-cv-response"],["scss","text/x-scss"],["scurl","text/vnd.curl.scurl"],["sda","application/vnd.stardivision.draw"],["sdc","application/vnd.stardivision.calc"],["sdd","application/vnd.stardivision.impress"],["sdkd","application/vnd.solent.sdkm+xml"],["sdkm","application/vnd.solent.sdkm+xml"],["sdp","application/sdp"],["sdw","application/vnd.stardivision.writer"],["sea","application/octet-stream"],["see","application/vnd.seemail"],["seed","application/vnd.fdsn.seed"],["sema","application/vnd.sema"],["semd","application/vnd.semd"],["semf","application/vnd.semf"],["senmlx","application/senml+xml"],["sensmlx","application/sensml+xml"],["ser","application/java-serialized-object"],["setpay","application/set-payment-initiation"],["setreg","application/set-registration-initiation"],["sfd-hdstx","application/vnd.hydrostatix.sof-data"],["sfs","application/vnd.spotfire.sfs"],["sfv","text/x-sfv"],["sgi","image/sgi"],["sgl","application/vnd.stardivision.writer-global"],["sgm","text/sgml"],["sgml","text/sgml"],["sh","application/x-sh"],["shar","application/x-shar"],["shex","text/shex"],["shf","application/shf+xml"],["shtml","text/html"],["sid","image/x-mrsid-image"],["sieve","application/sieve"],["sig","application/pgp-signature"],["sil","audio/silk"],["silo","model/mesh"],["sis","application/vnd.symbian.install"],["sisx","application/vnd.symbian.install"],["sit","application/x-stuffit"],["sitx","application/x-stuffitx"],["siv","application/sieve"],["skd","application/vnd.koan"],["skm","application/vnd.koan"],["skp","application/vnd.koan"],["skt","application/vnd.koan"],["sldm","application/vnd.ms-powerpoint.slide.macroenabled.12"],["sldx","application/vnd.openxmlformats-officedocument.presentationml.slide"],["slim","text/slim"],["slm","text/slim"],["sls","application/route-s-tsid+xml"],["slt","application/vnd.epson.salt"],["sm","application/vnd.stepmania.stepchart"],["smf","application/vnd.stardivision.math"],["smi","application/smil"],["smil","application/smil"],["smv","video/x-smv"],["smzip","application/vnd.stepmania.package"],["snd","audio/basic"],["snf","application/x-font-snf"],["so","application/octet-stream"],["spc","application/x-pkcs7-certificates"],["spdx","text/spdx"],["spf","application/vnd.yamaha.smaf-phrase"],["spl","application/x-futuresplash"],["spot","text/vnd.in3d.spot"],["spp","application/scvp-vp-response"],["spq","application/scvp-vp-request"],["spx","audio/ogg"],["sql","application/x-sql"],["src","application/x-wais-source"],["srt","application/x-subrip"],["sru","application/sru+xml"],["srx","application/sparql-results+xml"],["ssdl","application/ssdl+xml"],["sse","application/vnd.kodak-descriptor"],["ssf","application/vnd.epson.ssf"],["ssml","application/ssml+xml"],["sst","application/octet-stream"],["st","application/vnd.sailingtracker.track"],["stc","application/vnd.sun.xml.calc.template"],["std","application/vnd.sun.xml.draw.template"],["stf","application/vnd.wt.stf"],["sti","application/vnd.sun.xml.impress.template"],["stk","application/hyperstudio"],["stl","model/stl"],["stpx","model/step+xml"],["stpxz","model/step-xml+zip"],["stpz","model/step+zip"],["str","application/vnd.pg.format"],["stw","application/vnd.sun.xml.writer.template"],["styl","text/stylus"],["stylus","text/stylus"],["sub","text/vnd.dvb.subtitle"],["sus","application/vnd.sus-calendar"],["susp","application/vnd.sus-calendar"],["sv4cpio","application/x-sv4cpio"],["sv4crc","application/x-sv4crc"],["svc","application/vnd.dvb.service"],["svd","application/vnd.svd"],["svg","image/svg+xml"],["svgz","image/svg+xml"],["swa","application/x-director"],["swf","application/x-shockwave-flash"],["swi","application/vnd.aristanetworks.swi"],["swidtag","application/swid+xml"],["sxc","application/vnd.sun.xml.calc"],["sxd","application/vnd.sun.xml.draw"],["sxg","application/vnd.sun.xml.writer.global"],["sxi","application/vnd.sun.xml.impress"],["sxm","application/vnd.sun.xml.math"],["sxw","application/vnd.sun.xml.writer"],["t","text/troff"],["t3","application/x-t3vm-image"],["t38","image/t38"],["taglet","application/vnd.mynfc"],["tao","application/vnd.tao.intent-module-archive"],["tap","image/vnd.tencent.tap"],["tar","application/x-tar"],["tcap","application/vnd.3gpp2.tcap"],["tcl","application/x-tcl"],["td","application/urc-targetdesc+xml"],["teacher","application/vnd.smart.teacher"],["tei","application/tei+xml"],["teicorpus","application/tei+xml"],["tex","application/x-tex"],["texi","application/x-texinfo"],["texinfo","application/x-texinfo"],["text","text/plain"],["tfi","application/thraud+xml"],["tfm","application/x-tex-tfm"],["tfx","image/tiff-fx"],["tga","image/x-tga"],["tgz","application/x-tar"],["thmx","application/vnd.ms-officetheme"],["tif","image/tiff"],["tiff","image/tiff"],["tk","application/x-tcl"],["tmo","application/vnd.tmobile-livetv"],["toml","application/toml"],["torrent","application/x-bittorrent"],["tpl","application/vnd.groove-tool-template"],["tpt","application/vnd.trid.tpt"],["tr","text/troff"],["tra","application/vnd.trueapp"],["trig","application/trig"],["trm","application/x-msterminal"],["ts","video/mp2t"],["tsd","application/timestamped-data"],["tsv","text/tab-separated-values"],["ttc","font/collection"],["ttf","font/ttf"],["ttl","text/turtle"],["ttml","application/ttml+xml"],["twd","application/vnd.simtech-mindmapper"],["twds","application/vnd.simtech-mindmapper"],["txd","application/vnd.genomatix.tuxedo"],["txf","application/vnd.mobius.txf"],["txt","text/plain"],["u8dsn","message/global-delivery-status"],["u8hdr","message/global-headers"],["u8mdn","message/global-disposition-notification"],["u8msg","message/global"],["u32","application/x-authorware-bin"],["ubj","application/ubjson"],["udeb","application/x-debian-package"],["ufd","application/vnd.ufdl"],["ufdl","application/vnd.ufdl"],["ulx","application/x-glulx"],["umj","application/vnd.umajin"],["unityweb","application/vnd.unity"],["uoml","application/vnd.uoml+xml"],["uri","text/uri-list"],["uris","text/uri-list"],["urls","text/uri-list"],["usdz","model/vnd.usdz+zip"],["ustar","application/x-ustar"],["utz","application/vnd.uiq.theme"],["uu","text/x-uuencode"],["uva","audio/vnd.dece.audio"],["uvd","application/vnd.dece.data"],["uvf","application/vnd.dece.data"],["uvg","image/vnd.dece.graphic"],["uvh","video/vnd.dece.hd"],["uvi","image/vnd.dece.graphic"],["uvm","video/vnd.dece.mobile"],["uvp","video/vnd.dece.pd"],["uvs","video/vnd.dece.sd"],["uvt","application/vnd.dece.ttml+xml"],["uvu","video/vnd.uvvu.mp4"],["uvv","video/vnd.dece.video"],["uvva","audio/vnd.dece.audio"],["uvvd","application/vnd.dece.data"],["uvvf","application/vnd.dece.data"],["uvvg","image/vnd.dece.graphic"],["uvvh","video/vnd.dece.hd"],["uvvi","image/vnd.dece.graphic"],["uvvm","video/vnd.dece.mobile"],["uvvp","video/vnd.dece.pd"],["uvvs","video/vnd.dece.sd"],["uvvt","application/vnd.dece.ttml+xml"],["uvvu","video/vnd.uvvu.mp4"],["uvvv","video/vnd.dece.video"],["uvvx","application/vnd.dece.unspecified"],["uvvz","application/vnd.dece.zip"],["uvx","application/vnd.dece.unspecified"],["uvz","application/vnd.dece.zip"],["vbox","application/x-virtualbox-vbox"],["vbox-extpack","application/x-virtualbox-vbox-extpack"],["vcard","text/vcard"],["vcd","application/x-cdlink"],["vcf","text/x-vcard"],["vcg","application/vnd.groove-vcard"],["vcs","text/x-vcalendar"],["vcx","application/vnd.vcx"],["vdi","application/x-virtualbox-vdi"],["vds","model/vnd.sap.vds"],["vhd","application/x-virtualbox-vhd"],["vis","application/vnd.visionary"],["viv","video/vnd.vivo"],["vlc","application/videolan"],["vmdk","application/x-virtualbox-vmdk"],["vob","video/x-ms-vob"],["vor","application/vnd.stardivision.writer"],["vox","application/x-authorware-bin"],["vrml","model/vrml"],["vsd","application/vnd.visio"],["vsf","application/vnd.vsf"],["vss","application/vnd.visio"],["vst","application/vnd.visio"],["vsw","application/vnd.visio"],["vtf","image/vnd.valve.source.texture"],["vtt","text/vtt"],["vtu","model/vnd.vtu"],["vxml","application/voicexml+xml"],["w3d","application/x-director"],["wad","application/x-doom"],["wadl","application/vnd.sun.wadl+xml"],["war","application/java-archive"],["wasm","application/wasm"],["wav","audio/x-wav"],["wax","audio/x-ms-wax"],["wbmp","image/vnd.wap.wbmp"],["wbs","application/vnd.criticaltools.wbs+xml"],["wbxml","application/wbxml"],["wcm","application/vnd.ms-works"],["wdb","application/vnd.ms-works"],["wdp","image/vnd.ms-photo"],["weba","audio/webm"],["webapp","application/x-web-app-manifest+json"],["webm","video/webm"],["webmanifest","application/manifest+json"],["webp","image/webp"],["wg","application/vnd.pmi.widget"],["wgt","application/widget"],["wks","application/vnd.ms-works"],["wm","video/x-ms-wm"],["wma","audio/x-ms-wma"],["wmd","application/x-ms-wmd"],["wmf","image/wmf"],["wml","text/vnd.wap.wml"],["wmlc","application/wmlc"],["wmls","text/vnd.wap.wmlscript"],["wmlsc","application/vnd.wap.wmlscriptc"],["wmv","video/x-ms-wmv"],["wmx","video/x-ms-wmx"],["wmz","application/x-msmetafile"],["woff","font/woff"],["woff2","font/woff2"],["word","application/msword"],["wpd","application/vnd.wordperfect"],["wpl","application/vnd.ms-wpl"],["wps","application/vnd.ms-works"],["wqd","application/vnd.wqd"],["wri","application/x-mswrite"],["wrl","model/vrml"],["wsc","message/vnd.wfa.wsc"],["wsdl","application/wsdl+xml"],["wspolicy","application/wspolicy+xml"],["wtb","application/vnd.webturbo"],["wvx","video/x-ms-wvx"],["x3d","model/x3d+xml"],["x3db","model/x3d+fastinfoset"],["x3dbz","model/x3d+binary"],["x3dv","model/x3d-vrml"],["x3dvz","model/x3d+vrml"],["x3dz","model/x3d+xml"],["x32","application/x-authorware-bin"],["x_b","model/vnd.parasolid.transmit.binary"],["x_t","model/vnd.parasolid.transmit.text"],["xaml","application/xaml+xml"],["xap","application/x-silverlight-app"],["xar","application/vnd.xara"],["xav","application/xcap-att+xml"],["xbap","application/x-ms-xbap"],["xbd","application/vnd.fujixerox.docuworks.binder"],["xbm","image/x-xbitmap"],["xca","application/xcap-caps+xml"],["xcs","application/calendar+xml"],["xdf","application/xcap-diff+xml"],["xdm","application/vnd.syncml.dm+xml"],["xdp","application/vnd.adobe.xdp+xml"],["xdssc","application/dssc+xml"],["xdw","application/vnd.fujixerox.docuworks"],["xel","application/xcap-el+xml"],["xenc","application/xenc+xml"],["xer","application/patch-ops-error+xml"],["xfdf","application/vnd.adobe.xfdf"],["xfdl","application/vnd.xfdl"],["xht","application/xhtml+xml"],["xhtml","application/xhtml+xml"],["xhvml","application/xv+xml"],["xif","image/vnd.xiff"],["xl","application/excel"],["xla","application/vnd.ms-excel"],["xlam","application/vnd.ms-excel.addin.macroEnabled.12"],["xlc","application/vnd.ms-excel"],["xlf","application/xliff+xml"],["xlm","application/vnd.ms-excel"],["xls","application/vnd.ms-excel"],["xlsb","application/vnd.ms-excel.sheet.binary.macroEnabled.12"],["xlsm","application/vnd.ms-excel.sheet.macroEnabled.12"],["xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],["xlt","application/vnd.ms-excel"],["xltm","application/vnd.ms-excel.template.macroEnabled.12"],["xltx","application/vnd.openxmlformats-officedocument.spreadsheetml.template"],["xlw","application/vnd.ms-excel"],["xm","audio/xm"],["xml","application/xml"],["xns","application/xcap-ns+xml"],["xo","application/vnd.olpc-sugar"],["xop","application/xop+xml"],["xpi","application/x-xpinstall"],["xpl","application/xproc+xml"],["xpm","image/x-xpixmap"],["xpr","application/vnd.is-xpr"],["xps","application/vnd.ms-xpsdocument"],["xpw","application/vnd.intercon.formnet"],["xpx","application/vnd.intercon.formnet"],["xsd","application/xml"],["xsl","application/xml"],["xslt","application/xslt+xml"],["xsm","application/vnd.syncml+xml"],["xspf","application/xspf+xml"],["xul","application/vnd.mozilla.xul+xml"],["xvm","application/xv+xml"],["xvml","application/xv+xml"],["xwd","image/x-xwindowdump"],["xyz","chemical/x-xyz"],["xz","application/x-xz"],["yaml","text/yaml"],["yang","application/yang"],["yin","application/yin+xml"],["yml","text/yaml"],["ymp","text/x-suse-ymp"],["z","application/x-compress"],["z1","application/x-zmachine"],["z2","application/x-zmachine"],["z3","application/x-zmachine"],["z4","application/x-zmachine"],["z5","application/x-zmachine"],["z6","application/x-zmachine"],["z7","application/x-zmachine"],["z8","application/x-zmachine"],["zaz","application/vnd.zzazz.deck+xml"],["zip","application/zip"],["zir","application/vnd.zul"],["zirz","application/vnd.zul"],["zmm","application/vnd.handheld-entertainment+xml"],["zsh","text/x-scriptzsh"]]);function Oi(n,l,r){const o=_R(n),{webkitRelativePath:c}=n,u=typeof l=="string"?l:typeof c=="string"&&c.length>0?c:`./${n.name}`;return typeof o.path!="string"&&ky(o,"path",u),ky(o,"relativePath",u),o}function _R(n){const{name:l}=n;if(l&&l.lastIndexOf(".")!==-1&&!n.type){const o=l.split(".").pop().toLowerCase(),c=ER.get(o);c&&Object.defineProperty(n,"type",{value:c,writable:!1,configurable:!1,enumerable:!0})}return n}function ky(n,l,r){Object.defineProperty(n,l,{value:r,writable:!1,configurable:!1,enumerable:!0})}const CR=[".DS_Store","Thumbs.db"];function AR(n){return zl(this,void 0,void 0,function*(){return Bc(n)&&TR(n.dataTransfer)?jR(n.dataTransfer,n.type):OR(n)?RR(n):Array.isArray(n)&&n.every(l=>"getFile"in l&&typeof l.getFile=="function")?NR(n):[]})}function TR(n){return Bc(n)}function OR(n){return Bc(n)&&Bc(n.target)}function Bc(n){return typeof n=="object"&&n!==null}function RR(n){return Sd(n.target.files).map(l=>Oi(l))}function NR(n){return zl(this,void 0,void 0,function*(){return(yield Promise.all(n.map(r=>r.getFile()))).map(r=>Oi(r))})}function jR(n,l){return zl(this,void 0,void 0,function*(){if(n.items){const r=Sd(n.items).filter(c=>c.kind==="file");if(l!=="drop")return r;const o=yield Promise.all(r.map(DR));return Ly(T0(o))}return Ly(Sd(n.files).map(r=>Oi(r)))})}function Ly(n){return n.filter(l=>CR.indexOf(l.name)===-1)}function Sd(n){if(n===null)return[];const l=[];for(let r=0;r[...l,...Array.isArray(r)?T0(r):[r]],[])}function Uy(n,l){return zl(this,void 0,void 0,function*(){var r;if(globalThis.isSecureContext&&typeof n.getAsFileSystemHandle=="function"){const u=yield n.getAsFileSystemHandle();if(u===null)throw new Error(`${n} is not a File`);if(u!==void 0){const d=yield u.getFile();return d.handle=u,Oi(d)}}const o=n.getAsFile();if(!o)throw new Error(`${n} is not a File`);return Oi(o,(r=l?.fullPath)!==null&&r!==void 0?r:void 0)})}function MR(n){return zl(this,void 0,void 0,function*(){return n.isDirectory?O0(n):zR(n)})}function O0(n){const l=n.createReader();return new Promise((r,o)=>{const c=[];function u(){l.readEntries(d=>zl(this,void 0,void 0,function*(){if(d.length){const p=Promise.all(d.map(MR));c.push(p),u()}else try{const p=yield Promise.all(c);r(p)}catch(p){o(p)}}),d=>{o(d)})}u()})}function zR(n){return zl(this,void 0,void 0,function*(){return new Promise((l,r)=>{n.file(o=>{const c=Oi(o,n.fullPath);l(c)},o=>{r(o)})})})}var Sc={},Hy;function kR(){return Hy||(Hy=1,Sc.__esModule=!0,Sc.default=function(n,l){if(n&&l){var r=Array.isArray(l)?l:l.split(",");if(r.length===0)return!0;var o=n.name||"",c=(n.type||"").toLowerCase(),u=c.replace(/\/.*$/,"");return r.some(function(d){var p=d.trim().toLowerCase();return p.charAt(0)==="."?o.toLowerCase().endsWith(p):p.endsWith("/*")?u===p.replace(/\/.*$/,""):c===p})}return!0}),Sc}var LR=kR();const Zf=Gr(LR);function By(n){return BR(n)||HR(n)||N0(n)||UR()}function UR(){throw new TypeError(`Invalid attempt to spread non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function HR(n){if(typeof Symbol<"u"&&n[Symbol.iterator]!=null||n["@@iterator"]!=null)return Array.from(n)}function BR(n){if(Array.isArray(n))return wd(n)}function qy(n,l){var r=Object.keys(n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(n);l&&(o=o.filter(function(c){return Object.getOwnPropertyDescriptor(n,c).enumerable})),r.push.apply(r,o)}return r}function Vy(n){for(var l=1;ln.length)&&(l=n.length);for(var r=0,o=new Array(l);r0&&arguments[0]!==void 0?arguments[0]:"",r=l.split(","),o=r.length>1?"one of ".concat(r.join(", ")):r[0];return{code:YR,message:"File type must be ".concat(o)}},Py=function(l){return{code:FR,message:"File is larger than ".concat(l," ").concat(l===1?"byte":"bytes")}},Gy=function(l){return{code:XR,message:"File is smaller than ".concat(l," ").concat(l===1?"byte":"bytes")}},KR={code:IR,message:"Too many files"};function ZR(n){return n.type===""&&typeof n.getAsFile=="function"}function j0(n,l){var r=n.type==="application/x-moz-file"||GR(n,l)||ZR(n);return[r,r?null:QR(l)]}function D0(n,l,r){if(El(n.size))if(El(l)&&El(r)){if(n.size>r)return[!1,Py(r)];if(n.sizer)return[!1,Py(r)]}return[!0,null]}function El(n){return n!=null}function WR(n){var l=n.files,r=n.accept,o=n.minSize,c=n.maxSize,u=n.multiple,d=n.maxFiles,p=n.validator;return!u&&l.length>1||u&&d>=1&&l.length>d?!1:l.every(function(h){var m=j0(h,r),v=Pr(m,1),y=v[0],w=D0(h,o,c),_=Pr(w,1),E=_[0],S=p?p(h):null;return y&&E&&!S})}function qc(n){return typeof n.isPropagationStopped=="function"?n.isPropagationStopped():typeof n.cancelBubble<"u"?n.cancelBubble:!1}function Lr(n){return n.dataTransfer?Array.prototype.some.call(n.dataTransfer.types,function(l){return l==="Files"||l==="application/x-moz-file"}):!!n.target&&!!n.target.files}function Yy(n){n.preventDefault()}function JR(n){return n.indexOf("MSIE")!==-1||n.indexOf("Trident/")!==-1}function $R(n){return n.indexOf("Edge/")!==-1}function eN(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:window.navigator.userAgent;return JR(n)||$R(n)}function Nn(){for(var n=arguments.length,l=new Array(n),r=0;r1?c-1:0),d=1;dn.length)&&(l=n.length);for(var r=0,o=new Array(l);r=0)&&Object.prototype.propertyIsEnumerable.call(n,o)&&(r[o]=n[o])}return r}function vN(n,l){if(n==null)return{};var r={},o=Object.keys(n),c,u;for(u=0;u=0)&&(r[c]=n[c]);return r}var tp=x.forwardRef(function(n,l){var r=n.children,o=Vc(n,rN),c=np(o),u=c.open,d=Vc(c,oN);return x.useImperativeHandle(l,function(){return{open:u}},[u]),Qe.createElement(x.Fragment,null,r(et(et({},d),{},{open:u})))});tp.displayName="Dropzone";var L0={disabled:!1,getFilesFromEvent:AR,maxSize:1/0,minSize:0,multiple:!0,maxFiles:0,preventDropOnDocument:!0,noClick:!1,noKeyboard:!1,noDrag:!1,noDragEventsBubbling:!1,validator:null,useFsAccessApi:!1,autoFocus:!1};tp.defaultProps=L0;tp.propTypes={children:Ie.func,accept:Ie.objectOf(Ie.arrayOf(Ie.string)),multiple:Ie.bool,preventDropOnDocument:Ie.bool,noClick:Ie.bool,noKeyboard:Ie.bool,noDrag:Ie.bool,noDragEventsBubbling:Ie.bool,minSize:Ie.number,maxSize:Ie.number,maxFiles:Ie.number,disabled:Ie.bool,getFilesFromEvent:Ie.func,onFileDialogCancel:Ie.func,onFileDialogOpen:Ie.func,useFsAccessApi:Ie.bool,autoFocus:Ie.bool,onDragEnter:Ie.func,onDragLeave:Ie.func,onDragOver:Ie.func,onDrop:Ie.func,onDropAccepted:Ie.func,onDropRejected:Ie.func,onError:Ie.func,validator:Ie.func};var Cd={isFocused:!1,isFileDialogActive:!1,isDragActive:!1,isDragAccept:!1,isDragReject:!1,isDragGlobal:!1,acceptedFiles:[],fileRejections:[]};function np(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},l=et(et({},L0),n),r=l.accept,o=l.disabled,c=l.getFilesFromEvent,u=l.maxSize,d=l.minSize,p=l.multiple,h=l.maxFiles,m=l.onDragEnter,v=l.onDragLeave,y=l.onDragOver,w=l.onDrop,_=l.onDropAccepted,E=l.onDropRejected,S=l.onFileDialogCancel,A=l.onFileDialogOpen,T=l.useFsAccessApi,O=l.autoFocus,j=l.preventDropOnDocument,z=l.noClick,k=l.noKeyboard,Y=l.noDrag,U=l.noDragEventsBubbling,I=l.onError,ae=l.validator,ce=x.useMemo(function(){return aN(r)},[r]),H=x.useMemo(function(){return nN(r)},[r]),le=x.useMemo(function(){return typeof A=="function"?A:Iy},[A]),ve=x.useMemo(function(){return typeof S=="function"?S:Iy},[S]),re=x.useRef(null),de=x.useRef(null),M=x.useReducer(gN,Cd),Q=Wf(M,2),W=Q[0],ee=Q[1],J=W.isFocused,N=W.isFileDialogActive,F=x.useRef(typeof window<"u"&&window.isSecureContext&&T&&tN()),te=function(){!F.current&&N&&setTimeout(function(){if(de.current){var ye=de.current.files;ye.length||(ee({type:"closeDialog"}),ve())}},300)};x.useEffect(function(){return window.addEventListener("focus",te,!1),function(){window.removeEventListener("focus",te,!1)}},[de,N,ve,F]);var ne=x.useRef([]),ie=x.useRef([]),se=function(ye){re.current&&re.current.contains(ye.target)||(ye.preventDefault(),ne.current=[])};x.useEffect(function(){return j&&(document.addEventListener("dragover",Yy,!1),document.addEventListener("drop",se,!1)),function(){j&&(document.removeEventListener("dragover",Yy),document.removeEventListener("drop",se))}},[re,j]),x.useEffect(function(){var oe=function(Pt){ie.current=[].concat(Fy(ie.current),[Pt.target]),Lr(Pt)&&ee({isDragGlobal:!0,type:"setDragGlobal"})},ye=function(Pt){ie.current=ie.current.filter(function(mn){return mn!==Pt.target&&mn!==null}),!(ie.current.length>0)&&ee({isDragGlobal:!1,type:"setDragGlobal"})},Ze=function(){ie.current=[],ee({isDragGlobal:!1,type:"setDragGlobal"})},We=function(){ie.current=[],ee({isDragGlobal:!1,type:"setDragGlobal"})};return document.addEventListener("dragenter",oe,!1),document.addEventListener("dragleave",ye,!1),document.addEventListener("dragend",Ze,!1),document.addEventListener("drop",We,!1),function(){document.removeEventListener("dragenter",oe),document.removeEventListener("dragleave",ye),document.removeEventListener("dragend",Ze),document.removeEventListener("drop",We)}},[re]),x.useEffect(function(){return!o&&O&&re.current&&re.current.focus(),function(){}},[re,O,o]);var $=x.useCallback(function(oe){I?I(oe):console.error(oe)},[I]),Se=x.useCallback(function(oe){oe.preventDefault(),oe.persist(),ga(oe),ne.current=[].concat(Fy(ne.current),[oe.target]),Lr(oe)&&Promise.resolve(c(oe)).then(function(ye){if(!(qc(oe)&&!U)){var Ze=ye.length,We=Ze>0&&WR({files:ye,accept:ce,minSize:d,maxSize:u,multiple:p,maxFiles:h,validator:ae}),dt=Ze>0&&!We;ee({isDragAccept:We,isDragReject:dt,isDragActive:!0,type:"setDraggedFiles"}),m&&m(oe)}}).catch(function(ye){return $(ye)})},[c,m,$,U,ce,d,u,p,h,ae]),pe=x.useCallback(function(oe){oe.preventDefault(),oe.persist(),ga(oe);var ye=Lr(oe);if(ye&&oe.dataTransfer)try{oe.dataTransfer.dropEffect="copy"}catch{}return ye&&y&&y(oe),!1},[y,U]),Oe=x.useCallback(function(oe){oe.preventDefault(),oe.persist(),ga(oe);var ye=ne.current.filter(function(We){return re.current&&re.current.contains(We)}),Ze=ye.indexOf(oe.target);Ze!==-1&&ye.splice(Ze,1),ne.current=ye,!(ye.length>0)&&(ee({type:"setDraggedFiles",isDragActive:!1,isDragAccept:!1,isDragReject:!1}),Lr(oe)&&v&&v(oe))},[re,v,U]),Ce=x.useCallback(function(oe,ye){var Ze=[],We=[];oe.forEach(function(dt){var Pt=j0(dt,ce),mn=Wf(Pt,2),Ui=mn[0],Pn=mn[1],bt=D0(dt,d,u),Gt=Wf(bt,2),xt=Gt[0],Hi=Gt[1],Bi=ae?ae(dt):null;if(Ui&&xt&&!Bi)Ze.push(dt);else{var qi=[Pn,Hi];Bi&&(qi=qi.concat(Bi)),We.push({file:dt,errors:qi.filter(function(kl){return kl})})}}),(!p&&Ze.length>1||p&&h>=1&&Ze.length>h)&&(Ze.forEach(function(dt){We.push({file:dt,errors:[KR]})}),Ze.splice(0)),ee({acceptedFiles:Ze,fileRejections:We,isDragReject:We.length>0,type:"setFiles"}),w&&w(Ze,We,ye),We.length>0&&E&&E(We,ye),Ze.length>0&&_&&_(Ze,ye)},[ee,p,ce,d,u,h,w,_,E,ae]),ke=x.useCallback(function(oe){oe.preventDefault(),oe.persist(),ga(oe),ne.current=[],Lr(oe)&&Promise.resolve(c(oe)).then(function(ye){qc(oe)&&!U||Ce(ye,oe)}).catch(function(ye){return $(ye)}),ee({type:"reset"})},[c,Ce,$,U]),Ke=x.useCallback(function(){if(F.current){ee({type:"openDialog"}),le();var oe={multiple:p,types:H};window.showOpenFilePicker(oe).then(function(ye){return c(ye)}).then(function(ye){Ce(ye,null),ee({type:"closeDialog"})}).catch(function(ye){lN(ye)?(ve(ye),ee({type:"closeDialog"})):iN(ye)?(F.current=!1,de.current?(de.current.value=null,de.current.click()):$(new Error("Cannot open the file picker because the https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API is not supported and no was provided."))):$(ye)});return}de.current&&(ee({type:"openDialog"}),le(),de.current.value=null,de.current.click())},[ee,le,ve,T,Ce,$,H,p]),nt=x.useCallback(function(oe){!re.current||!re.current.isEqualNode(oe.target)||(oe.key===" "||oe.key==="Enter"||oe.keyCode===32||oe.keyCode===13)&&(oe.preventDefault(),Ke())},[re,Ke]),_n=x.useCallback(function(){ee({type:"focus"})},[]),Cn=x.useCallback(function(){ee({type:"blur"})},[]),ha=x.useCallback(function(){z||(eN()?setTimeout(Ke,0):Ke())},[z,Ke]),Vn=function(ye){return o?null:ye},el=function(ye){return k?null:Vn(ye)},va=function(ye){return Y?null:Vn(ye)},ga=function(ye){U&&ye.stopPropagation()},ds=x.useMemo(function(){return function(){var oe=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},ye=oe.refKey,Ze=ye===void 0?"ref":ye,We=oe.role,dt=oe.onKeyDown,Pt=oe.onFocus,mn=oe.onBlur,Ui=oe.onClick,Pn=oe.onDragEnter,bt=oe.onDragOver,Gt=oe.onDragLeave,xt=oe.onDrop,Hi=Vc(oe,cN);return et(et(_d({onKeyDown:el(Nn(dt,nt)),onFocus:el(Nn(Pt,_n)),onBlur:el(Nn(mn,Cn)),onClick:Vn(Nn(Ui,ha)),onDragEnter:va(Nn(Pn,Se)),onDragOver:va(Nn(bt,pe)),onDragLeave:va(Nn(Gt,Oe)),onDrop:va(Nn(xt,ke)),role:typeof We=="string"&&We!==""?We:"presentation"},Ze,re),!o&&!k?{tabIndex:0}:{}),Hi)}},[re,nt,_n,Cn,ha,Se,pe,Oe,ke,k,Y,o]),ps=x.useCallback(function(oe){oe.stopPropagation()},[]),Rt=x.useMemo(function(){return function(){var oe=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},ye=oe.refKey,Ze=ye===void 0?"ref":ye,We=oe.onChange,dt=oe.onClick,Pt=Vc(oe,sN),mn=_d({accept:ce,multiple:p,type:"file",style:{border:0,clip:"rect(0, 0, 0, 0)",clipPath:"inset(50%)",height:"1px",margin:"0 -1px -1px 0",overflow:"hidden",padding:0,position:"absolute",width:"1px",whiteSpace:"nowrap"},onChange:Vn(Nn(We,ke)),onClick:Vn(Nn(dt,ps)),tabIndex:-1},Ze,de);return et(et({},mn),Pt)}},[de,r,p,ke,o]);return et(et({},W),{},{isFocused:J&&!o,getRootProps:ds,getInputProps:Rt,rootRef:re,inputRef:de,open:Vn(Ke)})}function gN(n,l){switch(l.type){case"focus":return et(et({},n),{},{isFocused:!0});case"blur":return et(et({},n),{},{isFocused:!1});case"openDialog":return et(et({},Cd),{},{isFileDialogActive:!0});case"closeDialog":return et(et({},n),{},{isFileDialogActive:!1});case"setDraggedFiles":return et(et({},n),{},{isDragActive:l.isDragActive,isDragAccept:l.isDragAccept,isDragReject:l.isDragReject});case"setFiles":return et(et({},n),{},{acceptedFiles:l.acceptedFiles,fileRejections:l.fileRejections,isDragReject:l.isDragReject});case"setDragGlobal":return et(et({},n),{},{isDragGlobal:l.isDragGlobal});case"reset":return et({},Cd);default:return n}}function Iy(){}function yN(n){return new Promise((l,r)=>{const o=new FileReader;o.onload=c=>{const u=c.target?.result;typeof u=="string"?l(u):r(new Error("Unable to read image file."))},o.onerror=()=>r(o.error??new Error("Unable to read image file.")),o.readAsDataURL(n)})}function Qy({value:n,onChange:l,label:r,description:o,className:c,compact:u=!1}){const d=x.useCallback(async y=>{const w=y[0];if(w)try{const _=await yN(w);l(_)}catch(_){console.error("Failed to read dropped image",_)}},[l]),{getRootProps:p,getInputProps:h,isDragAccept:m,isDragReject:v}=np({accept:{"image/*":[]},maxFiles:1,maxSize:10*1024*1024,multiple:!1,onDrop:y=>{d(y)}});return b.jsxs("div",{className:Be("space-y-3",c),children:[r?b.jsxs("div",{className:"space-y-1",children:[b.jsx("p",{className:"text-sm font-medium text-ink",children:r}),o?b.jsx("p",{className:"text-xs leading-5 text-muted",children:o}):null]}):null,n?b.jsx("div",{className:"overflow-hidden rounded-[1.5rem] border border-line bg-paper",children:b.jsxs("div",{className:Be("relative overflow-hidden bg-sand/45",u?"h-40":"h-52"),children:[b.jsx("img",{src:n,alt:"Selected input",className:"h-full w-full object-contain p-4"}),b.jsxs(Tl,{type:"button",variant:"outline",size:"icon",className:"absolute right-3 top-3 h-9 w-9 bg-paper/92",onClick:()=>l(null),children:[b.jsx(db,{className:"h-4 w-4"}),b.jsx("span",{className:"sr-only",children:"Remove image"})]})]})}):b.jsxs("div",{...p(),className:Be("rounded-[1.5rem] border border-dashed bg-oat/60 px-4 py-6 transition",u?"min-h-36":"min-h-40",m&&"border-clay bg-clay/8",v&&"border-clay-strong bg-clay/10","cursor-pointer border-line hover:border-clay/45 hover:bg-oat"),children:[b.jsx("input",{...h()}),b.jsxs("div",{className:"flex h-full flex-col items-center justify-center gap-3 text-center",children:[b.jsx("div",{className:"flex h-12 w-12 items-center justify-center rounded-full bg-paper text-clay shadow-[0_12px_30px_-22px_color-mix(in_oklab,var(--color-clay)_50%,transparent)]",children:m?b.jsx(VE,{className:"h-5 w-5"}):b.jsx(NE,{className:"h-5 w-5"})}),b.jsxs("div",{className:"space-y-1",children:[b.jsx("p",{className:"text-sm font-medium text-ink",children:"Drop an image or click to browse"}),b.jsx("p",{className:"text-xs leading-5 text-muted",children:"PNG, JPG, or WEBP up to 10 MB."})]})]})]})]})}function bN(n,l){return x.useReducer((r,o)=>l[r][o]??r,n)}var ma=n=>{const{present:l,children:r}=n,o=xN(l),c=typeof r=="function"?r({present:o.isPresent}):x.Children.only(r),u=qe(o.ref,SN(c));return typeof r=="function"||o.isPresent?x.cloneElement(c,{ref:u}):null};ma.displayName="Presence";function xN(n){const[l,r]=x.useState(),o=x.useRef(null),c=x.useRef(n),u=x.useRef("none"),d=n?"mounted":"unmounted",[p,h]=bN(d,{mounted:{UNMOUNT:"unmounted",ANIMATION_OUT:"unmountSuspended"},unmountSuspended:{MOUNT:"mounted",ANIMATION_END:"unmounted"},unmounted:{MOUNT:"mounted"}});return x.useEffect(()=>{const m=wc(o.current);u.current=p==="mounted"?m:"none"},[p]),yt(()=>{const m=o.current,v=c.current;if(v!==n){const w=u.current,_=wc(m);n?h("MOUNT"):_==="none"||m?.display==="none"?h("UNMOUNT"):h(v&&w!==_?"ANIMATION_OUT":"UNMOUNT"),c.current=n}},[n,h]),yt(()=>{if(l){let m;const v=l.ownerDocument.defaultView??window,y=_=>{const S=wc(o.current).includes(CSS.escape(_.animationName));if(_.target===l&&S&&(h("ANIMATION_END"),!c.current)){const A=l.style.animationFillMode;l.style.animationFillMode="forwards",m=v.setTimeout(()=>{l.style.animationFillMode==="forwards"&&(l.style.animationFillMode=A)})}},w=_=>{_.target===l&&(u.current=wc(o.current))};return l.addEventListener("animationstart",w),l.addEventListener("animationcancel",y),l.addEventListener("animationend",y),()=>{v.clearTimeout(m),l.removeEventListener("animationstart",w),l.removeEventListener("animationcancel",y),l.removeEventListener("animationend",y)}}else h("ANIMATION_END")},[l,h]),{isPresent:["mounted","unmountSuspended"].includes(p),ref:x.useCallback(m=>{o.current=m?getComputedStyle(m):null,r(m)},[])}}function wc(n){return n?.animationName||"none"}function SN(n){let l=Object.getOwnPropertyDescriptor(n.props,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning;return r?n.ref:(l=Object.getOwnPropertyDescriptor(n,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning,r?n.props.ref:n.props.ref||n.ref)}var is="Collapsible",[wN,U0]=Wa(is),[EN,ap]=wN(is),H0=x.forwardRef((n,l)=>{const{__scopeCollapsible:r,open:o,defaultOpen:c,disabled:u,onOpenChange:d,...p}=n,[h,m]=Rl({prop:o,defaultProp:c??!1,onChange:d,caller:is});return b.jsx(EN,{scope:r,disabled:u,contentId:Xa(),open:h,onOpenToggle:x.useCallback(()=>m(v=>!v),[m]),children:b.jsx(Te.div,{"data-state":ip(h),"data-disabled":u?"":void 0,...p,ref:l})})});H0.displayName=is;var B0="CollapsibleTrigger",q0=x.forwardRef((n,l)=>{const{__scopeCollapsible:r,...o}=n,c=ap(B0,r);return b.jsx(Te.button,{type:"button","aria-controls":c.contentId,"aria-expanded":c.open||!1,"data-state":ip(c.open),"data-disabled":c.disabled?"":void 0,disabled:c.disabled,...o,ref:l,onClick:ze(n.onClick,c.onOpenToggle)})});q0.displayName=B0;var lp="CollapsibleContent",V0=x.forwardRef((n,l)=>{const{forceMount:r,...o}=n,c=ap(lp,n.__scopeCollapsible);return b.jsx(ma,{present:r||c.open,children:({present:u})=>b.jsx(_N,{...o,ref:l,present:u})})});V0.displayName=lp;var _N=x.forwardRef((n,l)=>{const{__scopeCollapsible:r,present:o,children:c,...u}=n,d=ap(lp,r),[p,h]=x.useState(o),m=x.useRef(null),v=qe(l,m),y=x.useRef(0),w=y.current,_=x.useRef(0),E=_.current,S=d.open||p,A=x.useRef(S),T=x.useRef(void 0);return x.useEffect(()=>{const O=requestAnimationFrame(()=>A.current=!1);return()=>cancelAnimationFrame(O)},[]),yt(()=>{const O=m.current;if(O){T.current=T.current||{transitionDuration:O.style.transitionDuration,animationName:O.style.animationName},O.style.transitionDuration="0s",O.style.animationName="none";const j=O.getBoundingClientRect();y.current=j.height,_.current=j.width,A.current||(O.style.transitionDuration=T.current.transitionDuration,O.style.animationName=T.current.animationName),h(o)}},[d.open,o]),b.jsx(Te.div,{"data-state":ip(d.open),"data-disabled":d.disabled?"":void 0,id:d.contentId,hidden:!S,...u,ref:v,style:{"--radix-collapsible-content-height":w?`${w}px`:void 0,"--radix-collapsible-content-width":E?`${E}px`:void 0,...n.style},children:S&&c})});function ip(n){return n?"open":"closed"}var CN=H0,AN=q0,TN=V0,wn="Accordion",ON=["Home","End","ArrowDown","ArrowUp","ArrowLeft","ArrowRight"],[rp,RN,NN]=ax(wn),[rs]=Wa(wn,[NN,U0]),op=U0(),P0=Qe.forwardRef((n,l)=>{const{type:r,...o}=n,c=o,u=o;return b.jsx(rp.Provider,{scope:n.__scopeAccordion,children:r==="multiple"?b.jsx(zN,{...u,ref:l}):b.jsx(MN,{...c,ref:l})})});P0.displayName=wn;var[G0,jN]=rs(wn),[Y0,DN]=rs(wn,{collapsible:!1}),MN=Qe.forwardRef((n,l)=>{const{value:r,defaultValue:o,onValueChange:c=()=>{},collapsible:u=!1,...d}=n,[p,h]=Rl({prop:r,defaultProp:o??"",onChange:c,caller:wn});return b.jsx(G0,{scope:n.__scopeAccordion,value:Qe.useMemo(()=>p?[p]:[],[p]),onItemOpen:h,onItemClose:Qe.useCallback(()=>u&&h(""),[u,h]),children:b.jsx(Y0,{scope:n.__scopeAccordion,collapsible:u,children:b.jsx(F0,{...d,ref:l})})})}),zN=Qe.forwardRef((n,l)=>{const{value:r,defaultValue:o,onValueChange:c=()=>{},...u}=n,[d,p]=Rl({prop:r,defaultProp:o??[],onChange:c,caller:wn}),h=Qe.useCallback(v=>p((y=[])=>[...y,v]),[p]),m=Qe.useCallback(v=>p((y=[])=>y.filter(w=>w!==v)),[p]);return b.jsx(G0,{scope:n.__scopeAccordion,value:d,onItemOpen:h,onItemClose:m,children:b.jsx(Y0,{scope:n.__scopeAccordion,collapsible:!0,children:b.jsx(F0,{...u,ref:l})})})}),[kN,os]=rs(wn),F0=Qe.forwardRef((n,l)=>{const{__scopeAccordion:r,disabled:o,dir:c,orientation:u="vertical",...d}=n,p=Qe.useRef(null),h=qe(p,l),m=RN(r),y=Hd(c)==="ltr",w=ze(n.onKeyDown,_=>{if(!ON.includes(_.key))return;const E=_.target,S=m().filter(I=>!I.ref.current?.disabled),A=S.findIndex(I=>I.ref.current===E),T=S.length;if(A===-1)return;_.preventDefault();let O=A;const j=0,z=T-1,k=()=>{O=A+1,O>z&&(O=j)},Y=()=>{O=A-1,O{const{__scopeAccordion:r,value:o,...c}=n,u=os(Pc,r),d=jN(Pc,r),p=op(r),h=Xa(),m=o&&d.value.includes(o)||!1,v=u.disabled||n.disabled;return b.jsx(LN,{scope:r,open:m,disabled:v,triggerId:h,children:b.jsx(CN,{"data-orientation":u.orientation,"data-state":J0(m),...p,...c,ref:l,disabled:v,open:m,onOpenChange:y=>{y?d.onItemOpen(o):d.onItemClose(o)}})})});X0.displayName=Pc;var I0="AccordionHeader",Q0=Qe.forwardRef((n,l)=>{const{__scopeAccordion:r,...o}=n,c=os(wn,r),u=cp(I0,r);return b.jsx(Te.h3,{"data-orientation":c.orientation,"data-state":J0(u.open),"data-disabled":u.disabled?"":void 0,...o,ref:l})});Q0.displayName=I0;var Ad="AccordionTrigger",K0=Qe.forwardRef((n,l)=>{const{__scopeAccordion:r,...o}=n,c=os(wn,r),u=cp(Ad,r),d=DN(Ad,r),p=op(r);return b.jsx(rp.ItemSlot,{scope:r,children:b.jsx(AN,{"aria-disabled":u.open&&!d.collapsible||void 0,"data-orientation":c.orientation,id:u.triggerId,...p,...o,ref:l})})});K0.displayName=Ad;var Z0="AccordionContent",W0=Qe.forwardRef((n,l)=>{const{__scopeAccordion:r,...o}=n,c=os(wn,r),u=cp(Z0,r),d=op(r);return b.jsx(TN,{role:"region","aria-labelledby":u.triggerId,"data-orientation":c.orientation,...d,...o,ref:l,style:{"--radix-accordion-content-height":"var(--radix-collapsible-content-height)","--radix-accordion-content-width":"var(--radix-collapsible-content-width)",...n.style}})});W0.displayName=Z0;function J0(n){return n?"open":"closed"}var UN=P0,HN=X0,BN=Q0,$0=K0,eS=W0;const qN=UN,jn=x.forwardRef(({className:n,...l},r)=>b.jsx(HN,{ref:r,className:Be("rounded-[1.4rem] border border-line/80 bg-paper/76 px-1",n),...l}));jn.displayName="AccordionItem";const Dn=x.forwardRef(({className:n,children:l,...r},o)=>b.jsx(BN,{className:"flex",children:b.jsxs($0,{ref:o,className:Be("group flex flex-1 items-center justify-between px-4 py-3.5 text-left text-sm font-medium text-ink transition hover:text-clay",n),...r,children:[l,b.jsx(Rd,{className:"h-4 w-4 shrink-0 text-muted transition-transform duration-200 group-data-[state=open]:rotate-180"})]})}));Dn.displayName=$0.displayName;const Mn=x.forwardRef(({className:n,children:l,...r},o)=>b.jsx(eS,{ref:o,className:"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",...r,children:b.jsx("div",{className:Be("px-4 pb-4 pt-0.5",n),children:l})}));Mn.displayName=eS.displayName;const dn=x.forwardRef(({className:n,type:l,...r},o)=>b.jsx("input",{type:l,className:Be("flex h-11 w-full rounded-2xl border border-line bg-paper px-4 text-sm text-ink shadow-[inset_0_1px_0_color-mix(in_oklab,var(--color-paper)_40%,white)] transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-clay/20 disabled:cursor-not-allowed disabled:opacity-50","placeholder:text-muted",n),ref:o,...r}));dn.displayName="Input";function VN(n,l){return x.useReducer((r,o)=>l[r][o]??r,n)}var sp="ScrollArea",[tS]=Wa(sp),[PN,pn]=tS(sp),nS=x.forwardRef((n,l)=>{const{__scopeScrollArea:r,type:o="hover",dir:c,scrollHideDelay:u=600,...d}=n,[p,h]=x.useState(null),[m,v]=x.useState(null),[y,w]=x.useState(null),[_,E]=x.useState(null),[S,A]=x.useState(null),[T,O]=x.useState(0),[j,z]=x.useState(0),[k,Y]=x.useState(!1),[U,I]=x.useState(!1),ae=qe(l,H=>h(H)),ce=Hd(c);return b.jsx(PN,{scope:r,type:o,dir:ce,scrollHideDelay:u,scrollArea:p,viewport:m,onViewportChange:v,content:y,onContentChange:w,scrollbarX:_,onScrollbarXChange:E,scrollbarXEnabled:k,onScrollbarXEnabledChange:Y,scrollbarY:S,onScrollbarYChange:A,scrollbarYEnabled:U,onScrollbarYEnabledChange:I,onCornerWidthChange:O,onCornerHeightChange:z,children:b.jsx(Te.div,{dir:ce,...d,ref:ae,style:{position:"relative","--radix-scroll-area-corner-width":T+"px","--radix-scroll-area-corner-height":j+"px",...n.style}})})});nS.displayName=sp;var aS="ScrollAreaViewport",lS=x.forwardRef((n,l)=>{const{__scopeScrollArea:r,children:o,nonce:c,...u}=n,d=pn(aS,r),p=x.useRef(null),h=qe(l,p,d.onViewportChange);return b.jsxs(b.Fragment,{children:[b.jsx("style",{dangerouslySetInnerHTML:{__html:"[data-radix-scroll-area-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-scroll-area-viewport]::-webkit-scrollbar{display:none}"},nonce:c}),b.jsx(Te.div,{"data-radix-scroll-area-viewport":"",...u,ref:h,style:{overflowX:d.scrollbarXEnabled?"scroll":"hidden",overflowY:d.scrollbarYEnabled?"scroll":"hidden",...n.style},children:b.jsx("div",{ref:d.onContentChange,style:{minWidth:"100%",display:"table"},children:o})})]})});lS.displayName=aS;var Bn="ScrollAreaScrollbar",up=x.forwardRef((n,l)=>{const{forceMount:r,...o}=n,c=pn(Bn,n.__scopeScrollArea),{onScrollbarXEnabledChange:u,onScrollbarYEnabledChange:d}=c,p=n.orientation==="horizontal";return x.useEffect(()=>(p?u(!0):d(!0),()=>{p?u(!1):d(!1)}),[p,u,d]),c.type==="hover"?b.jsx(GN,{...o,ref:l,forceMount:r}):c.type==="scroll"?b.jsx(YN,{...o,ref:l,forceMount:r}):c.type==="auto"?b.jsx(iS,{...o,ref:l,forceMount:r}):c.type==="always"?b.jsx(fp,{...o,ref:l}):null});up.displayName=Bn;var GN=x.forwardRef((n,l)=>{const{forceMount:r,...o}=n,c=pn(Bn,n.__scopeScrollArea),[u,d]=x.useState(!1);return x.useEffect(()=>{const p=c.scrollArea;let h=0;if(p){const m=()=>{window.clearTimeout(h),d(!0)},v=()=>{h=window.setTimeout(()=>d(!1),c.scrollHideDelay)};return p.addEventListener("pointerenter",m),p.addEventListener("pointerleave",v),()=>{window.clearTimeout(h),p.removeEventListener("pointerenter",m),p.removeEventListener("pointerleave",v)}}},[c.scrollArea,c.scrollHideDelay]),b.jsx(ma,{present:r||u,children:b.jsx(iS,{"data-state":u?"visible":"hidden",...o,ref:l})})}),YN=x.forwardRef((n,l)=>{const{forceMount:r,...o}=n,c=pn(Bn,n.__scopeScrollArea),u=n.orientation==="horizontal",d=ss(()=>h("SCROLL_END"),100),[p,h]=VN("hidden",{hidden:{SCROLL:"scrolling"},scrolling:{SCROLL_END:"idle",POINTER_ENTER:"interacting"},interacting:{SCROLL:"interacting",POINTER_LEAVE:"idle"},idle:{HIDE:"hidden",SCROLL:"scrolling",POINTER_ENTER:"interacting"}});return x.useEffect(()=>{if(p==="idle"){const m=window.setTimeout(()=>h("HIDE"),c.scrollHideDelay);return()=>window.clearTimeout(m)}},[p,c.scrollHideDelay,h]),x.useEffect(()=>{const m=c.viewport,v=u?"scrollLeft":"scrollTop";if(m){let y=m[v];const w=()=>{const _=m[v];y!==_&&(h("SCROLL"),d()),y=_};return m.addEventListener("scroll",w),()=>m.removeEventListener("scroll",w)}},[c.viewport,u,h,d]),b.jsx(ma,{present:r||p!=="hidden",children:b.jsx(fp,{"data-state":p==="hidden"?"hidden":"visible",...o,ref:l,onPointerEnter:ze(n.onPointerEnter,()=>h("POINTER_ENTER")),onPointerLeave:ze(n.onPointerLeave,()=>h("POINTER_LEAVE"))})})}),iS=x.forwardRef((n,l)=>{const r=pn(Bn,n.__scopeScrollArea),{forceMount:o,...c}=n,[u,d]=x.useState(!1),p=n.orientation==="horizontal",h=ss(()=>{if(r.viewport){const m=r.viewport.offsetWidth{const{orientation:r="vertical",...o}=n,c=pn(Bn,n.__scopeScrollArea),u=x.useRef(null),d=x.useRef(0),[p,h]=x.useState({content:0,viewport:0,scrollbar:{size:0,paddingStart:0,paddingEnd:0}}),m=uS(p.viewport,p.content),v={...o,sizes:p,onSizesChange:h,hasThumb:m>0&&m<1,onThumbChange:w=>u.current=w,onThumbPointerUp:()=>d.current=0,onThumbPointerDown:w=>d.current=w};function y(w,_){return ZN(w,d.current,p,_)}return r==="horizontal"?b.jsx(FN,{...v,ref:l,onThumbPositionChange:()=>{if(c.viewport&&u.current){const w=c.viewport.scrollLeft,_=Ky(w,p,c.dir);u.current.style.transform=`translate3d(${_}px, 0, 0)`}},onWheelScroll:w=>{c.viewport&&(c.viewport.scrollLeft=w)},onDragScroll:w=>{c.viewport&&(c.viewport.scrollLeft=y(w,c.dir))}}):r==="vertical"?b.jsx(XN,{...v,ref:l,onThumbPositionChange:()=>{if(c.viewport&&u.current){const w=c.viewport.scrollTop,_=Ky(w,p);u.current.style.transform=`translate3d(0, ${_}px, 0)`}},onWheelScroll:w=>{c.viewport&&(c.viewport.scrollTop=w)},onDragScroll:w=>{c.viewport&&(c.viewport.scrollTop=y(w))}}):null}),FN=x.forwardRef((n,l)=>{const{sizes:r,onSizesChange:o,...c}=n,u=pn(Bn,n.__scopeScrollArea),[d,p]=x.useState(),h=x.useRef(null),m=qe(l,h,u.onScrollbarXChange);return x.useEffect(()=>{h.current&&p(getComputedStyle(h.current))},[h]),b.jsx(oS,{"data-orientation":"horizontal",...c,ref:m,sizes:r,style:{bottom:0,left:u.dir==="rtl"?"var(--radix-scroll-area-corner-width)":0,right:u.dir==="ltr"?"var(--radix-scroll-area-corner-width)":0,"--radix-scroll-area-thumb-width":cs(r)+"px",...n.style},onThumbPointerDown:v=>n.onThumbPointerDown(v.x),onDragScroll:v=>n.onDragScroll(v.x),onWheelScroll:(v,y)=>{if(u.viewport){const w=u.viewport.scrollLeft+v.deltaX;n.onWheelScroll(w),dS(w,y)&&v.preventDefault()}},onResize:()=>{h.current&&u.viewport&&d&&o({content:u.viewport.scrollWidth,viewport:u.viewport.offsetWidth,scrollbar:{size:h.current.clientWidth,paddingStart:Yc(d.paddingLeft),paddingEnd:Yc(d.paddingRight)}})}})}),XN=x.forwardRef((n,l)=>{const{sizes:r,onSizesChange:o,...c}=n,u=pn(Bn,n.__scopeScrollArea),[d,p]=x.useState(),h=x.useRef(null),m=qe(l,h,u.onScrollbarYChange);return x.useEffect(()=>{h.current&&p(getComputedStyle(h.current))},[h]),b.jsx(oS,{"data-orientation":"vertical",...c,ref:m,sizes:r,style:{top:0,right:u.dir==="ltr"?0:void 0,left:u.dir==="rtl"?0:void 0,bottom:"var(--radix-scroll-area-corner-height)","--radix-scroll-area-thumb-height":cs(r)+"px",...n.style},onThumbPointerDown:v=>n.onThumbPointerDown(v.y),onDragScroll:v=>n.onDragScroll(v.y),onWheelScroll:(v,y)=>{if(u.viewport){const w=u.viewport.scrollTop+v.deltaY;n.onWheelScroll(w),dS(w,y)&&v.preventDefault()}},onResize:()=>{h.current&&u.viewport&&d&&o({content:u.viewport.scrollHeight,viewport:u.viewport.offsetHeight,scrollbar:{size:h.current.clientHeight,paddingStart:Yc(d.paddingTop),paddingEnd:Yc(d.paddingBottom)}})}})}),[IN,rS]=tS(Bn),oS=x.forwardRef((n,l)=>{const{__scopeScrollArea:r,sizes:o,hasThumb:c,onThumbChange:u,onThumbPointerUp:d,onThumbPointerDown:p,onThumbPositionChange:h,onDragScroll:m,onWheelScroll:v,onResize:y,...w}=n,_=pn(Bn,r),[E,S]=x.useState(null),A=qe(l,ae=>S(ae)),T=x.useRef(null),O=x.useRef(""),j=_.viewport,z=o.content-o.viewport,k=Bt(v),Y=Bt(h),U=ss(y,10);function I(ae){if(T.current){const ce=ae.clientX-T.current.left,H=ae.clientY-T.current.top;m({x:ce,y:H})}}return x.useEffect(()=>{const ae=ce=>{const H=ce.target;E?.contains(H)&&k(ce,z)};return document.addEventListener("wheel",ae,{passive:!1}),()=>document.removeEventListener("wheel",ae,{passive:!1})},[j,E,z,k]),x.useEffect(Y,[o,Y]),Ri(E,U),Ri(_.content,U),b.jsx(IN,{scope:r,scrollbar:E,hasThumb:c,onThumbChange:Bt(u),onThumbPointerUp:Bt(d),onThumbPositionChange:Y,onThumbPointerDown:Bt(p),children:b.jsx(Te.div,{...w,ref:A,style:{position:"absolute",...w.style},onPointerDown:ze(n.onPointerDown,ae=>{ae.button===0&&(ae.target.setPointerCapture(ae.pointerId),T.current=E.getBoundingClientRect(),O.current=document.body.style.webkitUserSelect,document.body.style.webkitUserSelect="none",_.viewport&&(_.viewport.style.scrollBehavior="auto"),I(ae))}),onPointerMove:ze(n.onPointerMove,I),onPointerUp:ze(n.onPointerUp,ae=>{const ce=ae.target;ce.hasPointerCapture(ae.pointerId)&&ce.releasePointerCapture(ae.pointerId),document.body.style.webkitUserSelect=O.current,_.viewport&&(_.viewport.style.scrollBehavior=""),T.current=null})})})}),Gc="ScrollAreaThumb",cS=x.forwardRef((n,l)=>{const{forceMount:r,...o}=n,c=rS(Gc,n.__scopeScrollArea);return b.jsx(ma,{present:r||c.hasThumb,children:b.jsx(QN,{ref:l,...o})})}),QN=x.forwardRef((n,l)=>{const{__scopeScrollArea:r,style:o,...c}=n,u=pn(Gc,r),d=rS(Gc,r),{onThumbPositionChange:p}=d,h=qe(l,y=>d.onThumbChange(y)),m=x.useRef(void 0),v=ss(()=>{m.current&&(m.current(),m.current=void 0)},100);return x.useEffect(()=>{const y=u.viewport;if(y){const w=()=>{if(v(),!m.current){const _=WN(y,p);m.current=_,p()}};return p(),y.addEventListener("scroll",w),()=>y.removeEventListener("scroll",w)}},[u.viewport,v,p]),b.jsx(Te.div,{"data-state":d.hasThumb?"visible":"hidden",...c,ref:h,style:{width:"var(--radix-scroll-area-thumb-width)",height:"var(--radix-scroll-area-thumb-height)",...o},onPointerDownCapture:ze(n.onPointerDownCapture,y=>{const _=y.target.getBoundingClientRect(),E=y.clientX-_.left,S=y.clientY-_.top;d.onThumbPointerDown({x:E,y:S})}),onPointerUp:ze(n.onPointerUp,d.onThumbPointerUp)})});cS.displayName=Gc;var dp="ScrollAreaCorner",sS=x.forwardRef((n,l)=>{const r=pn(dp,n.__scopeScrollArea),o=!!(r.scrollbarX&&r.scrollbarY);return r.type!=="scroll"&&o?b.jsx(KN,{...n,ref:l}):null});sS.displayName=dp;var KN=x.forwardRef((n,l)=>{const{__scopeScrollArea:r,...o}=n,c=pn(dp,r),[u,d]=x.useState(0),[p,h]=x.useState(0),m=!!(u&&p);return Ri(c.scrollbarX,()=>{const v=c.scrollbarX?.offsetHeight||0;c.onCornerHeightChange(v),h(v)}),Ri(c.scrollbarY,()=>{const v=c.scrollbarY?.offsetWidth||0;c.onCornerWidthChange(v),d(v)}),m?b.jsx(Te.div,{...o,ref:l,style:{width:u,height:p,position:"absolute",right:c.dir==="ltr"?0:void 0,left:c.dir==="rtl"?0:void 0,bottom:0,...n.style}}):null});function Yc(n){return n?parseInt(n,10):0}function uS(n,l){const r=n/l;return isNaN(r)?0:r}function cs(n){const l=uS(n.viewport,n.content),r=n.scrollbar.paddingStart+n.scrollbar.paddingEnd,o=(n.scrollbar.size-r)*l;return Math.max(o,18)}function ZN(n,l,r,o="ltr"){const c=cs(r),u=c/2,d=l||u,p=c-d,h=r.scrollbar.paddingStart+d,m=r.scrollbar.size-r.scrollbar.paddingEnd-p,v=r.content-r.viewport,y=o==="ltr"?[0,v]:[v*-1,0];return fS([h,m],y)(n)}function Ky(n,l,r="ltr"){const o=cs(l),c=l.scrollbar.paddingStart+l.scrollbar.paddingEnd,u=l.scrollbar.size-c,d=l.content-l.viewport,p=u-o,h=r==="ltr"?[0,d]:[d*-1,0],m=sd(n,h);return fS([0,d],[0,p])(m)}function fS(n,l){return r=>{if(n[0]===n[1]||l[0]===l[1])return l[0];const o=(l[1]-l[0])/(n[1]-n[0]);return l[0]+o*(r-n[0])}}function dS(n,l){return n>0&&n{})=>{let r={left:n.scrollLeft,top:n.scrollTop},o=0;return(function c(){const u={left:n.scrollLeft,top:n.scrollTop},d=r.left!==u.left,p=r.top!==u.top;(d||p)&&l(),r=u,o=window.requestAnimationFrame(c)})(),()=>window.cancelAnimationFrame(o)};function ss(n,l){const r=Bt(n),o=x.useRef(0);return x.useEffect(()=>()=>window.clearTimeout(o.current),[]),x.useCallback(()=>{window.clearTimeout(o.current),o.current=window.setTimeout(r,l)},[r,l])}function Ri(n,l){const r=Bt(l);yt(()=>{let o=0;if(n){const c=new ResizeObserver(()=>{cancelAnimationFrame(o),o=window.requestAnimationFrame(r)});return c.observe(n),()=>{window.cancelAnimationFrame(o),c.unobserve(n)}}},[n,r])}var pS=nS,JN=lS,$N=sS;const pp=x.forwardRef(({className:n,children:l,...r},o)=>b.jsxs(pS,{ref:o,className:Be("relative overflow-hidden",n),...r,children:[b.jsx(JN,{className:"h-full w-full rounded-[inherit]",children:l}),b.jsx(mp,{}),b.jsx($N,{})]}));pp.displayName=pS.displayName;const mp=x.forwardRef(({className:n,orientation:l="vertical",...r},o)=>b.jsx(up,{ref:o,orientation:l,className:Be("flex touch-none select-none transition-colors",l==="vertical"&&"h-full w-2.5 border-l border-l-transparent p-[1px]",l==="horizontal"&&"h-2.5 flex-col border-t border-t-transparent p-[1px]",n),...r,children:b.jsx(cS,{className:"relative flex-1 rounded-full bg-stone/60"})}));mp.displayName=up.displayName;var us="Switch",[ej]=Wa(us),[tj,nj]=ej(us),mS=x.forwardRef((n,l)=>{const{__scopeSwitch:r,name:o,checked:c,defaultChecked:u,required:d,disabled:p,value:h="on",onCheckedChange:m,form:v,...y}=n,[w,_]=x.useState(null),E=qe(l,j=>_(j)),S=x.useRef(!1),A=w?v||!!w.closest("form"):!0,[T,O]=Rl({prop:c,defaultProp:u??!1,onChange:m,caller:us});return b.jsxs(tj,{scope:r,checked:T,disabled:p,children:[b.jsx(Te.button,{type:"button",role:"switch","aria-checked":T,"aria-required":d,"data-state":yS(T),"data-disabled":p?"":void 0,disabled:p,value:h,...y,ref:E,onClick:ze(n.onClick,j=>{O(z=>!z),A&&(S.current=j.isPropagationStopped(),S.current||j.stopPropagation())})}),A&&b.jsx(gS,{control:w,bubbles:!S.current,name:o,value:h,checked:T,required:d,disabled:p,form:v,style:{transform:"translateX(-100%)"}})]})});mS.displayName=us;var hS="SwitchThumb",vS=x.forwardRef((n,l)=>{const{__scopeSwitch:r,...o}=n,c=nj(hS,r);return b.jsx(Te.span,{"data-state":yS(c.checked),"data-disabled":c.disabled?"":void 0,...o,ref:l})});vS.displayName=hS;var aj="SwitchBubbleInput",gS=x.forwardRef(({__scopeSwitch:n,control:l,checked:r,bubbles:o=!0,...c},u)=>{const d=x.useRef(null),p=qe(d,u),h=jx(r),m=xx(l);return x.useEffect(()=>{const v=d.current;if(!v)return;const y=window.HTMLInputElement.prototype,_=Object.getOwnPropertyDescriptor(y,"checked").set;if(h!==r&&_){const E=new Event("click",{bubbles:o});_.call(v,r),v.dispatchEvent(E)}},[h,r,o]),b.jsx("input",{type:"checkbox","aria-hidden":!0,defaultChecked:r,...c,tabIndex:-1,ref:p,style:{...c.style,...m,position:"absolute",pointerEvents:"none",opacity:0,margin:0}})});gS.displayName=aj;function yS(n){return n?"checked":"unchecked"}var bS=mS,lj=vS;const xS=x.forwardRef(({className:n,...l},r)=>b.jsx(bS,{className:Be("peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border border-transparent bg-sand transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-clay/20 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-clay",n),...l,ref:r,children:b.jsx(lj,{className:Be("pointer-events-none block h-5 w-5 rounded-full bg-paper shadow-[0_1px_2px_color-mix(in_oklab,var(--color-ink)_12%,transparent)] ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0")})}));xS.displayName=bS.displayName;const ij=["dpmpp_2m","dpmpp_2m_cfgpp","dpmpp_sde","dpmpp_sde_cfgpp","euler","euler_cfgpp","euler_ancestral","euler_ancestral_cfgpp"],rj=["karras","exponential","sgm_uniform","simple","normal","ays"],oj=["canny","depth","pose","softedge"],cj=["balanced","detailed","creative","disabled"];function ht({label:n,description:l,children:r}){return b.jsxs("div",{className:"space-y-2",children:[b.jsx(Ei,{children:n}),l?b.jsx("p",{className:"text-xs leading-5 text-muted",children:l}):null,r]})}function jt({checked:n,description:l,disabled:r,label:o,onCheckedChange:c}){return b.jsxs("div",{className:Be("flex items-center justify-between gap-4 rounded-[1.15rem] border px-3.5 py-3",r?"border-line bg-oat/32 opacity-70":"border-line bg-oat/42"),children:[b.jsxs("div",{className:"space-y-1",children:[b.jsx("p",{className:"text-sm font-medium text-ink",children:o}),l?b.jsx("p",{className:"text-xs leading-5 text-muted",children:l}):null]}),b.jsx(xS,{checked:n,disabled:r,onCheckedChange:c})]})}function Ec({tone:n,text:l}){return b.jsx("p",{className:Be("text-sm",n==="error"?"text-clay-strong":n==="warning"?"text-muted":"text-clay"),children:l})}function Ur({capability:n,label:l}){return n!==!1?null:b.jsx("p",{className:"text-xs leading-5 text-muted",children:l})}function Ya({disabled:n,onValueChange:l,options:r,placeholder:o,value:c}){return b.jsxs(E0,{disabled:n,onValueChange:l,value:c,children:[b.jsx(Jd,{children:b.jsx(_0,{placeholder:o})}),b.jsx($d,{children:r.length>0?r.map(u=>b.jsx(ep,{value:u.value,children:u.label},u.value)):b.jsx("div",{className:"px-4 py-3 text-sm text-muted",children:"No options available"})})]})}function sj(){const{availableControlNets:n,availableModels:l,settings:r,settingsHistory:o,setSettings:c,status:u}=Ia(Di(H=>({availableControlNets:H.availableControlNets,availableModels:H.availableModels,settings:H.settings,settingsHistory:H.settingsHistory,setSettings:H.setSettings,status:H.status}))),{importSettingsFromFiles:d,restoreLastSeed:p,saveSettingsSnapshot:h,updateAutotuneSettings:m}=kd(),[v,y]=x.useState(null),[w,_]=x.useState(null),[E,S]=x.useState(null),A=x.useMemo(()=>l.map(H=>({value:H.path,label:H.name})),[l]),T=x.useMemo(()=>n.map(H=>({value:H,label:H})),[n]),O=l.find(H=>H.path===r.model_path),j=O?.capabilities,z=np({accept:{"image/*":[]},maxFiles:1,multiple:!1,onDrop:H=>{(async()=>{const le=await d(H);y({tone:le.ok?le.warning?"warning":"success":"error",text:le.warning?`${le.message} ${le.warning}`:le.message})})()}}),k=(H,le=0)=>ve=>{const re=ve.currentTarget.value,de=re===""?le:Number(re);Number.isNaN(de)||c({[H]:de})},Y=H=>{c(H),y({tone:"success",text:"Restored a saved local snapshot."})},U=H=>{if(H&&r.torch_compile){(async()=>{const le=await m({stable_fast:!0,torch_compile:!1,vae_autotune:r.vae_autotune});S(le.ok?null:{tone:"error",text:le.message})})();return}c({stable_fast:H}),S(null)},I=H=>{(async()=>{const le=await m({stable_fast:H?!1:r.stable_fast,torch_compile:H,vae_autotune:r.vae_autotune});S(le.ok?null:{tone:"error",text:le.message})})()},ae=H=>{(async()=>{const le=await m({torch_compile:r.torch_compile,vae_autotune:H});S(le.ok?null:{tone:"error",text:le.message})})()},ce=[O?.type,j?.supports_img2img?"Img2Img":null,j?.supports_controlnet?"ControlNet":null,j?.supports_hires_fix?"Hires Fix":null].filter(Boolean);return b.jsxs("section",{className:"flex h-full min-h-0 flex-col overflow-hidden",children:[b.jsxs("div",{className:"space-y-1.5 border-b border-line/70 pb-3",children:[b.jsx("p",{className:"text-xs leading-5 text-muted",children:"Technical controls live here. The main prompt stays in the composer."}),b.jsx("p",{className:"text-[11px] uppercase tracking-[0.16em] text-muted",children:O?O.name:"No model selected"}),u==="error"?b.jsx(Ec,{tone:"error",text:"Generation failed. Check the backend logs."}):null]}),b.jsx(pp,{className:"soft-scroll min-h-0 flex-1",children:b.jsxs("div",{className:"space-y-5 py-4",children:[b.jsx("div",{className:"flex flex-wrap gap-2",children:ce.length>0?ce.map(H=>b.jsx("span",{className:"rounded-full bg-sand px-3 py-1.5 text-xs text-muted",children:H},H)):b.jsx("span",{className:"rounded-full bg-sand px-3 py-1.5 text-xs text-muted",children:"Waiting for model metadata"})}),b.jsxs(qN,{className:"space-y-2.5",type:"multiple",defaultValue:["output"],children:[b.jsxs(jn,{value:"output",children:[b.jsx(Dn,{children:b.jsxs("span",{className:"flex items-center gap-2",children:[b.jsx(ad,{className:"h-4 w-4 text-clay"}),"Output"]})}),b.jsx(Mn,{children:b.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[b.jsx(ht,{label:"Width",children:b.jsx(dn,{type:"number",step:"64",value:r.width,onChange:k("width",512)})}),b.jsx(ht,{label:"Height",children:b.jsx(dn,{type:"number",step:"64",value:r.height,onChange:k("height",512)})}),b.jsx(ht,{label:"Steps",children:b.jsx(dn,{type:"number",min:"1",value:r.steps,onChange:k("steps",20)})}),b.jsx(ht,{label:"CFG scale",children:b.jsx(dn,{type:"number",step:"0.5",value:r.cfg_scale,onChange:k("cfg_scale",7)})}),b.jsx(ht,{label:"Batch size",children:b.jsx(dn,{type:"number",min:"1",max:"4",value:r.batch_size,onChange:k("batch_size",1)})}),b.jsx(ht,{label:"Images",children:b.jsx(dn,{type:"number",min:"1",value:r.num_images,onChange:k("num_images",1)})})]})})]}),b.jsxs(jn,{value:"sampling",children:[b.jsx(Dn,{children:b.jsxs("span",{className:"flex items-center gap-2",children:[b.jsx(jg,{className:"h-4 w-4 text-clay"}),"Sampling"]})}),b.jsx(Mn,{children:b.jsxs("div",{className:"space-y-4",children:[b.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[b.jsx(ht,{label:"Sampler",children:b.jsx(Ya,{onValueChange:H=>c({sampler:H}),options:ij.map(H=>({value:H,label:H})),placeholder:"Sampler",value:r.sampler})}),b.jsx(ht,{label:"Scheduler",children:b.jsx(Ya,{onValueChange:H=>c({scheduler:H}),options:rj.map(H=>({value:H,label:H})),placeholder:"Scheduler",value:r.scheduler})}),b.jsx(ht,{label:"Preview fidelity",children:b.jsx(Ya,{disabled:!r.enable_preview,onValueChange:H=>c({preview_fidelity:H}),options:[{value:"low",label:"Low · faster"},{value:"balanced",label:"Balanced · default"},{value:"high",label:"High · slower"}],placeholder:"Preview fidelity",value:r.preview_fidelity||"balanced"})}),b.jsx(jt,{checked:r.reuse_seed,label:"Reuse seed",onCheckedChange:H=>c({reuse_seed:H})})]}),b.jsxs("div",{className:"grid gap-4 sm:grid-cols-[minmax(0,1fr)_auto]",children:[b.jsx(ht,{label:"Seed",children:b.jsx(dn,{type:"number",value:r.seed??-1,onChange:k("seed",-1)})}),b.jsx(Tl,{className:"self-end",type:"button",variant:"outline",onClick:()=>{(async()=>{const H=await p();_({tone:H.ok?"success":"error",text:H.message})})()},children:"Use last seed"})]}),w?b.jsx(Ec,{...w}):null]})})]}),b.jsxs(jn,{value:"enhancements",children:[b.jsx(Dn,{children:b.jsxs("span",{className:"flex items-center gap-2",children:[b.jsx(GE,{className:"h-4 w-4 text-clay"}),"Enhancements"]})}),b.jsx(Mn,{children:b.jsxs("div",{className:"space-y-3",children:[b.jsx(jt,{checked:r.hiresfix,disabled:j?.supports_hires_fix===!1,label:"High Res Fix",onCheckedChange:H=>c({hiresfix:H})}),b.jsx(Ur,{capability:j?.supports_hires_fix,label:"The selected model does not support High Res Fix."}),b.jsx(jt,{checked:r.adetailer,label:"ADetailer",onCheckedChange:H=>c({adetailer:H})}),b.jsx(jt,{checked:r.enhance_prompt,label:"Prompt enhancer",onCheckedChange:H=>c({enhance_prompt:H})}),b.jsx(jt,{checked:r.enable_preview,label:"Live preview",onCheckedChange:H=>c({enable_preview:H})})]})})]}),b.jsxs(jn,{value:"refiner",children:[b.jsx(Dn,{children:b.jsxs("span",{className:"flex items-center gap-2",children:[b.jsx(Ng,{className:"h-4 w-4 text-clay"}),"Refiner"]})}),b.jsx(Mn,{children:b.jsxs("div",{className:"space-y-4",children:[b.jsx(ht,{label:"Refiner model",children:b.jsx(Ya,{disabled:O?.type!=="SDXL",onValueChange:H=>c({refiner_model_path:H==="__none"?"":H}),options:[{value:"__none",label:"None"},...A],placeholder:"None",value:r.refiner_model_path||"__none"})}),b.jsx(ht,{label:"Switch step",children:b.jsx(dn,{disabled:!r.refiner_model_path,type:"number",min:"1",value:r.refiner_switch_step??15,onChange:k("refiner_switch_step",15)})}),b.jsx(Ur,{capability:O?.type==="SDXL",label:"Refiner selection is only relevant for SDXL base models."})]})})]}),b.jsxs(jn,{value:"img2img",children:[b.jsx(Dn,{children:b.jsxs("span",{className:"flex items-center gap-2",children:[b.jsx(FE,{className:"h-4 w-4 text-clay"}),"Image to image"]})}),b.jsx(Mn,{children:b.jsxs("div",{className:"space-y-4",children:[b.jsx(jt,{checked:r.img2img_mode,disabled:j?.supports_img2img===!1,label:"Enable Img2Img",onCheckedChange:H=>c({img2img_mode:H})}),b.jsx(Ur,{capability:j?.supports_img2img,label:"The selected model does not support Img2Img."}),r.img2img_mode?b.jsx(Qy,{label:"Input image",value:r.img2img_image,onChange:H=>c({img2img_image:H??void 0})}):null,b.jsx(ht,{label:"Denoising strength",children:b.jsx(dn,{disabled:!r.img2img_mode,type:"number",min:"0",max:"1",step:"0.05",value:r.img2img_denoise,onChange:k("img2img_denoise",.75)})})]})})]}),b.jsxs(jn,{value:"controlnet",children:[b.jsx(Dn,{children:b.jsxs("span",{className:"flex items-center gap-2",children:[b.jsx(ad,{className:"h-4 w-4 text-clay"}),"ControlNet"]})}),b.jsx(Mn,{children:b.jsxs("div",{className:"space-y-4",children:[b.jsx(jt,{checked:r.controlnet_enabled,disabled:j?.supports_controlnet===!1,label:"Enable ControlNet",onCheckedChange:H=>c({controlnet_enabled:H})}),b.jsx(Ur,{capability:j?.supports_controlnet,label:"The selected model does not support ControlNet."}),r.controlnet_enabled?b.jsxs(b.Fragment,{children:[b.jsx(ht,{label:"ControlNet model",children:b.jsx(Ya,{onValueChange:H=>c({controlnet_model:H==="__none"?void 0:H}),options:[{value:"__none",label:"Select a model"},...T],placeholder:"Select a ControlNet model",value:r.controlnet_model||"__none"})}),b.jsx(ht,{label:"Control type",children:b.jsx(Ya,{onValueChange:H=>c({controlnet_type:H}),options:oj.map(H=>({value:H,label:H})),placeholder:"Control type",value:r.controlnet_type})}),b.jsx(ht,{label:"Strength",children:b.jsx(dn,{type:"number",min:"0",max:"2",step:"0.1",value:r.controlnet_strength,onChange:k("controlnet_strength",1)})}),r.img2img_mode?b.jsx("p",{className:"text-xs leading-5 text-muted",children:"Uses the Img2Img source image."}):b.jsx(Qy,{compact:!0,label:"Control image",value:r.img2img_image,onChange:H=>c({img2img_image:H??void 0})})]}):null]})})]}),b.jsxs(jn,{value:"performance",children:[b.jsx(Dn,{children:b.jsxs("span",{className:"flex items-center gap-2",children:[b.jsx(jg,{className:"h-4 w-4 text-clay"}),"Performance and optimizations"]})}),b.jsx(Mn,{children:b.jsxs("div",{className:"space-y-3",children:[b.jsx(jt,{checked:r.stable_fast,disabled:j?.supports_stable_fast===!1,label:"Stable Fast",onCheckedChange:U}),b.jsx(Ur,{capability:j?.supports_stable_fast,label:"The selected model does not support Stable Fast."}),b.jsx(jt,{checked:r.torch_compile,disabled:r.stable_fast,description:"Compiles the diffusion model for faster repeat runs.",label:"Model autotune (torch.compile)",onCheckedChange:I}),b.jsx(jt,{checked:r.vae_autotune,description:"Compiles the VAE decoder when enabled for faster decode and encode steps.",label:"VAE autotune (torch.compile)",onCheckedChange:ae}),b.jsx(ht,{label:"Weight quantization",children:b.jsx(Ya,{onValueChange:H=>c({weight_quantization:H==="none"?null:H}),options:[{value:"none",label:"None · FP16/BF16"},{value:"fp8",label:"FP8 · 8-bit"},{value:"nvfp4",label:"NVFP4 · 4-bit"}],placeholder:"Weight quantization",value:r.weight_quantization||"none"})}),b.jsx(jt,{checked:r.keep_models_loaded,label:"Keep models loaded",onCheckedChange:H=>c({keep_models_loaded:H})}),b.jsx(jt,{checked:r.deepcache_enabled,disabled:j?.supports_deepcache===!1,label:"DeepCache",onCheckedChange:H=>c({deepcache_enabled:H})}),b.jsx(jt,{checked:r.tome_enabled,disabled:j?.supports_tome===!1,label:"ToMe",onCheckedChange:H=>c({tome_enabled:H})}),E?b.jsx(Ec,{...E}):null]})})]}),b.jsxs(jn,{value:"multiscale",children:[b.jsx(Dn,{children:b.jsxs("span",{className:"flex items-center gap-2",children:[b.jsx(Ng,{className:"h-4 w-4 text-clay"}),"Multiscale generation"]})}),b.jsx(Mn,{children:b.jsxs("div",{className:"space-y-4",children:[b.jsx(jt,{checked:r.enable_multiscale,label:"Enable multiscale",onCheckedChange:H=>c({enable_multiscale:H})}),r.enable_multiscale?b.jsxs(b.Fragment,{children:[b.jsx(ht,{label:"Preset",children:b.jsx(Ya,{onValueChange:H=>c({multiscale_preset:H}),options:cj.map(H=>({value:H,label:H})),placeholder:"Preset",value:r.multiscale_preset})}),b.jsx(ht,{label:"Factor",children:b.jsx(dn,{type:"number",min:"0.1",max:"1",step:"0.1",value:r.multiscale_factor,onChange:k("multiscale_factor",.5)})})]}):null]})})]}),b.jsxs(jn,{value:"history",children:[b.jsx(Dn,{children:b.jsxs("span",{className:"flex items-center gap-2",children:[b.jsx(AE,{className:"h-4 w-4 text-clay"}),"History and import"]})}),b.jsx(Mn,{children:b.jsxs("div",{className:"space-y-4",children:[b.jsx(jt,{checked:!!r.persist_prompt_history,label:"Include prompts in server history",onCheckedChange:H=>c({persist_prompt_history:H})}),b.jsx("div",{className:"flex flex-wrap gap-3",children:b.jsx(Tl,{type:"button",variant:"outline",onClick:()=>{(async()=>{const H=await h();y({tone:H.ok?"success":"error",text:H.message})})()},children:"Save settings"})}),b.jsxs("div",{...z.getRootProps(),className:"cursor-pointer rounded-[1.5rem] border border-dashed border-line bg-oat/55 px-4 py-5 transition hover:border-clay/35 hover:bg-oat",children:[b.jsx("input",{...z.getInputProps()}),b.jsxs("div",{className:"space-y-1 text-sm",children:[b.jsx("p",{className:"font-medium text-ink",children:"Import from image"}),b.jsx("p",{className:"text-xs leading-5 text-muted",children:"Drop an image to restore its settings."})]})]}),o.length>0?b.jsxs("div",{className:"space-y-2",children:[b.jsx("p",{className:"text-xs uppercase tracking-[0.16em] text-muted",children:"Local snapshots"}),b.jsx("div",{className:"space-y-2",children:o.slice(0,5).map(H=>b.jsxs("button",{type:"button",onClick:()=>Y(H.settings),className:"flex w-full items-center justify-between rounded-[1.2rem] border border-line bg-paper px-4 py-3 text-left transition hover:border-clay/35 hover:bg-oat/75",children:[b.jsxs("div",{children:[b.jsx("p",{className:"text-sm font-medium text-ink",children:H.settings.model_path||"Saved state"}),b.jsx("p",{className:"text-xs leading-5 text-muted",children:new Intl.DateTimeFormat(void 0,{dateStyle:"medium",timeStyle:"short"}).format(H.ts*1e3)})]}),b.jsx("span",{className:"text-xs text-muted",children:"Restore"})]},H.id))})]}):null,v?b.jsx(Ec,{...v}):null]})})]})]})]})})]})}function uj(){const{currentImage:n,gallery:l,setCurrentImage:r}=Ia(Di(o=>({currentImage:o.currentImage,gallery:o.gallery,setCurrentImage:o.setCurrentImage})));return b.jsxs("section",{className:"-mt-2 overflow-hidden rounded-b-[2rem] border border-line border-t-0 bg-paper/62 px-4 pb-3 pt-2 sm:px-5",children:[b.jsxs("div",{className:"flex items-center justify-between gap-3",children:[b.jsx("h2",{className:"font-serif text-[1.05rem] tracking-[-0.025em] text-ink",children:"Recent"}),b.jsx("p",{className:"text-xs text-muted",children:l.length===0?"No saved frames yet":`${l.length} saved`})]}),l.length===0?b.jsx("div",{className:"mt-4 rounded-[1.4rem] border border-dashed border-line bg-oat/45 px-4 py-6 text-sm text-muted",children:"Generated images will collect here for quick comparison."}):b.jsxs(pp,{className:"mt-2.5 w-full whitespace-nowrap",children:[b.jsx("div",{className:"flex gap-2 pb-2",children:l.map((o,c)=>{const u=o===n;return b.jsxs("button",{type:"button",onClick:()=>r(o),className:Be("group relative w-[4.25rem] shrink-0 overflow-hidden rounded-[1rem] border bg-paper text-left transition sm:w-[4.9rem]",u?"border-clay shadow-[0_10px_20px_-18px_color-mix(in_oklab,var(--color-clay)_28%,transparent)]":"border-line hover:-translate-y-0.5 hover:border-clay/35"),"aria-label":`Open image ${c+1}`,children:[b.jsx("img",{src:o,alt:`Generated frame ${c+1}`,loading:"lazy",decoding:"async",className:"h-[4.25rem] w-full object-cover sm:h-[4.9rem]"}),u?b.jsx("div",{className:"absolute right-3 top-3 h-2.5 w-2.5 rounded-full bg-clay"}):null]},`${c}-${o.slice(0,28)}`)})}),b.jsx(mp,{orientation:"horizontal"})]})]})}var Jf={},Wt={},$f={},Zy;function qn(){return Zy||(Zy=1,(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isEventSourceSupported=n.isReactNative=n.ReadyState=n.DEFAULT_HEARTBEAT=n.UNPARSABLE_JSON_OBJECT=n.DEFAULT_RECONNECT_INTERVAL_MS=n.DEFAULT_RECONNECT_LIMIT=n.SOCKET_IO_PING_CODE=n.SOCKET_IO_PATH=n.SOCKET_IO_PING_INTERVAL=n.DEFAULT_EVENT_SOURCE_OPTIONS=n.EMPTY_EVENT_HANDLERS=n.DEFAULT_OPTIONS=void 0;var l=1,r=1e3*l;n.DEFAULT_OPTIONS={},n.EMPTY_EVENT_HANDLERS={},n.DEFAULT_EVENT_SOURCE_OPTIONS={withCredentials:!1,events:n.EMPTY_EVENT_HANDLERS},n.SOCKET_IO_PING_INTERVAL=25*r,n.SOCKET_IO_PATH="/socket.io/?EIO=3&transport=websocket",n.SOCKET_IO_PING_CODE="2",n.DEFAULT_RECONNECT_LIMIT=20,n.DEFAULT_RECONNECT_INTERVAL_MS=5e3,n.UNPARSABLE_JSON_OBJECT={},n.DEFAULT_HEARTBEAT={message:"ping",timeout:6e4,interval:25e3};var o;(function(u){u[u.UNINSTANTIATED=-1]="UNINSTANTIATED",u[u.CONNECTING=0]="CONNECTING",u[u.OPEN=1]="OPEN",u[u.CLOSING=2]="CLOSING",u[u.CLOSED=3]="CLOSED"})(o||(n.ReadyState=o={}));var c=function(){try{return"EventSource"in globalThis}catch{return!1}};n.isReactNative=typeof navigator<"u"&&navigator.product==="ReactNative",n.isEventSourceSupported=!n.isReactNative&&c()})($f)),$f}var Hr={},ed={},Wy;function hp(){return Wy||(Wy=1,(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.resetWebSockets=n.sharedWebSockets=void 0,n.sharedWebSockets={};var l=function(r){if(r&&n.sharedWebSockets.hasOwnProperty(r))delete n.sharedWebSockets[r];else for(var o in n.sharedWebSockets)n.sharedWebSockets.hasOwnProperty(o)&&delete n.sharedWebSockets[o]};n.resetWebSockets=l})(ed)),ed}var xl={},ca={},Jy;function vp(){if(Jy)return ca;Jy=1,Object.defineProperty(ca,"__esModule",{value:!0}),ca.setUpSocketIOPing=ca.appendQueryParams=ca.parseSocketIOUrl=void 0;var n=qn(),l=function(c){if(c){var u=/^https|wss/.test(c),d=c.replace(/^(https?|wss?)(:\/\/)?/,""),p=d.replace(/\/$/,""),h=u?"wss":"ws";return"".concat(h,"://").concat(p).concat(n.SOCKET_IO_PATH)}else if(c===""){var u=/^https/.test(window.location.protocol),h=u?"wss":"ws",m=window.location.port?":".concat(window.location.port):"";return"".concat(h,"://").concat(window.location.hostname).concat(m).concat(n.SOCKET_IO_PATH)}return c};ca.parseSocketIOUrl=l;var r=function(c,u){u===void 0&&(u={});var d=/\?([\w]+=[\w]+)/,p=d.test(c),h="".concat(Object.entries(u).reduce(function(m,v){var y=v[0],w=v[1];return m+"".concat(y,"=").concat(w,"&")},"").slice(0,-1));return"".concat(c).concat(p?"&":"?").concat(h)};ca.appendQueryParams=r;var o=function(c,u){u===void 0&&(u=n.SOCKET_IO_PING_INTERVAL);var d=function(){return c(n.SOCKET_IO_PING_CODE)};return window.setInterval(d,u)};return ca.setUpSocketIOPing=o,ca}var _c={},$y;function SS(){if($y)return _c;$y=1,Object.defineProperty(_c,"__esModule",{value:!0}),_c.heartbeat=r;var n=qn();function l(o){return Array.isArray(o)?o.reduce(function(c,u){return c.current>u.current?c:u}).current:o.current}function r(o,c,u){var d=u||{},p=d.interval,h=p===void 0?n.DEFAULT_HEARTBEAT.interval:p,m=d.timeout,v=m===void 0?n.DEFAULT_HEARTBEAT.timeout:m,y=d.message,w=y===void 0?n.DEFAULT_HEARTBEAT.message:y,_=Math.max(100,h/10),E=Date.now(),S=setInterval(function(){var A=Date.now(),T=l(c);if(T+v<=A)console.warn("Heartbeat timed out, closing connection, last message received ".concat(A-T,"ms ago, last ping sent ").concat(A-E,"ms ago")),o.close();else if(T+h<=A&&E+h<=A)try{typeof w=="function"?o.send(w()):o.send(w),E=A}catch(O){console.error("Heartbeat failed, closing connection",O instanceof Error?O.message:O),o.close()}},_);return o.addEventListener("close",function(){clearInterval(S)}),function(){}}return _c}var Br={},td={},eb;function gp(){return eb||(eb=1,(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.resetSubscribers=n.removeSubscriber=n.addSubscriber=n.hasSubscribers=n.getSubscribers=void 0;var l={},r=[],o=function(h){return(0,n.hasSubscribers)(h)?Array.from(l[h]):r};n.getSubscribers=o;var c=function(h){var m;return((m=l[h])===null||m===void 0?void 0:m.size)>0};n.hasSubscribers=c;var u=function(h,m){l[h]=l[h]||new Set,l[h].add(m)};n.addSubscriber=u;var d=function(h,m){l[h].delete(m)};n.removeSubscriber=d;var p=function(h){if(h&&l.hasOwnProperty(h))delete l[h];else for(var m in l)l.hasOwnProperty(m)&&delete l[m]};n.resetSubscribers=p})(td)),td}var tb;function yp(){if(tb)return Br;tb=1,Object.defineProperty(Br,"__esModule",{value:!0}),Br.assertIsWebSocket=r,Br.resetGlobalState=o;var n=hp(),l=gp();function r(c,u){if(!u&&!(c instanceof WebSocket))throw new Error("")}function o(c){(0,l.resetSubscribers)(c),(0,n.resetWebSockets)(c)}return Br}var nb;function fj(){if(nb)return xl;nb=1;var n=xl&&xl.__assign||function(){return n=Object.assign||function(v){for(var y,w=1,_=arguments.length;w<_;w++){y=arguments[w];for(var E in y)Object.prototype.hasOwnProperty.call(y,E)&&(v[E]=y[E])}return v},n.apply(this,arguments)};Object.defineProperty(xl,"__esModule",{value:!0}),xl.attachListeners=void 0;var l=vp(),r=SS(),o=qn(),c=yp(),u=function(v,y,w,_){v.onmessage=function(E){var S;y.current.onMessage&&y.current.onMessage(E),typeof _?.current=="number"&&(_.current=Date.now()),!(typeof y.current.filter=="function"&&y.current.filter(E)!==!0)&&(y.current.heartbeat&&typeof y.current.heartbeat!="boolean"&&((S=y.current.heartbeat)===null||S===void 0?void 0:S.returnMessage)===E.data||w(E))}},d=function(v,y,w,_,E){v.onopen=function(S){if(y.current.onOpen&&y.current.onOpen(S),_.current=0,w(o.ReadyState.OPEN),y.current.heartbeat&&v instanceof WebSocket){var A=typeof y.current.heartbeat=="boolean"?void 0:y.current.heartbeat;E.current=Date.now(),(0,r.heartbeat)(v,E,A)}}},p=function(v,y,w,_,E){if(o.isEventSourceSupported&&v instanceof EventSource)return function(){};(0,c.assertIsWebSocket)(v,y.current.skipAssert);var S;return v.onclose=function(A){var T;if(y.current.onClose&&y.current.onClose(A),w(o.ReadyState.CLOSED),y.current.shouldReconnect&&y.current.shouldReconnect(A)){var O=(T=y.current.reconnectAttempts)!==null&&T!==void 0?T:o.DEFAULT_RECONNECT_LIMIT;if(E.current0&&_[_.length-1])&&(T[0]===6||T[0]===2)){v=0;continue}if(T[0]===3&&(!_||T[1]>_[0]&&T[1]<_[3])){v.label=T[1];break}if(T[0]===6&&v.label<_[1]){v.label=_[1],_=T;break}if(_&&v.label<_[2]){v.label=_[2],v.ops.push(T);break}_[2]&&v.ops.pop(),v.trys.pop();continue}T=m.call(h,v)}catch(O){T=[6,O],w=0}finally{y=_=0}if(T[0]&5)throw T[1];return{value:T[0]?T[1]:void 0,done:!0}}},o=sa&&sa.__spreadArray||function(h,m,v){if(v||arguments.length===2)for(var y=0,w=m.length,_;y0&&T[T.length-1])&&(k[0]===6||k[0]===2)){E=0;continue}if(k[0]===3&&(!T||k[1]>T[0]&&k[1]({currentImage:z.currentImage,preview:z.preview,setPreview:z.setPreview,setServerStatus:z.setServerStatus,status:z.status}))),[d,p]=x.useState(null),[h,m]=x.useState(null),v=x.useRef(null),y=x.useRef(-1),_=`${window.location.protocol==="https:"?"wss":"ws"}://${window.location.host}/ws/preview`,E=x.useCallback(z=>{try{const k=JSON.parse(z.data);if(k.type==="generation_start"&&k.generation_id){v.current=k.generation_id,y.current=-1,p(null),o(null);return}if(k.generation_id&&v.current&&k.generation_id!==v.current)return;if(k.step!==void 0){if(k.step0&&p(k.images[0]),o(k)}catch(k){console.error("Failed to parse websocket message",k)}},[o]);xj(_,{shouldReconnect:()=>!0,reconnectInterval:3e3,onOpen:()=>c(!0),onClose:()=>c(!1),onError:()=>c(!1),onMessage:E}),x.useEffect(()=>{y.current=-1},[u]),x.useEffect(()=>{u==="idle"&&(v.current=null)},[u]);const S=u==="generating",A=S?r?d:null:l,T=S&&r?.step!==void 0&&r.total_steps?r.step/r.total_steps*100:0,O=S&&r?.step!==void 0&&r.total_steps?`Step ${r.step} / ${r.total_steps}`:S?"Generating...":"Idle",j=async()=>{if(!A)return;const z=await n(A);m({tone:z.ok?z.warning?"warning":"success":"error",text:z.warning?`${z.message} ${z.warning}`:z.message})};return b.jsxs("section",{className:"overflow-hidden rounded-t-[2.25rem] border border-line border-b-0 bg-paper/90 p-2 shadow-[0_18px_42px_-36px_color-mix(in_oklab,var(--color-ink)_18%,transparent)] sm:p-3",children:[b.jsxs("div",{className:"studio-grid relative min-h-[460px] overflow-hidden rounded-[1.7rem] p-2 sm:min-h-[680px] sm:p-4",children:[S?b.jsxs("div",{className:"absolute inset-x-4 top-4 z-10 flex items-center justify-between sm:inset-x-6",children:[b.jsx("div",{className:"rounded-full border border-line bg-paper/92 px-3 py-1.5 text-[11px] uppercase tracking-[0.16em] text-muted",children:"Generating"}),b.jsx("div",{className:"rounded-full border border-line bg-paper/92 px-3 py-1.5 text-xs text-muted",children:O})]}):null,b.jsx("div",{className:"flex h-full items-center justify-center",children:A?b.jsx("img",{src:A,alt:"Generated preview",className:"max-h-[calc(100vh-10rem)] w-auto max-w-full rounded-[1.15rem] object-contain shadow-[0_16px_30px_-24px_color-mix(in_oklab,var(--color-ink)_18%,transparent)]"}):b.jsxs("div",{className:"flex max-w-lg flex-col items-center justify-center gap-5 px-4 text-center",children:[b.jsx("div",{className:"flex h-16 w-16 items-center justify-center rounded-full border border-line bg-paper text-clay",children:S?b.jsx(kE,{className:"h-6 w-6 animate-spin"}):b.jsx(OE,{className:"h-6 w-6"})}),b.jsxs("div",{className:"space-y-2",children:[b.jsx("p",{className:"font-serif text-[clamp(1.8rem,3vw,2.5rem)] tracking-[-0.035em] text-ink",children:S?"Preparing the next frame":"Ready to generate"}),b.jsx("p",{className:"text-sm leading-6 text-muted",children:S?"Live previews appear here as the run progresses.":"Choose a model, write a prompt, then generate your first frame."})]})]})}),S?b.jsx("div",{className:"pointer-events-none absolute inset-x-4 bottom-4 sm:inset-x-6",children:b.jsxs("div",{className:"rounded-[1.35rem] border border-line bg-paper/94 p-3",children:[b.jsxs("div",{className:"mb-2 flex items-center justify-between text-xs text-muted",children:[b.jsx("span",{children:"Progress"}),b.jsxs("span",{children:[Math.round(T),"%"]})]}),b.jsx("div",{className:"h-1.5 overflow-hidden rounded-full bg-sand",children:b.jsx("div",{className:"h-full rounded-full bg-clay transition-[width] duration-300",style:{width:`${T}%`}})})]})}):null]}),A?b.jsx("div",{className:"mt-1 flex justify-end pr-1",children:b.jsxs(Tl,{variant:"ghost",size:"sm",className:"text-muted hover:text-ink",onClick:()=>{j()},children:[b.jsx(DE,{className:"h-4 w-4"}),"Import settings from image"]})}):null,h?b.jsx("p",{className:Be("mt-3 text-sm",h.tone==="error"?"text-clay-strong":h.tone==="warning"?"text-muted":"text-clay"),children:h.text}):null]})}function wj(n){const l=Ej(n),r=x.forwardRef((o,c)=>{const{children:u,...d}=o,p=x.Children.toArray(u),h=p.find(Cj);if(h){const m=h.props.children,v=p.map(y=>y===h?x.Children.count(m)>1?x.Children.only(null):x.isValidElement(m)?m.props.children:null:y);return b.jsx(l,{...d,ref:c,children:x.isValidElement(m)?x.cloneElement(m,void 0,v):null})}return b.jsx(l,{...d,ref:c,children:u})});return r.displayName=`${n}.Slot`,r}function Ej(n){const l=x.forwardRef((r,o)=>{const{children:c,...u}=r;if(x.isValidElement(c)){const d=Tj(c),p=Aj(u,c.props);return c.type!==x.Fragment&&(p.ref=o?Mi(o,d):d),x.cloneElement(c,p)}return x.Children.count(c)>1?x.Children.only(null):null});return l.displayName=`${n}.SlotClone`,l}var _j=Symbol("radix.slottable");function Cj(n){return x.isValidElement(n)&&typeof n.type=="function"&&"__radixId"in n.type&&n.type.__radixId===_j}function Aj(n,l){const r={...l};for(const o in l){const c=n[o],u=l[o];/^on[A-Z]/.test(o)?c&&u?r[o]=(...p)=>{const h=u(...p);return c(...p),h}:c&&(r[o]=c):o==="style"?r[o]={...c,...u}:o==="className"&&(r[o]=[c,u].filter(Boolean).join(" "))}return{...n,...r}}function Tj(n){let l=Object.getOwnPropertyDescriptor(n.props,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning;return r?n.ref:(l=Object.getOwnPropertyDescriptor(n,"ref")?.get,r=l&&"isReactWarning"in l&&l.isReactWarning,r?n.props.ref:n.props.ref||n.ref)}var fs="Dialog",[wS]=Wa(fs),[Oj,En]=wS(fs),ES=n=>{const{__scopeDialog:l,children:r,open:o,defaultOpen:c,onOpenChange:u,modal:d=!0}=n,p=x.useRef(null),h=x.useRef(null),[m,v]=Rl({prop:o,defaultProp:c??!1,onChange:u,caller:fs});return b.jsx(Oj,{scope:l,triggerRef:p,contentRef:h,contentId:Xa(),titleId:Xa(),descriptionId:Xa(),open:m,onOpenChange:v,onOpenToggle:x.useCallback(()=>v(y=>!y),[v]),modal:d,children:r})};ES.displayName=fs;var _S="DialogTrigger",Rj=x.forwardRef((n,l)=>{const{__scopeDialog:r,...o}=n,c=En(_S,r),u=qe(l,c.triggerRef);return b.jsx(Te.button,{type:"button","aria-haspopup":"dialog","aria-expanded":c.open,"aria-controls":c.contentId,"data-state":wp(c.open),...o,ref:u,onClick:ze(n.onClick,c.onOpenToggle)})});Rj.displayName=_S;var xp="DialogPortal",[Nj,CS]=wS(xp,{forceMount:void 0}),AS=n=>{const{__scopeDialog:l,forceMount:r,children:o,container:c}=n,u=En(xp,l);return b.jsx(Nj,{scope:l,forceMount:r,children:x.Children.map(o,d=>b.jsx(ma,{present:r||u.open,children:b.jsx(Kd,{asChild:!0,container:c,children:d})}))})};AS.displayName=xp;var Fc="DialogOverlay",TS=x.forwardRef((n,l)=>{const r=CS(Fc,n.__scopeDialog),{forceMount:o=r.forceMount,...c}=n,u=En(Fc,n.__scopeDialog);return u.modal?b.jsx(ma,{present:o||u.open,children:b.jsx(Dj,{...c,ref:l})}):null});TS.displayName=Fc;var jj=wj("DialogOverlay.RemoveScroll"),Dj=x.forwardRef((n,l)=>{const{__scopeDialog:r,...o}=n,c=En(Fc,r);return b.jsx(Zd,{as:jj,allowPinchZoom:!0,shards:[c.contentRef],children:b.jsx(Te.div,{"data-state":wp(c.open),...o,ref:l,style:{pointerEvents:"auto",...o.style}})})}),Dl="DialogContent",OS=x.forwardRef((n,l)=>{const r=CS(Dl,n.__scopeDialog),{forceMount:o=r.forceMount,...c}=n,u=En(Dl,n.__scopeDialog);return b.jsx(ma,{present:o||u.open,children:u.modal?b.jsx(Mj,{...c,ref:l}):b.jsx(zj,{...c,ref:l})})});OS.displayName=Dl;var Mj=x.forwardRef((n,l)=>{const r=En(Dl,n.__scopeDialog),o=x.useRef(null),c=qe(l,r.contentRef,o);return x.useEffect(()=>{const u=o.current;if(u)return zx(u)},[]),b.jsx(RS,{...n,ref:c,trapFocus:r.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:ze(n.onCloseAutoFocus,u=>{u.preventDefault(),r.triggerRef.current?.focus()}),onPointerDownOutside:ze(n.onPointerDownOutside,u=>{const d=u.detail.originalEvent,p=d.button===0&&d.ctrlKey===!0;(d.button===2||p)&&u.preventDefault()}),onFocusOutside:ze(n.onFocusOutside,u=>u.preventDefault())})}),zj=x.forwardRef((n,l)=>{const r=En(Dl,n.__scopeDialog),o=x.useRef(!1),c=x.useRef(!1);return b.jsx(RS,{...n,ref:l,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:u=>{n.onCloseAutoFocus?.(u),u.defaultPrevented||(o.current||r.triggerRef.current?.focus(),u.preventDefault()),o.current=!1,c.current=!1},onInteractOutside:u=>{n.onInteractOutside?.(u),u.defaultPrevented||(o.current=!0,u.detail.originalEvent.type==="pointerdown"&&(c.current=!0));const d=u.target;r.triggerRef.current?.contains(d)&&u.preventDefault(),u.detail.originalEvent.type==="focusin"&&c.current&&u.preventDefault()}})}),RS=x.forwardRef((n,l)=>{const{__scopeDialog:r,trapFocus:o,onOpenAutoFocus:c,onCloseAutoFocus:u,...d}=n,p=En(Dl,r),h=x.useRef(null),m=qe(l,h);return rx(),b.jsxs(b.Fragment,{children:[b.jsx(qd,{asChild:!0,loop:!0,trapped:o,onMountAutoFocus:c,onUnmountAutoFocus:u,children:b.jsx(Bd,{role:"dialog",id:p.contentId,"aria-describedby":p.descriptionId,"aria-labelledby":p.titleId,"data-state":wp(p.open),...d,ref:m,onDismiss:()=>p.onOpenChange(!1)})}),b.jsxs(b.Fragment,{children:[b.jsx(kj,{titleId:p.titleId}),b.jsx(Uj,{contentRef:h,descriptionId:p.descriptionId})]})]})}),Sp="DialogTitle",NS=x.forwardRef((n,l)=>{const{__scopeDialog:r,...o}=n,c=En(Sp,r);return b.jsx(Te.h2,{id:c.titleId,...o,ref:l})});NS.displayName=Sp;var jS="DialogDescription",DS=x.forwardRef((n,l)=>{const{__scopeDialog:r,...o}=n,c=En(jS,r);return b.jsx(Te.p,{id:c.descriptionId,...o,ref:l})});DS.displayName=jS;var MS="DialogClose",zS=x.forwardRef((n,l)=>{const{__scopeDialog:r,...o}=n,c=En(MS,r);return b.jsx(Te.button,{type:"button",...o,ref:l,onClick:ze(n.onClick,()=>c.onOpenChange(!1))})});zS.displayName=MS;function wp(n){return n?"open":"closed"}var kS="DialogTitleWarning",[pD,LS]=GA(kS,{contentName:Dl,titleName:Sp,docsSlug:"dialog"}),kj=({titleId:n})=>{const l=LS(kS),r=`\`${l.contentName}\` requires a \`${l.titleName}\` for the component to be accessible for screen reader users. + +If you want to hide the \`${l.titleName}\`, you can wrap it with our VisuallyHidden component. + +For more information, see https://radix-ui.com/primitives/docs/components/${l.docsSlug}`;return x.useEffect(()=>{n&&(document.getElementById(n)||console.error(r))},[r,n]),null},Lj="DialogDescriptionWarning",Uj=({contentRef:n,descriptionId:l})=>{const o=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${LS(Lj).contentName}}.`;return x.useEffect(()=>{const c=n.current?.getAttribute("aria-describedby");l&&c&&(document.getElementById(l)||console.warn(o))},[o,n,l]),null},Hj=ES,Bj=AS,US=TS,HS=OS,BS=NS,qS=DS,qj=zS;const Vj=Hj,Pj=Bj,VS=x.forwardRef(({className:n,...l},r)=>b.jsx(US,{className:Be("fixed inset-0 z-50 bg-ink/14 backdrop-blur-[1.5px]",n),...l,ref:r}));VS.displayName=US.displayName;const Gj=qb("fixed z-50 gap-4 bg-paper/98 shadow-[0_22px_46px_-28px_color-mix(in_oklab,var(--color-ink)_18%,transparent)] transition ease-out",{variants:{side:{top:"inset-x-4 top-4 rounded-[2rem] border border-line p-6",bottom:"inset-x-3 bottom-3 rounded-[2rem] border border-line p-5 pb-7",left:"inset-y-3 left-3 h-auto w-3/4 rounded-[1.9rem] border border-line p-5 sm:max-w-sm",right:"inset-y-3 right-3 h-auto w-3/4 rounded-[1.9rem] border border-line p-5 sm:max-w-sm"}},defaultVariants:{side:"right"}}),PS=x.forwardRef(({side:n="right",className:l,children:r,...o},c)=>b.jsxs(Pj,{children:[b.jsx(VS,{}),b.jsxs(HS,{ref:c,className:Be(Gj({side:n}),l),...o,children:[r,b.jsxs(qj,{className:"absolute right-5 top-5 rounded-full p-2 text-muted transition hover:bg-sand hover:text-ink focus:outline-none focus:ring-2 focus:ring-clay/20",children:[b.jsx(db,{className:"h-4 w-4"}),b.jsx("span",{className:"sr-only",children:"Close"})]})]})]}));PS.displayName=HS.displayName;const Yj=({className:n,...l})=>b.jsx("div",{className:Be("flex flex-col gap-1.5 pr-10 text-left",n),...l}),GS=x.forwardRef(({className:n,...l},r)=>b.jsx(BS,{ref:r,className:Be("text-lg font-semibold text-ink",n),...l}));GS.displayName=BS.displayName;const YS=x.forwardRef(({className:n,...l},r)=>b.jsx(qS,{ref:r,className:Be("text-sm text-muted",n),...l}));YS.displayName=qS.displayName;function Fj(){const{availableModels:n,setModels:l,setControlNets:r,setSettings:o}=Ia(Di(c=>({availableModels:c.availableModels,setModels:c.setModels,setControlNets:c.setControlNets,setSettings:c.setSettings})));x.useEffect(()=>{let c=!1;const u=async()=>{try{const h=await wC();if(c)return;if(l(h),!Ia.getState().settings.model_path&&h.length>0){const v=jC(h);v&&o(kb(v,h))}}catch(h){console.error("Failed to load models",h)}},d=async()=>{try{const h=await EC();c||r(h.models)}catch(h){console.error("Failed to load ControlNet models",h)}},p=async()=>{try{const h=await TC();c||o({torch_compile:!!h.torch_compile,vae_autotune:!!h.vae_autotune})}catch(h){console.error("Failed to load settings preferences",h)}};return n.length===0&&u(),d(),p(),()=>{c=!0}},[n.length,r,l,o])}function Xj(n){const[l,r]=x.useState(()=>typeof window>"u"?!1:window.matchMedia(n).matches);return x.useEffect(()=>{const o=window.matchMedia(n),c=u=>r(u.matches);return o.addEventListener("change",c),()=>o.removeEventListener("change",c)},[n]),l}function Ij(){Fj();const[n,l]=x.useState(!1),r=Xj("(min-width: 1024px)"),o=r?"right":"bottom";return b.jsxs("div",{className:"min-h-screen bg-canvas text-ink",children:[b.jsx("div",{className:"page-halo pointer-events-none absolute inset-x-0 top-0 h-96"}),b.jsx("main",{className:"page-fade relative mx-auto flex min-h-screen w-full max-w-[1320px] flex-col px-4 pb-10 pt-4 sm:px-6",children:b.jsxs("section",{className:"mx-auto min-h-0 w-full max-w-[1200px] space-y-4 sm:space-y-5",children:[b.jsx(yR,{onOpenAdvanced:()=>l(!0)}),b.jsx(Sj,{}),b.jsx(uj,{})]})}),b.jsx(Vj,{open:n,onOpenChange:l,children:b.jsxs(PS,{side:o,className:r?"h-[calc(100vh-2rem)] w-[26rem] overflow-hidden sm:max-w-none":"h-[min(88vh,860px)] overflow-hidden",children:[b.jsxs(Yj,{children:[b.jsx(GS,{children:"Advanced controls"}),b.jsx(YS,{children:"Sampling, conditioning, optimization, and history for the next run."})]}),b.jsx("div",{className:"mt-4 h-[calc(100%-4rem)] min-h-0",children:b.jsx(sj,{})})]})})]})}pE.createRoot(document.getElementById("root")).render(b.jsx(x.StrictMode,{children:b.jsx(Ij,{})})); diff --git a/frontend/dist/assets/index-CAwyaxYh.css b/frontend/dist/assets/index-CAwyaxYh.css new file mode 100644 index 0000000000000000000000000000000000000000..7cdba429a5034bbe73b1d170db366fafbf5b07fb --- /dev/null +++ b/frontend/dist/assets/index-CAwyaxYh.css @@ -0,0 +1 @@ +@import"https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,600;9..144,700&family=Instrument+Sans:wght@400;500;600;700&display=swap";@layer components;@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-pan-x:initial;--tw-pan-y:initial;--tw-pinch-zoom:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-divide-x-reverse:0;--tw-border-style:solid;--tw-divide-y-reverse:0;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}@layer theme{:root,:host{--font-sans:"Instrument Sans", ui-sans-serif, sans-serif;--font-serif:"Fraunces", ui-serif, serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--container-sm:24rem;--container-lg:32rem;--container-3xl:48rem;--container-4xl:56rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-medium:500;--font-weight-semibold:600;--leading-tight:1.25;--radius-2xl:1rem;--radius-3xl:1.5rem;--ease-out:cubic-bezier(0, 0, .2, 1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-canvas:oklch(97.8% .012 78);--color-paper:oklch(99.2% .008 82);--color-oat:oklch(96.7% .018 79);--color-sand:oklch(94% .018 76);--color-stone:oklch(83% .016 73);--color-line:oklch(88% .012 76);--color-ink:oklch(25.5% .02 55);--color-muted:oklch(54% .015 67);--color-clay:oklch(64% .15 41);--color-clay-strong:oklch(56% .16 39);--animate-accordion-down:accordion-down .22s cubic-bezier(.16, 1, .3, 1);--animate-accordion-up:accordion-up .18s cubic-bezier(.16, 1, .3, 1)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{color:var(--color-ink);background:var(--color-canvas);font-synthesis:none;text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*{border-color:#dfdad3}@supports (color:color-mix(in lab,red,red)){*{border-color:color-mix(in oklab,var(--color-line) 92%,white)}}html,body,#root{min-height:100%}body{font-family:var(--font-sans);color:var(--color-ink);background:radial-gradient(circle at top,#fbf3e79e,#0000 31rem),linear-gradient(#fffcf7,#fdf8f0 23rem);margin:0}@supports (color:color-mix(in lab,red,red)){body{background:radial-gradient(circle at top,color-mix(in oklab,var(--color-oat) 62%,transparent),transparent 31rem),linear-gradient(180deg,color-mix(in oklab,var(--color-paper) 99%,white),color-mix(in oklab,var(--color-canvas) 92%,white) 23rem)}}button,input,textarea{font:inherit}img{max-width:100%;display:block}::selection{background:#f6ded4}@supports (color:color-mix(in lab,red,red)){::selection{background:color-mix(in oklab,var(--color-clay) 22%,white)}}}@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.not-sr-only{clip-path:none;white-space:normal;width:auto;height:auto;margin:0;padding:0;position:static;overflow:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.inset-x-0{inset-inline:calc(var(--spacing) * 0)}.inset-x-3{inset-inline:calc(var(--spacing) * 3)}.inset-x-4{inset-inline:calc(var(--spacing) * 4)}.inset-y-3{inset-block:calc(var(--spacing) * 3)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.top-5{top:calc(var(--spacing) * 5)}.right-3{right:calc(var(--spacing) * 3)}.right-5{right:calc(var(--spacing) * 5)}.bottom-3{bottom:calc(var(--spacing) * 3)}.bottom-4{bottom:calc(var(--spacing) * 4)}.left-3{left:calc(var(--spacing) * 3)}.isolate{isolation:isolate}.isolation-auto{isolation:auto}.z-10{z-index:10}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing) * 1)}.-mt-2{margin-top:calc(var(--spacing) * -2)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.block{display:block}.contents{display:contents}.flex{display:flex}.flow-root{display:flow-root}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.inline-table{display:inline-table}.list-item{display:list-item}.table{display: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{display:table-row}.table-row-group{display:table-row-group}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-11{height:calc(var(--spacing) * 11)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-28{height:calc(var(--spacing) * 28)}.h-40{height:calc(var(--spacing) * 40)}.h-52{height:calc(var(--spacing) * 52)}.h-96{height:calc(var(--spacing) * 96)}.h-\[4\.25rem\]{height:4.25rem}.h-\[calc\(100\%-4rem\)\]{height:calc(100% - 4rem)}.h-\[calc\(100vh-2rem\)\]{height:calc(100vh - 2rem)}.h-\[min\(88vh\,860px\)\]{height:min(88vh,860px)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.max-h-80{max-height:calc(var(--spacing) * 80)}.max-h-\[calc\(100vh-10rem\)\]{max-height:calc(100vh - 10rem)}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-36{min-height:calc(var(--spacing) * 36)}.min-h-40{min-height:calc(var(--spacing) * 40)}.min-h-\[108px\]{min-height:108px}.min-h-\[124px\]{min-height:124px}.min-h-\[172px\]{min-height:172px}.min-h-\[460px\]{min-height:460px}.min-h-screen{min-height:100vh}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-3\/4{width:75%}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-11{width:calc(var(--spacing) * 11)}.w-12{width:calc(var(--spacing) * 12)}.w-16{width:calc(var(--spacing) * 16)}.w-\[4\.25rem\]{width:4.25rem}.w-\[26rem\]{width:26rem}.w-auto{width:auto}.w-full{width:100%}.w-px{width:1px}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-\[1200px\]{max-width:1200px}.max-w-\[1320px\]{max-width:1320px}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.min-w-\[8rem\]{min-width:8rem}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.border-collapse{border-collapse:collapse}.translate-none{translate:none}.scale-3d{scale:var(--tw-scale-x) var(--tw-scale-y) var(--tw-scale-z)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.touch-pinch-zoom{--tw-pinch-zoom:pinch-zoom;touch-action:var(--tw-pan-x,) var(--tw-pan-y,) var(--tw-pinch-zoom,)}.touch-none{touch-action:none}.resize{resize:both}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-reverse>:not(:last-child)){--tw-space-y-reverse:1}:where(.space-x-reverse>:not(:last-child)){--tw-space-x-reverse:1}:where(.divide-x>:not(:last-child)){--tw-divide-x-reverse:0;border-inline-style:var(--tw-border-style);border-inline-start-width:calc(1px * var(--tw-divide-x-reverse));border-inline-end-width:calc(1px * calc(1 - var(--tw-divide-x-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-y-reverse>:not(:last-child)){--tw-divide-y-reverse:1}.self-end{align-self:flex-end}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-\[1\.2rem\]{border-radius:1.2rem}.rounded-\[1\.4rem\]{border-radius:1.4rem}.rounded-\[1\.5rem\]{border-radius:1.5rem}.rounded-\[1\.7rem\]{border-radius:1.7rem}.rounded-\[1\.9rem\]{border-radius:1.9rem}.rounded-\[1\.15rem\]{border-radius:1.15rem}.rounded-\[1\.35rem\]{border-radius:1.35rem}.rounded-\[1\.75rem\]{border-radius:1.75rem}.rounded-\[1rem\]{border-radius:1rem}.rounded-\[2\.1rem\]{border-radius:2.1rem}.rounded-\[2rem\]{border-radius:2rem}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-s{border-start-start-radius:.25rem;border-end-start-radius:.25rem}.rounded-ss{border-start-start-radius:.25rem}.rounded-e{border-start-end-radius:.25rem;border-end-end-radius:.25rem}.rounded-se{border-start-end-radius:.25rem}.rounded-ee{border-end-end-radius:.25rem}.rounded-es{border-end-start-radius:.25rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-\[2\.25rem\]{border-top-left-radius:2.25rem;border-top-right-radius:2.25rem}.rounded-l{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-tl{border-top-left-radius:.25rem}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.rounded-tr{border-top-right-radius:.25rem}.rounded-b{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-b-\[2rem\]{border-bottom-right-radius:2rem;border-bottom-left-radius:2rem}.rounded-br{border-bottom-right-radius:.25rem}.rounded-bl{border-bottom-left-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-x{border-inline-style:var(--tw-border-style);border-inline-width:1px}.border-y{border-block-style:var(--tw-border-style);border-block-width:1px}.border-s{border-inline-start-style:var(--tw-border-style);border-inline-start-width:1px}.border-e{border-inline-end-style:var(--tw-border-style);border-inline-end-width:1px}.border-bs{border-block-start-style:var(--tw-border-style);border-block-start-width:1px}.border-be{border-block-end-style:var(--tw-border-style);border-block-end-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-t-0{border-top-style:var(--tw-border-style);border-top-width:0}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-clay{border-color:var(--color-clay)}.border-clay-strong{border-color:var(--color-clay-strong)}.border-line{border-color:var(--color-line)}.border-line\/65{border-color:#dcd7cfa6}@supports (color:color-mix(in lab,red,red)){.border-line\/65{border-color:color-mix(in oklab,var(--color-line) 65%,transparent)}}.border-line\/70{border-color:#dcd7cfb3}@supports (color:color-mix(in lab,red,red)){.border-line\/70{border-color:color-mix(in oklab,var(--color-line) 70%,transparent)}}.border-line\/75{border-color:#dcd7cfbf}@supports (color:color-mix(in lab,red,red)){.border-line\/75{border-color:color-mix(in oklab,var(--color-line) 75%,transparent)}}.border-line\/80{border-color:#dcd7cfcc}@supports (color:color-mix(in lab,red,red)){.border-line\/80{border-color:color-mix(in oklab,var(--color-line) 80%,transparent)}}.border-transparent{border-color:#0000}.border-t-transparent{border-top-color:#0000}.border-l-transparent{border-left-color:#0000}.bg-canvas{background-color:var(--color-canvas)}.bg-canvas\/34{background-color:#fcf7ef57}@supports (color:color-mix(in lab,red,red)){.bg-canvas\/34{background-color:color-mix(in oklab,var(--color-canvas) 34%,transparent)}}.bg-canvas\/48{background-color:#fcf7ef7a}@supports (color:color-mix(in lab,red,red)){.bg-canvas\/48{background-color:color-mix(in oklab,var(--color-canvas) 48%,transparent)}}.bg-clay{background-color:var(--color-clay)}.bg-clay\/8{background-color:#d6683d14}@supports (color:color-mix(in lab,red,red)){.bg-clay\/8{background-color:color-mix(in oklab,var(--color-clay) 8%,transparent)}}.bg-clay\/10{background-color:#d6683d1a}@supports (color:color-mix(in lab,red,red)){.bg-clay\/10{background-color:color-mix(in oklab,var(--color-clay) 10%,transparent)}}.bg-ink{background-color:var(--color-ink)}.bg-ink\/14{background-color:#2b201a24}@supports (color:color-mix(in lab,red,red)){.bg-ink\/14{background-color:color-mix(in oklab,var(--color-ink) 14%,transparent)}}.bg-ink\/\[0\.04\]{background-color:#2b201a0a}@supports (color:color-mix(in lab,red,red)){.bg-ink\/\[0\.04\]{background-color:color-mix(in oklab,var(--color-ink) 4%,transparent)}}.bg-line{background-color:var(--color-line)}.bg-oat\/32{background-color:#fbf3e752}@supports (color:color-mix(in lab,red,red)){.bg-oat\/32{background-color:color-mix(in oklab,var(--color-oat) 32%,transparent)}}.bg-oat\/42{background-color:#fbf3e76b}@supports (color:color-mix(in lab,red,red)){.bg-oat\/42{background-color:color-mix(in oklab,var(--color-oat) 42%,transparent)}}.bg-oat\/45{background-color:#fbf3e773}@supports (color:color-mix(in lab,red,red)){.bg-oat\/45{background-color:color-mix(in oklab,var(--color-oat) 45%,transparent)}}.bg-oat\/55{background-color:#fbf3e78c}@supports (color:color-mix(in lab,red,red)){.bg-oat\/55{background-color:color-mix(in oklab,var(--color-oat) 55%,transparent)}}.bg-oat\/60{background-color:#fbf3e799}@supports (color:color-mix(in lab,red,red)){.bg-oat\/60{background-color:color-mix(in oklab,var(--color-oat) 60%,transparent)}}.bg-paper{background-color:var(--color-paper)}.bg-paper\/62{background-color:#fffcf79e}@supports (color:color-mix(in lab,red,red)){.bg-paper\/62{background-color:color-mix(in oklab,var(--color-paper) 62%,transparent)}}.bg-paper\/76{background-color:#fffcf7c2}@supports (color:color-mix(in lab,red,red)){.bg-paper\/76{background-color:color-mix(in oklab,var(--color-paper) 76%,transparent)}}.bg-paper\/90{background-color:#fffcf7e6}@supports (color:color-mix(in lab,red,red)){.bg-paper\/90{background-color:color-mix(in oklab,var(--color-paper) 90%,transparent)}}.bg-paper\/92{background-color:#fffcf7eb}@supports (color:color-mix(in lab,red,red)){.bg-paper\/92{background-color:color-mix(in oklab,var(--color-paper) 92%,transparent)}}.bg-paper\/94{background-color:#fffcf7f0}@supports (color:color-mix(in lab,red,red)){.bg-paper\/94{background-color:color-mix(in oklab,var(--color-paper) 94%,transparent)}}.bg-paper\/97{background-color:#fffcf7f7}@supports (color:color-mix(in lab,red,red)){.bg-paper\/97{background-color:color-mix(in oklab,var(--color-paper) 97%,transparent)}}.bg-paper\/98{background-color:#fffcf7fa}@supports (color:color-mix(in lab,red,red)){.bg-paper\/98{background-color:color-mix(in oklab,var(--color-paper) 98%,transparent)}}.bg-sand{background-color:var(--color-sand)}.bg-sand\/45{background-color:#f2eade73}@supports (color:color-mix(in lab,red,red)){.bg-sand\/45{background-color:color-mix(in oklab,var(--color-sand) 45%,transparent)}}.bg-stone\/60{background-color:#cec6bc99}@supports (color:color-mix(in lab,red,red)){.bg-stone\/60{background-color:color-mix(in oklab,var(--color-stone) 60%,transparent)}}.bg-\[radial-gradient\(circle_at_top_left\,color-mix\(in_oklab\,var\(--color-oat\)_86\%\,transparent\)\,transparent_66\%\)\]{background-image:radial-gradient(circle at 0 0,#fbf3e7db,#0000 66%)}@supports (color:color-mix(in lab,red,red)){.bg-\[radial-gradient\(circle_at_top_left\,color-mix\(in_oklab\,var\(--color-oat\)_86\%\,transparent\)\,transparent_66\%\)\]{background-image:radial-gradient(circle at top left,color-mix(in oklab,var(--color-oat) 86%,transparent),transparent 66%)}}.bg-repeat{background-repeat:repeat}.mask-no-clip{-webkit-mask-clip:no-clip;mask-clip:no-clip}.mask-repeat{-webkit-mask-repeat:repeat;mask-repeat:repeat}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-\[1px\]{padding:1px}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-1{padding-right:calc(var(--spacing) * 1)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pr-10{padding-right:calc(var(--spacing) * 10)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-7{padding-bottom:calc(var(--spacing) * 7)}.pb-10{padding-bottom:calc(var(--spacing) * 10)}.pl-8{padding-left:calc(var(--spacing) * 8)}.text-center{text-align:center}.text-left{text-align:left}.font-serif{font-family:var(--font-serif)}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[1\.05rem\]{font-size:1.05rem}.text-\[1\.35rem\]{font-size:1.35rem}.text-\[11px\]{font-size:11px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[clamp\(1\.8rem\,3vw\,2\.5rem\)\]{font-size:clamp(1.8rem,3vw,2.5rem)}.text-\[clamp\(2\.75rem\,5\.2vw\,5rem\)\]{font-size:clamp(2.75rem,5.2vw,5rem)}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-7{--tw-leading:calc(var(--spacing) * 7);line-height:calc(var(--spacing) * 7)}.leading-\[0\.92\]{--tw-leading:.92;line-height:.92}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[-0\.03em\]{--tw-tracking:-.03em;letter-spacing:-.03em}.tracking-\[-0\.025em\]{--tw-tracking:-.025em;letter-spacing:-.025em}.tracking-\[-0\.035em\]{--tw-tracking:-.035em;letter-spacing:-.035em}.tracking-\[-0\.055em\]{--tw-tracking:-.055em;letter-spacing:-.055em}.tracking-\[0\.16em\]{--tw-tracking:.16em;letter-spacing:.16em}.text-wrap{text-wrap:wrap}.text-clip{text-overflow:clip}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.text-clay{color:var(--color-clay)}.text-clay-strong{color:var(--color-clay-strong)}.text-ink{color:var(--color-ink)}.text-muted{color:var(--color-muted)}.text-paper{color:var(--color-paper)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.normal-case{text-transform:none}.uppercase{text-transform:uppercase}.italic{font-style:italic}.not-italic{font-style:normal}.diagonal-fractions{--tw-numeric-fraction:diagonal-fractions;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.lining-nums{--tw-numeric-figure:lining-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.oldstyle-nums{--tw-numeric-figure:oldstyle-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.ordinal{--tw-ordinal:ordinal;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.proportional-nums{--tw-numeric-spacing:proportional-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.slashed-zero{--tw-slashed-zero:slashed-zero;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.stacked-fractions{--tw-numeric-fraction:stacked-fractions;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.normal-nums{font-variant-numeric:normal}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.overline{text-decoration-line:overline}.underline{text-decoration-line:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.subpixel-antialiased{-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.opacity-70{opacity:.7}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_1px_2px_color-mix\(in_oklab\,var\(--color-ink\)_12\%\,transparent\)\]{--tw-shadow:0 1px 2px var(--tw-shadow-color,#2b201a1f)}@supports (color:color-mix(in lab,red,red)){.shadow-\[0_1px_2px_color-mix\(in_oklab\,var\(--color-ink\)_12\%\,transparent\)\]{--tw-shadow:0 1px 2px var(--tw-shadow-color,color-mix(in oklab,var(--color-ink) 12%,transparent))}}.shadow-\[0_1px_2px_color-mix\(in_oklab\,var\(--color-ink\)_12\%\,transparent\)\]{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_10px_20px_-18px_color-mix\(in_oklab\,var\(--color-clay\)_28\%\,transparent\)\]{--tw-shadow:0 10px 20px -18px var(--tw-shadow-color,#d6683d47)}@supports (color:color-mix(in lab,red,red)){.shadow-\[0_10px_20px_-18px_color-mix\(in_oklab\,var\(--color-clay\)_28\%\,transparent\)\]{--tw-shadow:0 10px 20px -18px var(--tw-shadow-color,color-mix(in oklab,var(--color-clay) 28%,transparent))}}.shadow-\[0_10px_20px_-18px_color-mix\(in_oklab\,var\(--color-clay\)_28\%\,transparent\)\]{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_10px_30px_-18px_color-mix\(in_oklab\,var\(--color-ink\)_48\%\,transparent\)\]{--tw-shadow:0 10px 30px -18px var(--tw-shadow-color,#2b201a7a)}@supports (color:color-mix(in lab,red,red)){.shadow-\[0_10px_30px_-18px_color-mix\(in_oklab\,var\(--color-ink\)_48\%\,transparent\)\]{--tw-shadow:0 10px 30px -18px var(--tw-shadow-color,color-mix(in oklab,var(--color-ink) 48%,transparent))}}.shadow-\[0_10px_30px_-18px_color-mix\(in_oklab\,var\(--color-ink\)_48\%\,transparent\)\]{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_12px_30px_-22px_color-mix\(in_oklab\,var\(--color-clay\)_50\%\,transparent\)\]{--tw-shadow:0 12px 30px -22px var(--tw-shadow-color,#d6683d80)}@supports (color:color-mix(in lab,red,red)){.shadow-\[0_12px_30px_-22px_color-mix\(in_oklab\,var\(--color-clay\)_50\%\,transparent\)\]{--tw-shadow:0 12px 30px -22px var(--tw-shadow-color,color-mix(in oklab,var(--color-clay) 50%,transparent))}}.shadow-\[0_12px_30px_-22px_color-mix\(in_oklab\,var\(--color-clay\)_50\%\,transparent\)\]{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_16px_30px_-24px_color-mix\(in_oklab\,var\(--color-ink\)_18\%\,transparent\)\]{--tw-shadow:0 16px 30px -24px var(--tw-shadow-color,#2b201a2e)}@supports (color:color-mix(in lab,red,red)){.shadow-\[0_16px_30px_-24px_color-mix\(in_oklab\,var\(--color-ink\)_18\%\,transparent\)\]{--tw-shadow:0 16px 30px -24px var(--tw-shadow-color,color-mix(in oklab,var(--color-ink) 18%,transparent))}}.shadow-\[0_16px_30px_-24px_color-mix\(in_oklab\,var\(--color-ink\)_18\%\,transparent\)\]{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_18px_42px_-36px_color-mix\(in_oklab\,var\(--color-ink\)_18\%\,transparent\)\]{--tw-shadow:0 18px 42px -36px var(--tw-shadow-color,#2b201a2e)}@supports (color:color-mix(in lab,red,red)){.shadow-\[0_18px_42px_-36px_color-mix\(in_oklab\,var\(--color-ink\)_18\%\,transparent\)\]{--tw-shadow:0 18px 42px -36px var(--tw-shadow-color,color-mix(in oklab,var(--color-ink) 18%,transparent))}}.shadow-\[0_18px_42px_-36px_color-mix\(in_oklab\,var\(--color-ink\)_18\%\,transparent\)\]{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_20px_48px_-36px_color-mix\(in_oklab\,var\(--color-ink\)_16\%\,transparent\)\]{--tw-shadow:0 20px 48px -36px var(--tw-shadow-color,#2b201a29)}@supports (color:color-mix(in lab,red,red)){.shadow-\[0_20px_48px_-36px_color-mix\(in_oklab\,var\(--color-ink\)_16\%\,transparent\)\]{--tw-shadow:0 20px 48px -36px var(--tw-shadow-color,color-mix(in oklab,var(--color-ink) 16%,transparent))}}.shadow-\[0_20px_48px_-36px_color-mix\(in_oklab\,var\(--color-ink\)_16\%\,transparent\)\]{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_22px_46px_-28px_color-mix\(in_oklab\,var\(--color-ink\)_18\%\,transparent\)\]{--tw-shadow:0 22px 46px -28px var(--tw-shadow-color,#2b201a2e)}@supports (color:color-mix(in lab,red,red)){.shadow-\[0_22px_46px_-28px_color-mix\(in_oklab\,var\(--color-ink\)_18\%\,transparent\)\]{--tw-shadow:0 22px 46px -28px var(--tw-shadow-color,color-mix(in oklab,var(--color-ink) 18%,transparent))}}.shadow-\[0_22px_46px_-28px_color-mix\(in_oklab\,var\(--color-ink\)_18\%\,transparent\)\]{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_28px_80px_-28px_color-mix\(in_oklab\,var\(--color-ink\)_20\%\,transparent\)\]{--tw-shadow:0 28px 80px -28px var(--tw-shadow-color,#2b201a33)}@supports (color:color-mix(in lab,red,red)){.shadow-\[0_28px_80px_-28px_color-mix\(in_oklab\,var\(--color-ink\)_20\%\,transparent\)\]{--tw-shadow:0 28px 80px -28px var(--tw-shadow-color,color-mix(in oklab,var(--color-ink) 20%,transparent))}}.shadow-\[0_28px_80px_-28px_color-mix\(in_oklab\,var\(--color-ink\)_20\%\,transparent\)\]{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[inset_0_1px_0_color-mix\(in_oklab\,var\(--color-paper\)_40\%\,white\)\]{--tw-shadow:inset 0 1px 0 var(--tw-shadow-color,#fffefc)}@supports (color:color-mix(in lab,red,red)){.shadow-\[inset_0_1px_0_color-mix\(in_oklab\,var\(--color-paper\)_40\%\,white\)\]{--tw-shadow:inset 0 1px 0 var(--tw-shadow-color,color-mix(in oklab,var(--color-paper) 40%,white))}}.shadow-\[inset_0_1px_0_color-mix\(in_oklab\,var\(--color-paper\)_40\%\,white\)\]{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.inset-ring{--tw-inset-ring-shadow:inset 0 0 0 1px var(--tw-inset-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter: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,)}.drop-shadow{--tw-drop-shadow-size:drop-shadow(0 1px 2px var(--tw-drop-shadow-color,#0000001a)) drop-shadow(0 1px 1px var(--tw-drop-shadow-color,#0000000f));--tw-drop-shadow:drop-shadow(0 1px 2px #0000001a) drop-shadow(0 1px 1px #0000000f);filter: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,)}.filter{filter: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,)}.filter\!{filter: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,)!important}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter: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,);backdrop-filter: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,)}.backdrop-blur-\[1\.5px\]{--tw-backdrop-blur:blur(1.5px);-webkit-backdrop-filter: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,);backdrop-filter: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,)}.backdrop-grayscale{--tw-backdrop-grayscale:grayscale(100%);-webkit-backdrop-filter: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,);backdrop-filter: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,)}.backdrop-invert{--tw-backdrop-invert:invert(100%);-webkit-backdrop-filter: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,);backdrop-filter: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,)}.backdrop-sepia{--tw-backdrop-sepia:sepia(100%);-webkit-backdrop-filter: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,);backdrop-filter: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,)}.backdrop-filter{-webkit-backdrop-filter: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,);backdrop-filter: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,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[color\,background-color\,border-color\,box-shadow\,transform\]{transition-property:color,background-color,border-color,box-shadow,transform;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}:where(.divide-x-reverse>:not(:last-child)){--tw-divide-x-reverse:1}.ring-inset{--tw-ring-inset:inset}.group-data-\[state\=open\]\:rotate-180:is(:where(.group)[data-state=open] *){rotate:180deg}.placeholder\:text-muted::placeholder{color:var(--color-muted)}@media(hover:hover){.hover\:-translate-y-0\.5:hover{--tw-translate-y:calc(var(--spacing) * -.5);translate:var(--tw-translate-x) var(--tw-translate-y)}.hover\:border-clay\/35:hover{border-color:#d6683d59}@supports (color:color-mix(in lab,red,red)){.hover\:border-clay\/35:hover{border-color:color-mix(in oklab,var(--color-clay) 35%,transparent)}}.hover\:border-clay\/40:hover{border-color:#d6683d66}@supports (color:color-mix(in lab,red,red)){.hover\:border-clay\/40:hover{border-color:color-mix(in oklab,var(--color-clay) 40%,transparent)}}.hover\:border-clay\/45:hover{border-color:#d6683d73}@supports (color:color-mix(in lab,red,red)){.hover\:border-clay\/45:hover{border-color:color-mix(in oklab,var(--color-clay) 45%,transparent)}}.hover\:bg-clay-strong:hover{background-color:var(--color-clay-strong)}.hover\:bg-ink\/92:hover{background-color:#2b201aeb}@supports (color:color-mix(in lab,red,red)){.hover\:bg-ink\/92:hover{background-color:color-mix(in oklab,var(--color-ink) 92%,transparent)}}.hover\:bg-oat:hover{background-color:var(--color-oat)}.hover\:bg-oat\/75:hover{background-color:#fbf3e7bf}@supports (color:color-mix(in lab,red,red)){.hover\:bg-oat\/75:hover{background-color:color-mix(in oklab,var(--color-oat) 75%,transparent)}}.hover\:bg-paper:hover{background-color:var(--color-paper)}.hover\:bg-sand:hover{background-color:var(--color-sand)}.hover\:text-clay:hover{color:var(--color-clay)}.hover\:text-ink:hover{color:var(--color-ink)}}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-clay\/20:focus{--tw-ring-color:#d6683d33}@supports (color:color-mix(in lab,red,red)){.focus\:ring-clay\/20:focus{--tw-ring-color:color-mix(in oklab, var(--color-clay) 20%, transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-clay\/20:focus-visible{--tw-ring-color:#d6683d33}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-clay\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-clay) 20%, transparent)}}.focus-visible\:ring-clay\/25:focus-visible{--tw-ring-color:#d6683d40}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-clay\/25:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-clay) 25%, transparent)}}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-45:disabled{opacity:.45}.disabled\:opacity-50:disabled{opacity:.5}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-40[data-disabled]{opacity:.4}.data-\[highlighted\]\:bg-sand[data-highlighted]{background-color:var(--color-sand)}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:calc(var(--spacing) * 1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[state\=checked\]\:translate-x-5[data-state=checked]{--tw-translate-x:calc(var(--spacing) * 5);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[state\=checked\]\:bg-clay[data-state=checked]{background-color:var(--color-clay)}.data-\[state\=closed\]\:animate-accordion-up[data-state=closed]{animation:var(--animate-accordion-up)}.data-\[state\=open\]\:animate-accordion-down[data-state=open]{animation:var(--animate-accordion-down)}.data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked]{--tw-translate-x:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}@media(min-width:40rem){.sm\:inset-x-6{inset-inline:calc(var(--spacing) * 6)}.sm\:h-\[4\.9rem\]{height:4.9rem}.sm\:min-h-\[680px\]{min-height:680px}.sm\:w-\[4\.9rem\]{width:4.9rem}.sm\:max-w-none{max-width:none}.sm\:max-w-sm{max-width:var(--container-sm)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}:where(.sm\:space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}.sm\:p-3{padding:calc(var(--spacing) * 3)}.sm\:p-4{padding:calc(var(--spacing) * 4)}.sm\:px-5{padding-inline:calc(var(--spacing) * 5)}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}.sm\:px-7{padding-inline:calc(var(--spacing) * 7)}.sm\:py-7{padding-block:calc(var(--spacing) * 7)}}@media(min-width:64rem){.lg\:grid-cols-\[minmax\(0\,1\.2fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.2fr) minmax(0,1fr)}.lg\:grid-cols-\[minmax\(0\,1fr\)_15rem\]{grid-template-columns:minmax(0,1fr) 15rem}.lg\:items-start{align-items:flex-start}.lg\:items-stretch{align-items:stretch}.lg\:justify-between{justify-content:space-between}.lg\:p-5{padding:calc(var(--spacing) * 5)}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&\>span\]\:line-clamp-1>span{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.page-fade{animation:.28s cubic-bezier(.22,1,.36,1) page-fade}.studio-panel{background:#fffcf7}@supports (color:color-mix(in lab,red,red)){.studio-panel{background:color-mix(in oklab,var(--color-paper) 94%,white)}}.studio-panel{box-shadow:0 12px 32px -30px #2b201a1f}@supports (color:color-mix(in lab,red,red)){.studio-panel{box-shadow:0 12px 32px -30px color-mix(in oklab,var(--color-ink) 12%,transparent)}}.studio-grid{background:radial-gradient(circle at top,#fbf3e761,#0000 62%),linear-gradient(#fffcf7,#fdfbf6)}@supports (color:color-mix(in lab,red,red)){.studio-grid{background:radial-gradient(circle at top,color-mix(in oklab,var(--color-oat) 38%,transparent),transparent 62%),linear-gradient(180deg,color-mix(in oklab,var(--color-paper) 97%,white),color-mix(in oklab,var(--color-oat) 36%,white))}}.soft-scroll{scrollbar-width:thin;scrollbar-color:#cec6bca6 transparent}@supports (color:color-mix(in lab,red,red)){.soft-scroll{scrollbar-color:color-mix(in oklab,var(--color-stone) 65%,transparent) transparent}}.page-halo{background:radial-gradient(circle at top,#fbf3e7c7,#0000 66%),linear-gradient(#fffcf7f5,#0000 80%)}@supports (color:color-mix(in lab,red,red)){.page-halo{background:radial-gradient(circle at top,color-mix(in oklab,var(--color-oat) 78%,transparent),transparent 66%),linear-gradient(180deg,color-mix(in oklab,var(--color-paper) 96%,transparent),transparent 80%)}}}@keyframes accordion-down{0%{height:0}to{height:var(--radix-accordion-content-height)}}@keyframes accordion-up{0%{height:var(--radix-accordion-content-height)}to{height:0}}@keyframes page-fade{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes section-rise{0%{opacity:0;transform:translateY(18px)}to{opacity:1;transform:translateY(0)}}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-pan-x{syntax:"*";inherits:false}@property --tw-pan-y{syntax:"*";inherits:false}@property --tw-pinch-zoom{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@keyframes spin{to{transform:rotate(360deg)}} diff --git a/frontend/dist/index.html b/frontend/dist/index.html new file mode 100644 index 0000000000000000000000000000000000000000..a3a9cd5d091d70f4a4df2505089dca28170f1a41 --- /dev/null +++ b/frontend/dist/index.html @@ -0,0 +1,14 @@ + + + + + + + LightDiffusion Next + + + + +
+ + diff --git a/frontend/dist/vite.svg b/frontend/dist/vite.svg new file mode 100644 index 0000000000000000000000000000000000000000..e7b8dfb1b2a60bd50538bec9f876511b9cac21e3 --- /dev/null +++ b/frontend/dist/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js new file mode 100644 index 0000000000000000000000000000000000000000..5e6b472f583e34a1cca751440d4f241495475723 --- /dev/null +++ b/frontend/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000000000000000000000000000000000000..d8aa1298fbdda2a3031296093b03b3ea03c06ecb --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + LightDiffusion Next + + +
+ + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..9dd9d38f7212c42f49c2e67bd71b76c00c711326 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,5348 @@ +{ + "name": "frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.0.0", + "dependencies": { + "@radix-ui/react-accordion": "^1.2.12", + "@radix-ui/react-collapsible": "^1.1.12", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-switch": "^1.2.6", + "axios": "^1.13.4", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^1.8.0", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-dropzone": "^14.4.0", + "react-use-websocket": "^4.13.0", + "tailwind-merge": "^3.5.0", + "zustand": "^5.0.11" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@tailwindcss/vite": "^4.2.2", + "@types/node": "^24.10.1", + "@types/react": "^19.2.5", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "tailwindcss": "^4.2.2", + "typescript": "~5.9.3", + "typescript-eslint": "^8.46.4", + "vite": "^7.2.4" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz", + "integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz", + "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.4", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.7.tgz", + "integrity": "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.5" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-accordion": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", + "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz", + "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", + "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", + "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", + "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", + "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tailwindcss/node": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.2.tgz", + "integrity": "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.19.0", + "jiti": "^2.6.1", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.2.2" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.2.tgz", + "integrity": "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.2.2", + "@tailwindcss/oxide-darwin-arm64": "4.2.2", + "@tailwindcss/oxide-darwin-x64": "4.2.2", + "@tailwindcss/oxide-freebsd-x64": "4.2.2", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.2", + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.2", + "@tailwindcss/oxide-linux-arm64-musl": "4.2.2", + "@tailwindcss/oxide-linux-x64-gnu": "4.2.2", + "@tailwindcss/oxide-linux-x64-musl": "4.2.2", + "@tailwindcss/oxide-wasm32-wasi": "4.2.2", + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.2", + "@tailwindcss/oxide-win32-x64-msvc": "4.2.2" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.2.tgz", + "integrity": "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.2.tgz", + "integrity": "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.2.tgz", + "integrity": "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.2.tgz", + "integrity": "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.2.tgz", + "integrity": "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.2.tgz", + "integrity": "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.2.tgz", + "integrity": "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.2.tgz", + "integrity": "sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.2.tgz", + "integrity": "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.2.tgz", + "integrity": "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.8.1", + "@emnapi/runtime": "^1.8.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.1", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz", + "integrity": "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.2.tgz", + "integrity": "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.2.tgz", + "integrity": "sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.2.2", + "@tailwindcss/oxide": "4.2.2", + "tailwindcss": "4.2.2" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7 || ^8" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.13.tgz", + "integrity": "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.13", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.13.tgz", + "integrity": "sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "devOptional": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.55.0.tgz", + "integrity": "sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.55.0", + "@typescript-eslint/type-utils": "8.55.0", + "@typescript-eslint/utils": "8.55.0", + "@typescript-eslint/visitor-keys": "8.55.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.55.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.55.0.tgz", + "integrity": "sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.55.0", + "@typescript-eslint/types": "8.55.0", + "@typescript-eslint/typescript-estree": "8.55.0", + "@typescript-eslint/visitor-keys": "8.55.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.55.0.tgz", + "integrity": "sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.55.0", + "@typescript-eslint/types": "^8.55.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.55.0.tgz", + "integrity": "sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.55.0", + "@typescript-eslint/visitor-keys": "8.55.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.55.0.tgz", + "integrity": "sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.55.0.tgz", + "integrity": "sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.55.0", + "@typescript-eslint/typescript-estree": "8.55.0", + "@typescript-eslint/utils": "8.55.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.55.0.tgz", + "integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.55.0.tgz", + "integrity": "sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.55.0", + "@typescript-eslint/tsconfig-utils": "8.55.0", + "@typescript-eslint/types": "8.55.0", + "@typescript-eslint/visitor-keys": "8.55.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.55.0.tgz", + "integrity": "sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.55.0", + "@typescript-eslint/types": "8.55.0", + "@typescript-eslint/typescript-estree": "8.55.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz", + "integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.55.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", + "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/attr-accept": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz", + "integrity": "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001769", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz", + "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", + "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", + "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/file-selector": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-2.1.2.tgz", + "integrity": "sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==", + "license": "MIT", + "dependencies": { + "tslib": "^2.7.0" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.8.0.tgz", + "integrity": "sha512-WuvlsjngSk7TnTBJ1hsCy3ql9V9VOdcPkd3PKcSmM34vJD8KG6molxz7m7zbYFgICwsanQWmJ13JlYs4Zp7Arw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-dropzone": { + "version": "14.4.1", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.4.1.tgz", + "integrity": "sha512-QDuV76v3uKbHiH34SpwifZ+gOLi1+RdsCO1kl5vxMT4wW8R82+sthjvBw4th3NHF/XX6FBsqDYZVNN+pnhaw0g==", + "license": "MIT", + "dependencies": { + "attr-accept": "^2.2.4", + "file-selector": "^2.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "react": ">= 16.8 || 18.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-use-websocket": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-4.13.0.tgz", + "integrity": "sha512-anMuVoV//g2N76Wxqvqjjo1X48r9Np3y1/gMl7arX84tAPXdy5R7sB5lO5hvCzQRYjqXwV8XMAiEBOUbyrZFrw==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/rollup": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tailwind-merge": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz", + "integrity": "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz", + "integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.2.tgz", + "integrity": "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.55.0.tgz", + "integrity": "sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.55.0", + "@typescript-eslint/parser": "8.55.0", + "@typescript-eslint/typescript-estree": "8.55.0", + "@typescript-eslint/utils": "8.55.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + }, + "node_modules/zustand": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.11.tgz", + "integrity": "sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000000000000000000000000000000000000..11b1a302632bd2fe8033f9e1e407ffe49ca8d54f --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,49 @@ +{ + "name": "frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@radix-ui/react-accordion": "^1.2.12", + "@radix-ui/react-collapsible": "^1.1.12", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-switch": "^1.2.6", + "axios": "^1.13.4", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^1.8.0", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-dropzone": "^14.4.0", + "react-use-websocket": "^4.13.0", + "tailwind-merge": "^3.5.0", + "zustand": "^5.0.11" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@tailwindcss/vite": "^4.2.2", + "@types/node": "^24.10.1", + "@types/react": "^19.2.5", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "tailwindcss": "^4.2.2", + "typescript": "~5.9.3", + "typescript-eslint": "^8.46.4", + "vite": "^7.2.4" + } +} diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg new file mode 100644 index 0000000000000000000000000000000000000000..e7b8dfb1b2a60bd50538bec9f876511b9cac21e3 --- /dev/null +++ b/frontend/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c2eac7fbad2b9d4977588f1dc5699e734219a4be --- /dev/null +++ b/frontend/src/App.tsx @@ -0,0 +1,57 @@ +import { useState } from 'react'; +import { GenerationComposer } from './components/GenerationComposer'; +import { GenerationSettings } from './components/GenerationSettings'; +import { Gallery } from './components/Gallery'; +import { ImagePreview } from './components/ImagePreview'; +import { + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + SheetTitle, +} from './components/ui/sheet'; +import { useGenerationBootstrap } from './hooks/use-generation-bootstrap'; +import { useMediaQuery } from './hooks/use-media-query'; + +export default function App() { + useGenerationBootstrap(); + + const [controlsOpen, setControlsOpen] = useState(false); + const isDesktop = useMediaQuery('(min-width: 1024px)'); + const controlSide = isDesktop ? 'right' : 'bottom'; + + return ( +
+
+ +
+
+ setControlsOpen(true)} /> + + +
+
+ + + + + Advanced controls + + Sampling, conditioning, optimization, and history for the next run. + + +
+ +
+
+
+
+ ); +} diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts new file mode 100644 index 0000000000000000000000000000000000000000..cb282b24f6cb0be5d704214676fc862ca965a942 --- /dev/null +++ b/frontend/src/api/client.ts @@ -0,0 +1,70 @@ +import axios from 'axios'; +import type { + GenerationSettings, + GenerationResponse, + ImageMetadata, + ModelInfo, + SettingsPreferences, + SettingsSnapshot, +} from '../types'; + +const api = axios.create({ + baseURL: '/api', // Proxy handles redirection to localhost:7861 +}); + +export const listModels = async (): Promise => { + const res = await api.get('/models'); + return res.data; +}; + +export const listControlNets = async (): Promise<{ models: string[] }> => { + const res = await api.get<{ models: string[] }>('/controlnets'); + return res.data; +}; + +export const generateImage = async (settings: GenerationSettings): Promise => { + const res = await api.post('/generate', settings); + console.log("Generation response:", res.data); + return res.data; +}; + +export const interruptGeneration = async (): Promise => { + await api.post('/interrupt'); +}; + +export const getLastSeed = async (): Promise<{ seed: number | null }> => { + const res = await api.get('/settings/last'); + return res.data; +}; + +export const getSettingsHistory = async (): Promise<{ history: SettingsSnapshot[] }> => { + const res = await api.get('/settings/history'); + return res.data; +}; + +export const getSettingsPreferences = async (): Promise => { + const res = await api.get('/settings/preferences'); + return res.data; +}; + +export const postSettingsPreferences = async (preferences: SettingsPreferences): Promise => { + const res = await api.post('/settings/preferences', preferences); + return res.data; +}; + +export const postSettingsSnapshot = async (settings: GenerationSettings, include_prompt: boolean = false): Promise<{ snapshot: SettingsSnapshot }> => { + const res = await api.post('/settings/history', { settings, include_prompt }); + return res.data; +}; + +export const getImageMetadata = async (imageB64: string): Promise<{ metadata: ImageMetadata }> => { + const res = await api.post('/images/metadata', { image: imageB64 }); + return res.data; +}; + +export const getTelemetry = async (): Promise> => { + const res = await api.get('/telemetry'); + return res.data; +} + +export default api; diff --git a/frontend/src/assets/react.svg b/frontend/src/assets/react.svg new file mode 100644 index 0000000000000000000000000000000000000000..6c87de9bb3358469122cc991d5cf578927246184 --- /dev/null +++ b/frontend/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/components/Gallery.tsx b/frontend/src/components/Gallery.tsx new file mode 100644 index 0000000000000000000000000000000000000000..14b91e732402675178a9d5e2f36cad36059a4571 --- /dev/null +++ b/frontend/src/components/Gallery.tsx @@ -0,0 +1,62 @@ +import { ScrollArea, ScrollBar } from './ui/scroll-area'; +import { useStore } from '../store/useStore'; +import { cn } from '../lib/utils'; +import { useShallow } from 'zustand/react/shallow'; + +export function Gallery() { + const { currentImage, gallery, setCurrentImage } = useStore(useShallow((state) => ({ + currentImage: state.currentImage, + gallery: state.gallery, + setCurrentImage: state.setCurrentImage, + }))); + + return ( +
+
+

Recent

+

+ {gallery.length === 0 ? 'No saved frames yet' : `${gallery.length} saved`} +

+
+ + {gallery.length === 0 ? ( +
+ Generated images will collect here for quick comparison. +
+ ) : ( + +
+ {gallery.map((image, index) => { + const isSelected = image === currentImage; + + return ( + + ); + })} +
+ +
+ )} +
+ ); +} diff --git a/frontend/src/components/GenerationComposer.tsx b/frontend/src/components/GenerationComposer.tsx new file mode 100644 index 0000000000000000000000000000000000000000..046a721f97965bdd312443cffd9543825ada6d0a --- /dev/null +++ b/frontend/src/components/GenerationComposer.tsx @@ -0,0 +1,164 @@ +import { useMemo, useState } from 'react'; +import { PanelRightOpen, Sparkles } from 'lucide-react'; +import { useGenerationActions } from '../hooks/use-generation-actions'; +import { getModelSelectionUpdates } from '../lib/settings'; +import { useStore } from '../store/useStore'; +import { Button } from './ui/button'; +import { Label } from './ui/label'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from './ui/select'; +import { Textarea } from './ui/textarea'; +import { useShallow } from 'zustand/react/shallow'; + +interface GenerationComposerProps { + onOpenAdvanced: () => void; +} + +export function GenerationComposer({ onOpenAdvanced }: GenerationComposerProps) { + const { handleGenerate } = useGenerationActions(); + const { availableModels, serverStatus, setSettings, settings, status } = useStore( + useShallow((state) => ({ + availableModels: state.availableModels, + serverStatus: state.serverStatus, + setSettings: state.setSettings, + settings: state.settings, + status: state.status, + })), + ); + const [negativePromptOpen, setNegativePromptOpen] = useState(false); + + const modelOptions = useMemo( + () => availableModels.map((model) => ({ label: model.name, value: model.path })), + [availableModels], + ); + const activeModel = availableModels.find((model) => model.path === settings.model_path); + + const handleModelChange = (value: string) => { + const selectedModel = availableModels.find((model) => model.path === value); + if (!selectedModel) { + setSettings({ model_path: value }); + return; + } + + setSettings(getModelSelectionUpdates(selectedModel, availableModels)); + }; + + return ( +
+
+ +
+
+
+
+ + Generate +
+
+

+ Generate the next frame. +

+

+ Choose a model, write the prompt, and run. Advanced controls stay out of the way until you need them. +

+
+
+ + {!serverStatus ? ( + Engine offline + ) : null} +
+
+ +
+ + +

+ {activeModel ? `${activeModel.type} ready` : 'Models load automatically when the backend is available.'} +

+
+
+ +
+
+
+ + +
+