diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..920c08b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +# Nothing is COPY'd into the image — the Dockerfile clones from GitHub. +# This file is kept as a safeguard in case a COPY is added later. + +# Secrets — never bake certs or keys into the image +secrets/ + +# OS +.DS_Store +Thumbs.db diff --git a/.gitignore b/.gitignore index d4bb158..9a4722b 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,4 @@ experiments/ # Local databases NAS_Database/ Django_database/ +.claudeignore diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..05fc2ba --- /dev/null +++ b/Dockerfile @@ -0,0 +1,87 @@ +# ============================================================ +# SpikesortingLabHub — Production Image +# +# Self-contained: downloads the repo from GitHub so anyone can +# reproduce this image without needing the local source tree. +# ============================================================ + +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive + +# ------------------------------------------------------------ +# 1. System packages +# ------------------------------------------------------------ +RUN apt-get update && apt-get upgrade -y --no-install-recommends +RUN apt-get install -y --no-install-recommends \ + python3 \ + python3-venv \ + python3-pip \ + build-essential \ + libpq-dev \ + openssl \ + ca-certificates \ + curl \ + git \ + nodejs \ + npm \ + wget \ + unzip \ + && rm -rf /var/lib/apt/lists/* + +# ------------------------------------------------------------ +# 2. Download repository (docker branch) and unpack +# ------------------------------------------------------------ +WORKDIR /app +RUN wget -q https://github.com/UserFriendlySpikesorting/SpikesortingLabHub-server/archive/refs/heads/developing_branch.zip \ + && unzip -q developing_branch.zip \ + && mv SpikesortingLabHub-server-developing_branch/* . \ + && rm -rf developing_branch.zip SpikesortingLabHub-server-developing_branch + +# ------------------------------------------------------------ +# 3. Set up Python virtual environment and install requirements +# ------------------------------------------------------------ +RUN python3 -m venv /app/venv +RUN /app/venv/bin/pip install --no-cache-dir -r requirements.txt + +# Install SpikesortingLabHub-CLI (patch setup.py for Python 3.12) +RUN wget https://github.com/UserFriendlySpikesorting/SpikesortingLabHub-CLI/archive/refs/heads/main.zip \ + && unzip main.zip \ + && sed -i 's|3.13|3.12|' SpikesortingLabHub-CLI-main/setup.py \ + && /app/venv/bin/pip install --no-cache-dir SpikesortingLabHub-CLI-main/ + +ENV PATH="/app/venv/bin:$PATH" + +# ------------------------------------------------------------ +# 4. Build the React frontend +# my-app/build/ is gitignored so it must be compiled here. +# ------------------------------------------------------------ +RUN cd my-app && npm ci --omit=dev && npm run build + +# ------------------------------------------------------------ +# 5. Placeholder directories for bind mounts +# Docker Compose overlays the real host paths at runtime. +# /data ← trurnasdata (read-only NAS database) +# /django_db ← persistentdata (Django SQLite DB + logs) +# /experiments ← binary recording files (read-only) +# ------------------------------------------------------------ +RUN mkdir -p /data /app/django_db /app/experiments /app/secrets + +# ------------------------------------------------------------ +# 6. Entrypoint — already in the repo after download. +# Runs pre-flight checks, collectstatic, migrate, then Gunicorn. +# ------------------------------------------------------------ +RUN chmod +x /app/entrypoint.sh +ENTRYPOINT ["/app/entrypoint.sh"] + +# ------------------------------------------------------------ +# 7. Expose ports +# 9000 — plain HTTP +# 9443 — HTTPS (Gunicorn with --certfile / --keyfile) +# ------------------------------------------------------------ +EXPOSE 9000 9443 + +# ------------------------------------------------------------ +# 8. Default command — passed to entrypoint.sh via exec "$@". +# ------------------------------------------------------------ +CMD ["gunicorn", "-c", "gunicorn.conf.py", "labhub.wsgi:application"] diff --git a/INSTRUCTIONS.md b/INSTRUCTIONS.md new file mode 100644 index 0000000..92be5ac --- /dev/null +++ b/INSTRUCTIONS.md @@ -0,0 +1,108 @@ +# SpikesortingLabHub — TrueNAS Deployment Instructions + +Steps tested on the test rig. Replicate these exactly on the main TrueNAS. + +> **Path difference:** test rig used `user_home`, main TrueNAS uses `users`. +> Every path below already reflects the main TrueNAS convention. + +--- + +## 1. Enable SSH on TrueNAS + +TrueNAS UI → System → Services → start **SSH** and set it to auto-start. + +--- + +## 2. Copy the init script from your Mac to TrueNAS + +Run from your Mac terminal (not SSH): + +```bash +scp /Users/kajalpatel/SpikesortingLabHub-server/truenas_init.sh \ + kajal@128.164.33.182:/mnt/root_data_storage/users/kajal/ +``` + +--- + +## 3. SSH into TrueNAS + +```bash +ssh truenas_admin@128.164.33.182 +``` + +--- + +## 4. Move the script into the sslh folder + +```bash +sudo cp /mnt/root_data_storage/users/kajal/truenas_init.sh \ + /mnt/root_data_storage/users/sslh/truenas_init.sh + +sudo chmod +x /mnt/root_data_storage/users/sslh/truenas_init.sh +``` + +--- + +## 5. Test-run the script manually + +```bash +sudo /mnt/root_data_storage/users/sslh/truenas_init.sh +``` + +Check the log it generates: + +```bash +cat /mnt/root_data_storage/users/sslh/sslh_init.log +``` + +--- + +## 6. Pull the Docker image and start the container (first time only) + +```bash +docker pull ikajalpatel21/spikesorting-labhub-latestimg:latest + +export DJANGO_SECRET_KEY="$(cat /mnt/root_data_storage/users/sslh/secrets/django_secret.key)" + +docker compose -f /mnt/root_data_storage/users/sslh/docker-compose.yml up -d +``` + +> If `secrets/django_secret.key` does not exist yet, generate it first: +> ```bash +> mkdir -p /mnt/root_data_storage/users/sslh/secrets +> openssl rand -hex 50 > /mnt/root_data_storage/users/sslh/secrets/django_secret.key +> chmod 600 /mnt/root_data_storage/users/sslh/secrets/django_secret.key +> ``` + +--- + +## 7. Verify the container is running + +```bash +docker ps +docker logs spikesorting-labhub-server-spikesorting-labhub-1 +``` + +Open in browser: `https://128.164.33.182:9443` +(self-signed cert warning is expected — click through) + +--- + +## 8. Register the init script in TrueNAS UI + +System → Advanced Settings → Init/Shutdown Scripts → **Add** + +| Field | Value | +|---------|---------------------------------------------------------| +| Type | Script | +| Script | `/mnt/root_data_storage/users/sslh/truenas_init.sh` | +| When | Pre Init | +| Timeout | 30 | + +--- + +## What happens on every reboot after this + +1. TrueNAS kernel starts → ZFS pool mounts automatically +2. Pre Init script runs → verifies/creates bind-mount directories → bind-mounts experiments and trurnasdata +3. Docker daemon starts → `restart: unless-stopped` brings the container back up with all mounts in place diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index 3cdaf51..0000000 --- a/deploy.sh +++ /dev/null @@ -1,299 +0,0 @@ -#!/bin/bash - -# ============================================================================= -# QModel Django Deployment Script -# ============================================================================= -# This script sets up the complete environment for the qmodel branch including: -# - GitHub repository setup -# - Virtual environment creation -# - Dependencies installation -# - Database initialization -# - SSL certificate generation -# - Static files collection -# - Server startup options -# ============================================================================= - -set -e # Exit on any error - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Configuration -REPO_URL="https://github.com/iKajalpatel21/spikesorting-labhub-try-error.git" -BRANCH_NAME="qmodel" -PROJECT_DIR="spikesorting-labhub-try-error" -VENV_NAME=".djangovenv" - -# Function to print colored output -print_status() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -print_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -print_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -print_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Function to check if command exists -command_exists() { - command -v "$1" >/dev/null 2>&1 -} - -# ============================================================================= -# 1. System Requirements Check -# ============================================================================= -print_status "Checking system requirements..." - -if ! command_exists python3; then - print_error "Python3 is not installed. Please install Python3 first." - exit 1 -fi - -if ! command_exists git; then - print_error "Git is not installed. Please install Git first." - exit 1 -fi - -if ! command_exists openssl; then - print_error "OpenSSL is not installed. Please install OpenSSL first." - exit 1 -fi - -print_success "All system requirements are met." - -# ============================================================================= -# 2. Repository Setup -# ============================================================================= -print_status "Setting up repository..." - -# Check if we're already in the project directory -if [[ $(basename "$PWD") == "$PROJECT_DIR" ]]; then - print_status "Already in project directory. Pulling latest changes..." - git fetch origin - git checkout $BRANCH_NAME || git checkout -b $BRANCH_NAME origin/$BRANCH_NAME - git pull origin $BRANCH_NAME -else - # Check if project directory exists - if [ -d "$PROJECT_DIR" ]; then - print_status "Project directory exists. Updating..." - cd "$PROJECT_DIR" - git fetch origin - git checkout $BRANCH_NAME || git checkout -b $BRANCH_NAME origin/$BRANCH_NAME - git pull origin $BRANCH_NAME - else - print_status "Cloning repository..." - git clone -b $BRANCH_NAME $REPO_URL $PROJECT_DIR - cd "$PROJECT_DIR" - fi -fi - -print_success "Repository setup complete." - -# ============================================================================= -# 3. Virtual Environment Setup -# ============================================================================= -print_status "Setting up Python virtual environment..." - -# Create virtual environment if it doesn't exist -if [ ! -d "$VENV_NAME" ]; then - python3 -m venv $VENV_NAME || { - print_error "Failed to create virtual environment" - exit 1 - } -fi - -# Activate virtual environment -source $VENV_NAME/bin/activate || { - print_error "Failed to activate virtual environment" - exit 1 -} - -print_success "Virtual environment activated." - -# ============================================================================= -# 4. Dependencies Installation -# ============================================================================= -print_status "Installing/updating dependencies..." - -# Update pip -pip install -U pip || { - print_error "Failed to update pip" - exit 1 -} - -# Install requirements -if [ -f "requirements.txt" ]; then - pip install -U -r requirements.txt || { - print_error "Failed to install requirements from requirements.txt" - exit 1 - } -else - # Fallback to manual installation - print_warning "requirements.txt not found. Installing core dependencies manually..." - pip install -U django djangorestframework requests gunicorn urllib3 || { - print_error "Failed to install core dependencies" - exit 1 - } -fi - -print_success "Dependencies installed successfully." - -# ============================================================================= -# 5. Database Setup -# ============================================================================= -print_status "Setting up database..." - -# Ask user if they want to reset the database -read -p "Do you want to reset the database? This will clear all existing data. (y/N): " -n 1 -r -echo -if [[ $REPLY =~ ^[Yy]$ ]]; then - print_warning "Resetting database..." - echo -n > db.sqlite3 -fi - -# Run migrations -print_status "Running database migrations..." -python manage.py makemigrations || { - print_error "Failed to create migrations" - exit 1 -} - -python manage.py migrate || { - print_error "Failed to run migrations" - exit 1 -} - -print_success "Database setup complete." - -# ============================================================================= -# 6. Create Superuser (Optional) -# ============================================================================= -read -p "Do you want to create a superuser? (y/N): " -n 1 -r -echo -if [[ $REPLY =~ ^[Yy]$ ]]; then - print_status "Creating superuser..." - python manage.py createsuperuser --username admin || { - print_warning "Superuser creation failed or was skipped" - } -fi - -# ============================================================================= -# 7. SSL Certificate Generation -# ============================================================================= -print_status "Checking SSL certificates..." - -mkdir -p secrets -if [ ! -f "secrets/cert.crt" ] || [ ! -f "secrets/cert.key" ]; then - print_status "Generating self-signed SSL certificate..." - # Use the machine's actual IP/hostname as CN so clients can verify it. - # SAN (subjectAltName) covers both the hostname and IP address. - SERVER_HOST=$(hostname -f 2>/dev/null || hostname) - SERVER_IP=$(hostname -I 2>/dev/null | awk '{print $1}') - print_status "Certificate CN: ${SERVER_HOST} (IP: ${SERVER_IP})" - - openssl req -x509 -newkey rsa:4096 -keyout secrets/cert.key -out secrets/cert.crt -days 365 -nodes \ - -subj "/CN=${SERVER_HOST}" \ - -addext "subjectAltName=DNS:${SERVER_HOST},IP:${SERVER_IP},DNS:localhost,IP:127.0.0.1" || { - print_error "Failed to generate SSL certificates" - exit 1 - } - print_success "SSL certificate generated: secrets/cert.crt / secrets/cert.key (CN=${SERVER_HOST})" -else - print_success "SSL certificates already exist (secrets/cert.crt / secrets/cert.key)." -fi - -# ============================================================================= -# 8. Static Files Collection -# ============================================================================= -print_status "Collecting static files..." -yes yes | python manage.py collectstatic || { - print_warning "Static files collection failed or was skipped" -} - -print_success "Static files collected." - -# ============================================================================= -# 9. Server Startup Options -# ============================================================================= -print_success "Deployment complete! Choose how to run the server:" -echo -echo "Available options:" -echo "1) Development server (HTTP on port 8000)" -echo "2) Gunicorn server (HTTP on port 8000)" -echo "3) Gunicorn server with HTTPS (port 8443)" -echo "4) Just setup - don't start server" -echo "5) Start worker only" -echo - -read -p "Enter your choice (1-5): " -n 1 -r -echo - -case $REPLY in - 1) - print_status "Starting Django development server..." - python manage.py runserver - ;; - 2) - print_status "Starting Gunicorn HTTP server..." - gunicorn -c gunicorn.conf.py labhub.wsgi:application - ;; - 3) - print_status "Starting Gunicorn HTTPS server (port 443)..." - gunicorn -c gunicorn.conf.py \ - --certfile=secrets/cert.crt \ - --keyfile=secrets/cert.key \ - -b 0.0.0.0:443 \ - labhub.wsgi:application - ;; - 4) - print_success "Setup complete. You can manually start the server when ready." - echo - echo "To start the development server: python manage.py runserver" - echo "To start Gunicorn HTTP: gunicorn -c gunicorn.conf.py labhub.wsgi:application" - echo "To start Gunicorn HTTPS: gunicorn -c gunicorn.conf.py --certfile=secrets/cert.crt --keyfile=secrets/cert.key -b 0.0.0.0:443 labhub.wsgi:application" - echo "To start worker: python qmodel_worker.py" - ;; - 5) - print_status "Starting qmodel worker..." - python qmodel_worker.py - ;; - *) - print_warning "Invalid choice. Setup complete but no server started." - ;; -esac - -# ============================================================================= -# 10. Final Instructions -# ============================================================================= -echo -print_success "=== Deployment Summary ===" -echo "Project: $PROJECT_DIR" -echo "Branch: $BRANCH_NAME" -echo "Virtual Environment: $VENV_NAME" -echo "Database: SQLite (db.sqlite3)" -echo "SSL Certificates: cert.pem, key.pem" -echo -echo "=== Usage Instructions ===" -echo "• HTTP — Django admin: http://localhost:8000/admin/" -echo "• HTTPS — Django admin: https://localhost:443/admin/" -echo "• HTTP — Worker fetch: http://localhost:8000/job-queue/next-job/" -echo "• HTTPS — Worker fetch: https://localhost:443/job-queue/next-job/" -echo "• Worker (HTTP): python qmodel_worker.py" -echo "• Worker (HTTPS): LABHUB_BASE_URL=https://localhost LABHUB_SSL_VERIFY=false python qmodel_worker.py" -echo -echo "=== Multiple Terminal Setup ===" -echo "Terminal 1 (Server): ./deploy.sh (choose option 2 or 3)" -echo "Terminal 2 (Worker): source $VENV_NAME/bin/activate && python qmodel_worker.py" -echo -print_success "Setup complete! Enjoy your deployment and run the server as needed." diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..139cdd1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,74 @@ +# ============================================================ +# SpikesortingLabHub — Docker Compose +# +# Bind-mount layout (host path → container path): +# +# trurnasdata /mnt/root_data_storage/users/sslh/trurnasdata → /data (read-only — NAS database) +# persistentdata /mnt/root_data_storage/users/sslh/persistentdata → /django_db (read/write — Django DB + logs) +# experiments /mnt/root_data_storage/experiments → /experiments (read-only — binary recordings) +# +# Ports 8000, 8080, and 8443 are used by the NAS itself — avoid them. +# +# Usage: +# export DJANGO_SECRET_KEY="your-secret-key" +# docker compose build +# docker compose up -d +# (entrypoint.sh generates SSL certs automatically on first start) +# ============================================================ + +services: + spikesorting-labhub: + image: ikajalpatel21/spikesorting-labhub-latestimg:latest + restart: unless-stopped + + command: + - gunicorn + - -c + - gunicorn.conf.py + - --certfile=/app/secrets/cert.crt + - --keyfile=/app/secrets/cert.key + - -b + - 0.0.0.0:9443 + - labhub.wsgi:application + + ports: + - "9443:9443" # HTTPS — Gunicorn binds here via command: override above + + environment: + # Django core + DJANGO_SECRET_KEY: "${DJANGO_SECRET_KEY}" + DJANGO_DEBUG: "False" + + # Database lives on the persistentdata mount + DATABASE_PATH: "/django_db/db.sqlite3" + + # Tell Django where the NAS root is so $NAS$ placeholders resolve + NAS_ROOT: "/data" + + # Scan these directories for .bin / .prb data files + DATA_DIRS: "/experiments,/experiments/probes" + + # Path to the TrueNAS SQLite user database (used by FreeNASBackend for login) + NAS_DB_PATH: "/data/freenas-v1.db" + volumes: + # trurnasdata — NAS database (read-only) + - type: bind + source: /mnt/root_data_storage/users/sslh/truenasdata + target: /data + read_only: true + + # persistentdata — Django SQLite DB + logs (read/write) + - type: bind + source: /mnt/root_data_storage/users/sslh/persistentdata + target: /django_db + + # experiments — binary recording files (read-only) + - type: bind + source: /mnt/root_data_storage/experiments + target: /experiments + read_only: true + + # secrets — SSL certs generated by entrypoint.sh on first start (read-write) + - type: bind + source: /mnt/root_data_storage/users/sslh/secrets + target: /app/secrets diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..6211164 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,69 @@ +#!/bin/bash +set -e +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +ok() { echo -e "${GREEN}[OK]${NC} $1"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +info() { echo "$1"; } + + +# ============================================================================= +# 1. Check the database directory (mounted from persistentdata on the host) +# ============================================================================= +DB_PATH="${DATABASE_PATH:-/app/django_db/db.sqlite3}" +DB_DIR="$(dirname "$DB_PATH")" + +# mkdir -p "$DB_DIR" + +if [ -f "$DB_PATH" ]; then + ok "SQLite database exists: $DB_PATH" +else + warn "SQLite database not found: $DB_PATH" + info "Creating SQLite DB via Django migrations..." + + python manage.py migrate --noinput + + ok "SQLite database created and migrations applied." +fi + +# ============================================================================= +# 2. Generate SSL certificate if not already present +# ============================================================================= +# mkdir -p /app/secrets + +if [ -f "/app/secrets/cert.crt" ] && [ -f "/app/secrets/cert.key" ]; then + ok "SSL certificates already exist — leaving untouched." +else + echo "Generating self-signed TLS certificate into /app/secrets/..." + + SERVER_HOST=$(hostname -f 2>/dev/null || hostname) + SERVER_IP=$(hostname -I 2>/dev/null | awk '{print $1}') + [ -z "$SERVER_IP" ] && SERVER_IP="127.0.0.1" + + openssl req -x509 -newkey rsa:4096 \ + -keyout /app/secrets/cert.key \ + -out /app/secrets/cert.crt \ + -days 365 -nodes \ + -subj "/CN=${SERVER_HOST}" \ + -addext "subjectAltName=DNS:${SERVER_HOST},IP:${SERVER_IP},DNS:localhost,IP:127.0.0.1" + + ok "Certificate created (CN=${SERVER_HOST}, IP=${SERVER_IP})" +fi + +# ============================================================================= +# 3. Collect static files — needs DJANGO_SECRET_KEY from the environment. +# ============================================================================= +python manage.py collectstatic --noinput + +# ============================================================================= +# 4. Run database migrations — safe to run repeatedly. +# ============================================================================= +python manage.py migrate --noinput + +# ============================================================================= +# 5. Hand off to the main process (Gunicorn). +# ============================================================================= +exec "$@" diff --git a/gunicorn.conf.py b/gunicorn.conf.py index 932bc8e..0b739de 100644 --- a/gunicorn.conf.py +++ b/gunicorn.conf.py @@ -6,7 +6,7 @@ Usage: HTTP: gunicorn -c gunicorn.conf.py labhub.wsgi:application - HTTPS: gunicorn -c gunicorn.conf.py --certfile=secrets/cert.crt --keyfile=secrets/cert.key -b 0.0.0.0:443 labhub.wsgi:application + HTTPS: gunicorn -c gunicorn.conf.py --certfile=cert.crt --keyfile=cert.key -b 0.0.0.0:9443 labhub.wsgi:application On Linux, binding to port 443 requires one of: sudo gunicorn ... @@ -18,7 +18,7 @@ # ----------------------------------------------------------------------------- # Server socket (overridden by -b on the command line when using HTTPS) # ----------------------------------------------------------------------------- -bind = "0.0.0.0:8000" +bind = "0.0.0.0:9000" backlog = 2048 # ----------------------------------------------------------------------------- diff --git a/job_queue/models.py b/job_queue/models.py index 7d40337..c5eda93 100644 --- a/job_queue/models.py +++ b/job_queue/models.py @@ -127,6 +127,19 @@ def create_a_job(job_evn: dict, job_steps: list) -> "Job": f"Create the config first before creating the job." ) + # Detect duplicate identifiers before hitting the DB unique constraint. + # Two pipeline steps with identical config blocks share the same SHA-256 hash + # and therefore the same identifier, which violates unique_together=(job, identifier). + seen: set = set() + for step in job_steps: + identifier = step["identifier"] + if identifier in seen: + raise RuntimeError( + f"Duplicate step identifier '{identifier[:16]}...': two steps share the " + "same configuration block. Each step in a job must have a distinct config." + ) + seen.add(identifier) + # Create the Job and JobSteps atomically with transaction.atomic(): # All-or-nothing transaction job = Job.objects.create( diff --git a/job_queue/tests/test_models.py b/job_queue/tests/test_models.py index 85ea3f1..c8d3578 100644 --- a/job_queue/tests/test_models.py +++ b/job_queue/tests/test_models.py @@ -175,6 +175,37 @@ def test_creation_is_atomic(self): ]) self.assertEqual(Job.objects.count(), count_before) + def test_raises_for_duplicate_step_identifiers(self): + """ + Two steps with identical config blocks get the same SHA-256 identifier. + create_a_job must raise RuntimeError before hitting the DB unique constraint, + rather than letting the database produce a cryptic IntegrityError. + + This can happen in practice when a pipeline has two steps (e.g. two phy_export + steps) that share exactly the same configuration block, including an empty one {}. + """ + empty_hash = get_or_create_step_configs("phy_export", {}) + duplicate_steps = [ + {"function": "phy_export", "identifier": empty_hash, "depends": []}, + {"function": "phy_export", "identifier": empty_hash, "depends": []}, + ] + with self.assertRaises(RuntimeError) as ctx: + create_a_job({}, duplicate_steps) + self.assertIn("Duplicate", str(ctx.exception)) + + def test_duplicate_check_does_not_create_job(self): + """No Job row must be created when duplicate identifiers are rejected.""" + empty_hash = get_or_create_step_configs("phy_export", {}) + count_before = Job.objects.count() + try: + create_a_job({}, [ + {"function": "phy_export", "identifier": empty_hash, "depends": []}, + {"function": "phy_export", "identifier": empty_hash, "depends": []}, + ]) + except RuntimeError: + pass + self.assertEqual(Job.objects.count(), count_before) + # ============================================================================ # get_next_job_id() diff --git a/labhub/templates/asset-manifest.json b/labhub/templates/asset-manifest.json index a513f57..1cc38f0 100644 --- a/labhub/templates/asset-manifest.json +++ b/labhub/templates/asset-manifest.json @@ -1,15 +1,15 @@ { "files": { - "main.css": "/static/css/main.39cfbafe.css", - "main.js": "/static/js/main.9aca0609.js", + "main.css": "/static/css/main.b405a2cd.css", + "main.js": "/static/js/main.d15b9f18.js", "static/js/453.96453769.chunk.js": "/static/js/453.96453769.chunk.js", "index.html": "/index.html", - "main.39cfbafe.css.map": "/static/css/main.39cfbafe.css.map", - "main.9aca0609.js.map": "/static/js/main.9aca0609.js.map", + "main.b405a2cd.css.map": "/static/css/main.b405a2cd.css.map", + "main.d15b9f18.js.map": "/static/js/main.d15b9f18.js.map", "453.96453769.chunk.js.map": "/static/js/453.96453769.chunk.js.map" }, "entrypoints": [ - "static/css/main.39cfbafe.css", - "static/js/main.9aca0609.js" + "static/css/main.b405a2cd.css", + "static/js/main.d15b9f18.js" ] } \ No newline at end of file diff --git a/my-app/build/asset-manifest.json b/my-app/build/asset-manifest.json index a513f57..35372bb 100644 --- a/my-app/build/asset-manifest.json +++ b/my-app/build/asset-manifest.json @@ -1,15 +1,15 @@ { "files": { - "main.css": "/static/css/main.39cfbafe.css", - "main.js": "/static/js/main.9aca0609.js", + "main.css": "/static/css/main.af6adb2f.css", + "main.js": "/static/js/main.d98d43c8.js", "static/js/453.96453769.chunk.js": "/static/js/453.96453769.chunk.js", "index.html": "/index.html", - "main.39cfbafe.css.map": "/static/css/main.39cfbafe.css.map", - "main.9aca0609.js.map": "/static/js/main.9aca0609.js.map", + "main.af6adb2f.css.map": "/static/css/main.af6adb2f.css.map", + "main.d98d43c8.js.map": "/static/js/main.d98d43c8.js.map", "453.96453769.chunk.js.map": "/static/js/453.96453769.chunk.js.map" }, "entrypoints": [ - "static/css/main.39cfbafe.css", - "static/js/main.9aca0609.js" + "static/css/main.af6adb2f.css", + "static/js/main.d98d43c8.js" ] } \ No newline at end of file diff --git a/my-app/build/index.html b/my-app/build/index.html index a26a976..9d23568 100644 --- a/my-app/build/index.html +++ b/my-app/build/index.html @@ -1 +1 @@ -Spike Sorting Lab Hub
\ No newline at end of file +Spike Sorting Lab Hub
\ No newline at end of file diff --git a/my-app/build/static/css/main.c20849f5.css b/my-app/build/static/css/main.c20849f5.css deleted file mode 100644 index 934d376..0000000 --- a/my-app/build/static/css/main.c20849f5.css +++ /dev/null @@ -1,2 +0,0 @@ -body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#f0efe8;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;margin:0}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.fb-overlay{align-items:center;background:#00000073;display:flex;inset:0;justify-content:center;position:fixed;z-index:1000}.fb-modal{background:#fff;border-radius:8px;box-shadow:0 8px 32px #00000038;display:flex;flex-direction:column;max-height:80vh;max-width:95vw;overflow:hidden;width:640px}.fb-header{align-items:center;background:#f5f5f0;border-bottom:1px solid #e5e5e5;display:flex;justify-content:space-between;padding:14px 18px}.fb-title{color:#1e1e1e;font-size:.95rem;font-weight:600}.fb-close{background:none;border:none;border-radius:4px;color:#666;cursor:pointer;font-size:1rem;padding:2px 6px}.fb-close:hover{background:#e0e0e0;color:#1e1e1e}.fb-breadcrumb{align-items:center;background:#fafaf7;border-bottom:1px solid #eee;display:flex;flex-wrap:wrap;font-size:.8rem;gap:2px;padding:8px 18px}.fb-crumb-btn{background:none;border:none;border-radius:3px;color:#5a7a3a;cursor:pointer;font-size:.8rem;padding:2px 4px}.fb-crumb-btn:hover{background:#e8f0dc;text-decoration:underline}.fb-crumb-current{color:#444;font-weight:500;padding:2px 4px}.fb-crumb-sep{color:#bbb;margin:0 1px}.fb-back-btn{background:none;border:none;border-bottom:1px solid #eee;color:#5a7a3a;cursor:pointer;font-size:.82rem;padding:6px 18px;text-align:left;width:100%}.fb-back-btn:hover{background:#f0f5e8}.fb-body{flex:1 1;overflow-y:auto;padding:6px 0}.fb-row{align-items:center;background:none;border:none;color:#1e1e1e;cursor:pointer;display:flex;font-family:inherit;font-size:.88rem;gap:10px;padding:8px 18px;text-align:left;transition:background .1s;width:100%}.fb-row:hover{background:#f0f5e8}.fb-dir{color:#2a4a6a;font-weight:500}.fb-icon{flex-shrink:0;font-size:1rem}.fb-name{flex:1 1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fb-size{color:#999;flex-shrink:0;font-size:.75rem}.fb-status{color:#888;font-size:.87rem;padding:24px 18px;text-align:center}.fb-error{color:#b44}.fb-empty{color:#aaa}.recording-step{padding:0}.recording-form{display:flex;flex-direction:column;gap:20px}.recording-form-group{margin-bottom:0}.recording-form-group label{color:#333;display:block;font-size:.95em;font-weight:500;margin-bottom:8px}.recording-form-input{background:#f9f9f9;border:1px solid #ddd;border-radius:4px;font-family:inherit;font-size:.95em;padding:10px 12px;transition:border-color .3s ease;width:100%}.recording-form-input:focus{background:#fff;border-color:#8fa06e;outline:none}.recording-file-input{background:#f9f9f9;border:1px solid #ddd;border-radius:4px;font-family:inherit;font-size:.95em;padding:12px;transition:border-color .3s ease,background .3s ease}.recording-file-input:focus{background:#fff;border-color:#8fa06e;outline:none}.file-input-hidden{display:none}.file-upload-btn{align-items:center;background:#f8f9ff;border:2px solid #8fa06e;border-radius:6px;color:#8fa06e;cursor:pointer;display:flex;font-size:1em;font-weight:600;gap:8px;justify-content:center;padding:14px 16px;transition:all .3s ease;width:100%}.file-upload-btn:hover{background:#eef2ff;border-color:#5568d3;box-shadow:0 4px 12px #667eea33;transform:translateY(-2px)}.file-upload-btn:active{box-shadow:0 2px 6px #667eea1a;transform:translateY(0)}.file-info{background:#e8f5e9;color:#2e7d32;font-size:.9em;margin-top:6px;padding:8px}.channels-section{margin-bottom:20px}.channels-label{color:#333;display:block;font-size:.95em;font-weight:500;margin-bottom:10px}.channels-grid{grid-gap:8px;background:#f9f9f9;border-radius:4px;display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(50px,1fr));margin-bottom:10px;padding:12px}.checkbox-label{align-items:center;cursor:pointer;display:flex;gap:6px;-webkit-user-select:none;user-select:none}.checkbox-input{accent-color:#8fa06e;cursor:pointer;height:18px;width:18px}.checkbox-text{color:#333;font-size:.9em}.selected-text{background:#e3f2fd;border-left:3px solid #8fa06e;border-radius:4px;color:#1565c0;font-size:.9em;margin-top:8px;padding:8px 12px}.step-container{animation:fadeIn .3s ease}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.step-container h2{color:#333;font-size:1.8em;margin:0 0 10px}.step-description{color:#666;font-size:1em;line-height:1.5;margin:0 0 30px}.form-section{border-bottom:1px solid #eee;margin-bottom:30px;padding-bottom:30px}.form-section:last-child{border-bottom:none}.form-section h3{color:#333;font-size:1.2em;margin:0 0 15px}.section-description{color:#666;font-size:.95em;margin:0 0 15px}.form-group{margin-bottom:20px}.form-group label{color:#333;margin-bottom:8px}.file-input,.form-input{border:2px solid #e0e0e0;border-radius:6px;font-family:inherit;font-size:1em;padding:10px 12px;transition:border-color .3s ease;width:100%}.file-input:focus,.form-input:focus{border-color:#8fa06e;outline:none}.file-input{cursor:pointer}.file-info{background:#f0f7ff;border-left:4px solid #8fa06e;border-radius:4px;color:#333;font-size:.95em;margin-top:8px;padding:10px 12px}.form-row{grid-gap:20px;display:grid;gap:20px;grid-template-columns:1fr 1fr}.bad-channels-grid{grid-gap:8px;display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(50px,1fr));margin-bottom:15px}.channel-btn{background:#fff;border:2px solid #e0e0e0;border-radius:6px;cursor:pointer;font-size:.9em;font-weight:500;padding:8px;transition:all .2s ease}.channel-btn:hover{background:#f0f7ff;border-color:#8fa06e}.channel-btn.selected{background:#ff6b6b;border-color:#ff6b6b;color:#fff}.bad-channels-list{background:#fff3cd;border-left:4px solid #ffc107;border-radius:4px;color:#333;padding:12px}.pipelines-table-wrapper{box-shadow:0 2px 8px #0000001a;margin:20px 0}.pipelines-table thead{background:#f5f5f5;border-bottom:2px solid #ddd}.pipelines-table th{color:#333;font-size:.9em;font-weight:600;padding:12px 15px}.pipelines-table tbody tr{border-bottom:1px solid #eee;transition:all .2s ease}.pipelines-table tbody tr:hover{background:#f9f9f9}.pipelines-table tbody tr.selected{background:#f0f7ff;border-left:4px solid #8fa06e}.pipelines-table td{font-size:.95em;padding:12px 15px}.checkbox-column{text-align:center;width:60px}.pipeline-checkbox{height:18px;width:18px}.pipeline-id{font-weight:600;width:80px}.pipeline-desc{flex:1 1;max-width:400px;word-break:break-word}.steps-column{font-weight:500;text-align:center;width:70px}.created-date{color:#999;font-size:.9em;width:100px}.selection-summary{background:#d4edda;border-left:4px solid #28a745;border-radius:4px;color:#155724;font-size:.95em;margin-top:20px;padding:12px 15px}.environment-card-single{background:#fff;border:2px solid #e0e0e0;border-radius:8px;margin-bottom:30px;padding:20px}.environment-checkbox-group{align-items:flex-start;display:flex;gap:15px}.environment-checkbox{accent-color:#8fa06e;cursor:pointer;height:20px;margin-top:5px;width:20px}.environment-label{cursor:pointer;flex:1 1}.env-title{color:#333;font-size:1.05em;font-weight:600;margin-bottom:5px}.env-description{color:#666;font-size:.95em;line-height:1.5}.env-details{background:#f9f9f9;border-radius:6px;padding:15px}.detail-item{color:#333;margin-bottom:8px}.detail-item:last-child{margin-bottom:0}.detail-item strong{color:#333;margin-right:10px}.review-sections{margin-bottom:30px}.review-section{background:#f9f9f9;border-left:4px solid #8fa06e;margin-bottom:25px;padding:20px}.review-section h3{color:#333;margin:0 0 15px}.review-items{grid-gap:12px;gap:12px;grid-template-columns:1fr}.review-item{grid-gap:15px;border-bottom:1px solid #e0e0e0;gap:15px;grid-template-columns:200px 1fr;padding:10px 0}.review-item .label{color:#333;font-weight:600}.review-item .value{color:#666}.info-box{background:#e7f3ff;border-left:4px solid #8fa06e;color:#333;margin-bottom:20px;padding:15px}.info-box ul{margin:10px 0 0;padding-left:20px}.info-box li{margin-bottom:8px}.empty-state{background:#f9f9f9;color:#666}.validation-note{background:#d4edda;border-left:4px solid #28a745;border-radius:4px;color:#155724;font-size:.95em;margin-top:20px;padding:12px 15px}.error-message{background:#f8d7da;border-left:4px solid #f5222d;border-radius:6px;color:#721c24;font-weight:500;margin-bottom:20px;padding:15px}.submit-button{background:linear-gradient(135deg,#8fa06e,#7d8e5e);font-size:1.1em;font-weight:600;padding:15px;transition:all .3s ease}.submit-button:hover:not(:disabled){box-shadow:0 8px 24px #667eea66;transform:scale(1.02)}.submit-button:disabled{opacity:.7}.fb-field{align-items:center;background:#f9f9f9;border:1px solid #ddd;border-radius:4px;display:flex;gap:8px;padding:6px 10px}.fb-field-value{color:#1e1e1e;flex:1 1;font-size:.9rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fb-field-placeholder{color:#aaa;font-style:italic}.fb-field-path{color:#888;font-size:.75rem;margin-top:4px;word-break:break-all}.fb-browse-btn{background:#8fa06e;border:none;border-radius:4px;color:#fff;cursor:pointer;flex-shrink:0;font-family:inherit;font-size:.82rem;padding:5px 12px}.fb-browse-btn:hover{background:#7a8c5e}.fb-clear-btn{background:none;border:none;border-radius:3px;color:#999;cursor:pointer;flex-shrink:0;font-size:.85rem;padding:2px 4px}.fb-clear-btn:hover{background:#f0e0e0;color:#b44}.files-loading{color:#888;font-size:.85rem;padding:8px 0}.files-empty{color:#aaa;font-size:.8rem;padding:4px 0}.files-error-banner{background:#fff3cd;border:1px solid #ffc107;border-radius:4px;color:#856404;font-size:.85rem;margin-bottom:16px;padding:10px 14px}@media (max-width:768px){.environments-grid,.form-row,.review-item{grid-template-columns:1fr}.bad-channels-grid{grid-template-columns:repeat(auto-fill,minmax(40px,1fr))}}.wizard-container{background:#f0efe8;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;min-height:100vh;padding:48px 56px}.wizard-header{align-items:center;display:flex;gap:16px;margin-bottom:36px}.wizard-header h1{color:#1e1e1e;font-size:1.9em;font-weight:400;letter-spacing:-.4px;margin:0}.back-btn{background:#0000;border:1px solid #d4d3cc;border-radius:8px;color:#666;cursor:pointer;font-size:.85em;font-weight:500;padding:7px 14px;transition:border-color .15s,color .15s}.back-btn:hover{border-color:#999;color:#333}.wizard-progress{align-items:center;display:flex;gap:0;justify-content:center;margin-bottom:32px;margin-left:auto;margin-right:auto;max-width:500px}.progress-step{align-items:center;display:flex;flex:1 1;flex-direction:column;gap:6px;opacity:.35;position:relative;transition:opacity .2s}.progress-step+.progress-step:before{background:#d4d3cc;content:"";height:1px;left:-50%;position:absolute;top:14px;width:100%;z-index:0}.progress-step.active{opacity:1}.step-number{align-items:center;background:#e8e7e0;border:1px solid #d4d3cc;border-radius:50%;color:#666;display:flex;font-size:.82em;font-weight:600;height:28px;justify-content:center;position:relative;width:28px;z-index:1}.progress-step.active .step-number{background:#8fa06e;border-color:#8fa06e;color:#fff}.step-label{color:#999;font-size:.78em;font-weight:500;text-align:center}.progress-step.active .step-label{color:#1e1e1e}.wizard-content{background:#fff;border:1px solid #e8e7e0;border-radius:14px;margin:0 auto 24px;max-width:780px;padding:36px}.wizard-navigation{display:flex;gap:12px;justify-content:space-between;margin:0 auto;max-width:780px}.nav-button{border-radius:8px;cursor:pointer;font-size:.9em;font-weight:500;min-width:120px;padding:10px 28px;transition:all .15s}.nav-button.primary{background:#8fa06e;border:none;color:#fff}.nav-button.primary:hover:not(:disabled){background:#7d8e5e}.nav-button.secondary{background:#0000;border:1px solid #d4d3cc;color:#666}.nav-button.secondary:hover:not(:disabled){border-color:#999;color:#333}.nav-button:disabled{cursor:not-allowed;opacity:.4}@media (max-width:768px){.wizard-container{padding:32px 20px}.wizard-header h1{font-size:1.5em}.wizard-progress{gap:0}.wizard-content{padding:20px}}.pipeline-form-container{background:#f0efe8;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;min-height:100vh;padding:48px 56px}.pipeline-form-header{margin-bottom:32px}.pipeline-form-header .back-btn{background:#0000;border:1px solid #d4d3cc;border-radius:8px;color:#666;cursor:pointer;display:inline-block;font-size:.85em;font-weight:500;margin-bottom:20px;padding:7px 14px;transition:border-color .15s,color .15s}.pipeline-form-header .back-btn:hover{border-color:#999;color:#333}.pipeline-form-header h1{color:#1e1e1e;font-size:1.9em;font-weight:400;letter-spacing:-.4px;margin:0 0 6px}.pipeline-form-header .subtitle{color:#999;font-size:.88em;margin:0}.pipeline-form{background:#fff;border:1px solid #e8e7e0;border-radius:14px;max-width:860px;padding:36px}.form-section{border-bottom:1px solid #f0efe8;margin-bottom:28px;padding-bottom:28px}.form-section:last-of-type{border-bottom:none;margin-bottom:0;padding-bottom:0}.form-section h3{color:#aaa;font-size:.78em;font-weight:500;letter-spacing:.8px;margin:0 0 6px;text-transform:uppercase}.section-description{color:#888;font-size:.87em;line-height:1.5;margin:0 0 18px}.json-upload-section{background:#fafaf8;border:1px solid #eeede6;border-radius:10px;padding:24px}.file-input{display:none}.file-upload-box{position:relative}.file-label{align-items:center;background:#fff;border:1.5px dashed #c8c7be;border-radius:10px;cursor:pointer;display:flex;gap:18px;justify-content:center;padding:36px 24px;transition:border-color .15s,background .15s}.file-label:hover{background:#f7f8f3;border-color:#8fa06e}.file-icon{font-size:2.2em;opacity:.6}.file-text{text-align:left}.file-text strong{color:#333;display:block;font-size:.95em;font-weight:500;margin-bottom:4px}.file-text small{color:#aaa;font-size:.82em}.validation-error{background:#fef2f0;border:1px solid #f5c6c0;border-radius:8px;color:#c0392b}.validation-error,.validation-success{font-size:.85em;margin-top:12px;padding:10px 14px}.validation-success{background:#f0f8f0;border:1px solid #b8ddb8;border-radius:8px;color:#2d6a2d}.error-message{background:#fef2f0;border-left:3px solid #e87060;color:#c0392b}.error-message,.success-message{border-radius:8px;font-size:.88em;margin-bottom:18px;padding:12px 16px}.success-message{background:#f0f8f0;border-left:3px solid #6aaa6a;color:#2d6a2d}.form-group{margin-bottom:18px}.form-group label{color:#555;display:block;font-size:.85em;font-weight:500;margin-bottom:6px}.form-input,.form-textarea{background:#fafaf8;border:1px solid #e0dfd8;border-radius:8px;box-sizing:border-box;color:#1e1e1e;font-family:inherit;font-size:.9em;padding:10px 12px;transition:border-color .15s;width:100%}.form-input:focus,.form-textarea:focus{background:#fff;border-color:#8fa06e;outline:none}.form-textarea{resize:vertical}.form-actions{display:flex;gap:12px}.submit-btn{background:#8fa06e;border:none;border-radius:8px;color:#fff;cursor:pointer;flex:1 1;font-size:.9em;font-weight:500;padding:11px 24px;transition:background .15s}.submit-btn:hover:not(:disabled){background:#7d8e5e}.submit-btn:disabled{background:#c0c9aa;cursor:not-allowed}.steps-container{grid-gap:16px;display:grid;gap:16px;margin-bottom:18px}.step-card{background:#fafaf8;border:1px solid #e8e7e0;border-radius:10px;padding:18px}.step-card:hover{border-color:#c0bfb8}.step-header{align-items:center;border-bottom:1px solid #f0efe8;display:flex;justify-content:space-between;margin-bottom:14px;padding-bottom:12px}.step-header h4{color:#1e1e1e;font-size:.9em;font-weight:500;margin:0}.remove-step-btn{align-items:center;background:#0000;border:1px solid #e0dfd8;border-radius:50%;color:#ccc;cursor:pointer;display:flex;font-size:1em;height:28px;justify-content:center;transition:all .15s;width:28px}.remove-step-btn:hover{background:#fef2f0;border-color:#e87060;color:#c0392b}.step-grid{grid-gap:12px;display:grid;gap:12px;grid-template-columns:1fr 1fr;margin-bottom:12px}.add-step-btn{background:#0000;border:1.5px dashed #c8c7be;border-radius:8px;color:#999;cursor:pointer;display:block;font-size:.88em;font-weight:500;margin-bottom:24px;padding:10px 18px;transition:all .15s;width:100%}.add-step-btn:hover{background:#f7f8f3;border-color:#8fa06e;color:#8fa06e}.pipelines-table-wrapper{border:1px solid #e8e7e0;border-radius:8px;margin:16px 0;overflow-x:auto}.pipelines-table{background:#fff;border-collapse:collapse;width:100%}.pipelines-table thead{background:#fafaf8;border-bottom:1px solid #e8e7e0}.pipelines-table th{color:#aaa;font-size:.78em;font-weight:500;letter-spacing:.5px;padding:10px 14px;text-align:left;text-transform:uppercase}.pipelines-table tbody tr{border-bottom:1px solid #f0efe8;cursor:pointer;transition:background .1s}.pipelines-table tbody tr:hover{background:#fafaf8}.pipelines-table tbody tr.selected{background:#f7f8f3;border-left:3px solid #8fa06e}.pipelines-table td{color:#333;font-size:.88em;padding:10px 14px}.pipeline-checkbox{accent-color:#8fa06e;cursor:pointer;height:16px;width:16px}.pipeline-id{color:#8fa06e;font-weight:500}.selection-summary{background:#f7f8f3;border-left:3px solid #8fa06e;border-radius:6px;color:#4a5c35;font-size:.87em;margin-top:14px;padding:10px 14px}.review-sections{margin-bottom:24px}.review-section{background:#fafaf8;border-left:3px solid #c8c7be;border-radius:8px;margin-bottom:18px;padding:18px}.review-section h3{color:#aaa;font-size:.78em;font-weight:500;letter-spacing:.6px;margin:0 0 12px;text-transform:uppercase}.review-items{grid-gap:8px;display:grid;gap:8px}.review-item{grid-gap:12px;border-bottom:1px solid #f0efe8;display:grid;font-size:.88em;gap:12px;grid-template-columns:180px 1fr;padding:8px 0}.review-item:last-child{border-bottom:none}.review-item .label{color:#999;font-weight:500}.review-item .value{color:#333;word-break:break-word}.info-box{background:#f7f8f3;border-left:3px solid #8fa06e;border-radius:6px;color:#444;font-size:.88em;line-height:1.6;margin-bottom:18px;padding:14px}.info-box ul{margin:8px 0 0;padding-left:18px}.info-box li{color:#666;margin-bottom:6px}.validation-note{background:#f7f8f3;border-left:3px solid #8fa06e;border-radius:6px;color:#4a5c35;font-size:.87em;margin-top:16px;padding:10px 14px}.empty-state{background:#fafaf8;border:1px solid #e8e7e0;border-radius:8px;color:#aaa;font-size:.9em;padding:40px 20px;text-align:center}.submit-button{background:#8fa06e;border:none;border-radius:8px;color:#fff;cursor:pointer;font-size:.9em;font-weight:500;padding:11px;transition:background .15s;width:100%}.submit-button:hover:not(:disabled){background:#7d8e5e}.submit-button:disabled{background:#c0c9aa;cursor:not-allowed}.help-text{color:#bbb;display:block;font-size:.8em;margin-top:5px}.steps-preview{list-style:none;margin:0;padding:0}.steps-preview li{align-items:center;background:#fafaf8;border-left:3px solid #c8c7be;border-radius:6px;display:flex;font-size:.88em;justify-content:space-between;margin-bottom:6px;padding:10px 12px}.step-function{color:#8fa06e;font-weight:500}.step-deps{background:#fff;border:1px solid #e8e7e0;border-radius:4px;color:#aaa;font-size:.82em;padding:3px 8px}@media (max-width:768px){.pipeline-form-container{padding:32px 20px}.pipeline-form{padding:20px}.pipeline-form-header h1{font-size:1.5em}.review-item,.step-grid{grid-template-columns:1fr}}.mj-container{background:#f0efe8;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;min-height:100vh;padding:48px 56px}.mj-header{align-items:center;display:flex;gap:16px;margin-bottom:36px}.mj-title{color:#1e1e1e;flex-grow:1;font-size:1.9em;font-weight:400;letter-spacing:-.4px;margin:0}.mj-btn-ghost{background:#0000;border:1px solid #d4d3cc;border-radius:8px;color:#666;cursor:pointer;font-size:.85em;font-weight:500;padding:7px 14px;transition:border-color .15s,color .15s}.mj-btn-ghost:hover{border-color:#999;color:#333}.mj-stats{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:28px}.mj-stat{background:#fff;border:1px solid #e8e7e0;border-radius:10px;min-width:80px;padding:14px 22px;text-align:center}.mj-stat-value{font-size:1.6em;font-weight:300;line-height:1;margin-bottom:4px}.mj-stat-label{color:#aaa;font-size:.72em;letter-spacing:.6px;text-transform:uppercase}.mj-filters{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:24px}.mj-filter{background:#0000;border:1px solid #d4d3cc;border-radius:20px;color:#666;cursor:pointer;font-size:.83em;font-weight:500;padding:6px 16px;transition:all .15s}.mj-filter:hover{border-color:#999;color:#333}.mj-filter.active{background:#1e1e1e;border-color:#1e1e1e;color:#fff}.mj-table{background:#fff;border:1px solid #e8e7e0;border-radius:12px;max-width:1100px;overflow:hidden}.mj-table-head{background:#fafaf8;border-bottom:1px solid #e8e7e0;color:#aaa;font-size:.74em;font-weight:600;letter-spacing:.6px;padding:11px 20px;text-transform:uppercase}.mj-table-head,.mj-table-row{grid-gap:16px;display:grid;gap:16px;grid-template-columns:140px 110px 1fr 160px 180px}.mj-table-row{align-items:center;border-bottom:1px solid #f0efe8;cursor:pointer;font-size:.88em;padding:14px 20px;transition:background .1s}.mj-table-row:last-child{border-bottom:none}.mj-table-row:hover{background:#fafaf8}.mj-job-id{color:#333;font-family:SF Mono,Fira Code,monospace;font-size:.92em;font-weight:500}.mj-date{color:#777;font-size:.88em}.mj-status-pill{border-radius:20px;color:#fff;display:inline-block;font-size:.72em;font-weight:700;letter-spacing:.4px;padding:3px 9px;white-space:nowrap}.mj-progress-cell{align-items:center;display:flex;gap:8px}.mj-progress-track{background:#f0efe8;border-radius:3px;flex:1 1;height:5px;overflow:hidden}.mj-progress-fill{border-radius:3px;height:100%;transition:width .3s ease}.mj-progress-pct{color:#aaa;flex-shrink:0;font-size:.8em;white-space:nowrap}.mj-row-actions{align-items:center;display:flex;gap:6px}.mj-row-btn{border:1px solid #0000;border-radius:7px;cursor:pointer;font-size:.8em;font-weight:500;padding:5px 10px;transition:all .15s;white-space:nowrap}.mj-row-btn:disabled{cursor:not-allowed;opacity:.3}.mj-row-btn.cancel{background:#fff0f0;border-color:#f5c6c6;color:#c0392b}.mj-row-btn.cancel:hover:not(:disabled){background:#dc3545;border-color:#dc3545;color:#fff}.mj-row-btn.resume{background:#f0faf3;border-color:#b8dfc5;color:#1a7a3a}.mj-row-btn.resume:hover:not(:disabled){background:#28a745;border-color:#28a745;color:#fff}.mj-row-btn.details{background:#0000;border-color:#d4d3cc;color:#555}.mj-row-btn.details:hover{background:#1e1e1e;border-color:#1e1e1e;color:#fff}.mj-detail-card{background:#fff;border:1px solid #e8e7e0;border-radius:14px;max-width:700px;padding:36px}.mj-detail-top{align-items:flex-start;border-bottom:1px solid #f0efe8;display:flex;justify-content:space-between;margin-bottom:28px;padding-bottom:24px}.mj-detail-id{color:#333;font-family:SF Mono,Fira Code,monospace;font-size:.9em;font-weight:500;margin-bottom:6px;word-break:break-all}.mj-detail-date{color:#aaa;font-size:.83em}.mj-detail-progress{border-bottom:1px solid #f0efe8;margin-bottom:24px;padding-bottom:24px}.mj-progress-meta{color:#aaa;display:flex;font-size:.83em;justify-content:space-between;margin-bottom:8px}.mj-detail-actions{border-bottom:1px solid #f0efe8;display:flex;gap:10px;margin-bottom:28px;padding-bottom:28px}.mj-action-cancel,.mj-action-resume{border:1px solid #0000;border-radius:9px;cursor:pointer;font-size:.85em;font-weight:600;padding:9px 20px;transition:all .15s}.mj-action-cancel:disabled,.mj-action-resume:disabled{cursor:not-allowed;opacity:.3}.mj-action-cancel{background:#fff0f0;border-color:#f5c6c6;color:#c0392b}.mj-action-cancel:hover:not(:disabled){background:#dc3545;border-color:#dc3545;color:#fff}.mj-action-resume{background:#f0faf3;border-color:#b8dfc5;color:#1a7a3a}.mj-action-resume:hover:not(:disabled){background:#28a745;border-color:#28a745;color:#fff}.mj-steps-label{color:#aaa;font-size:.72em;font-weight:600;letter-spacing:.8px;margin-bottom:16px;text-transform:uppercase}.mj-steps-track{display:flex;flex-direction:column}.mj-step-row{align-items:stretch;display:flex;gap:16px}.mj-step-left{align-items:center;display:flex;flex-direction:column;flex-shrink:0;width:20px}.mj-step-dot{border:2px solid #ccc;border-radius:50%;flex-shrink:0;height:14px;margin-top:3px;transition:background .2s,border-color .2s;width:14px}.mj-step-line{background:#e8e7e0;flex:1 1;margin:4px 0;min-height:20px;width:2px}.mj-step-body{align-items:center;border-bottom:1px solid #f5f4ef;display:flex;flex:1 1;justify-content:space-between;padding:6px 0 20px}.mj-step-row:last-child .mj-step-body{border-bottom:none;padding-bottom:0}.mj-step-name{color:#1e1e1e;font-size:.9em;font-weight:500;text-transform:capitalize}.mj-step-status{font-size:.8em;font-weight:500;letter-spacing:.3px;text-transform:uppercase}.mj-empty{background:#fff;border:1px solid #e8e7e0;border-radius:12px;color:#aaa;font-size:.95em;max-width:1100px;padding:64px 20px;text-align:center}.mj-error{background:#fef2f0;border-left:3px solid #e87060;border-radius:8px;color:#c0392b;font-size:.88em;margin-bottom:16px;max-width:1100px;padding:12px 16px}@media (max-width:768px){.mj-container{padding:24px 16px}.mj-table-head,.mj-table-row{grid-template-columns:1fr 90px}.mj-table-head span:nth-child(3),.mj-table-head span:nth-child(4),.mj-table-row span:nth-child(3),.mj-table-row span:nth-child(4){display:none}.mj-detail-card{padding:20px}.mj-detail-top{flex-direction:column;gap:12px}}.dashboard-container{background:#f0efe8;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;min-height:100vh;padding:48px 56px}.dashboard-greeting{margin-bottom:48px}.dashboard-greeting h1{color:#1e1e1e;font-size:2.6em;font-weight:400;letter-spacing:-.5px;margin:0 0 6px}.dashboard-greeting p{color:#888;font-size:.95em;font-weight:400;margin:0}.section-title{color:#1e1e1e;font-size:1.25em;font-weight:500;letter-spacing:-.2px;margin:0 0 24px}.dashboard-actions{grid-gap:20px;display:grid;gap:20px;grid-template-columns:repeat(3,1fr);margin-bottom:56px}.action-card{border-radius:14px;box-sizing:border-box;cursor:pointer;display:flex;flex-direction:column;gap:12px;min-height:220px;padding:32px 28px 28px;position:relative;transition:transform .15s ease,opacity .15s ease}.action-card:hover{opacity:.92;transform:translateY(-3px)}.create-job{background:#8fa06e}.add-pipeline{background:#b57d5a}.manage-jobs{background:#c5ca85}.card-icon-label{align-items:center;color:#00000073;display:flex;font-size:.8em;font-weight:600;gap:6px;letter-spacing:1px;text-transform:uppercase}.card-icon-label svg{height:14px;width:14px}.action-card h3{color:#1a1a1a;font-size:1.25em;font-weight:500;line-height:1.3;margin:4px 0 0}.action-card p{color:#0000008c;flex-grow:1;font-size:.88em;line-height:1.6;margin:0}.card-tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.card-tag{background:#0000001a;border-radius:20px;color:#0009;font-size:.75em;font-weight:500;padding:4px 10px}.workspace-section{margin-top:4px}.workspace-grid{grid-gap:20px;display:grid;gap:20px;grid-template-columns:repeat(3,1fr)}.workspace-card{background:#fff;border:1px solid #e8e7e0;border-radius:14px;box-sizing:border-box;display:flex;flex-direction:column;gap:10px;min-height:140px;padding:28px}.workspace-card h4{align-items:center;color:#888;display:flex;font-size:.9em;font-weight:500;gap:6px;letter-spacing:.8px;margin:0;text-transform:uppercase}.workspace-stat{color:#1e1e1e;font-size:2.2em;font-weight:300;line-height:1;margin:0}.workspace-stat-label{color:#aaa;font-size:.85em;margin:0}@media (max-width:900px){.dashboard-container{padding:32px 24px}.dashboard-actions,.workspace-grid{grid-template-columns:1fr}} -/*# sourceMappingURL=main.c20849f5.css.map*/ \ No newline at end of file diff --git a/my-app/build/static/css/main.c20849f5.css.map b/my-app/build/static/css/main.c20849f5.css.map deleted file mode 100644 index aab93bf..0000000 --- a/my-app/build/static/css/main.c20849f5.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"static/css/main.c20849f5.css","mappings":"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","sources":["index.css","styles/FileBrowser.css","styles/WizardSteps.css","styles/Wizard.css","styles/AddNewPipeline.css","styles/ManageJobs.css","styles/Dashboard.css"],"sourcesContent":["body {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n background: #f0efe8;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\n monospace;\n}\n","/* ---- Overlay ---- */\n.fb-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.45);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n/* ---- Modal shell ---- */\n.fb-modal {\n background: #fff;\n border-radius: 8px;\n width: 640px;\n max-width: 95vw;\n max-height: 80vh;\n display: flex;\n flex-direction: column;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.22);\n overflow: hidden;\n}\n\n/* ---- Header ---- */\n.fb-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid #e5e5e5;\n background: #f5f5f0;\n}\n\n.fb-title {\n font-weight: 600;\n font-size: 0.95rem;\n color: #1e1e1e;\n}\n\n.fb-close {\n background: none;\n border: none;\n font-size: 1rem;\n cursor: pointer;\n color: #666;\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.fb-close:hover {\n background: #e0e0e0;\n color: #1e1e1e;\n}\n\n/* ---- Breadcrumb ---- */\n.fb-breadcrumb {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 2px;\n padding: 8px 18px;\n background: #fafaf7;\n border-bottom: 1px solid #eee;\n font-size: 0.8rem;\n}\n\n.fb-crumb-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: #5a7a3a;\n font-size: 0.8rem;\n padding: 2px 4px;\n border-radius: 3px;\n}\n\n.fb-crumb-btn:hover {\n background: #e8f0dc;\n text-decoration: underline;\n}\n\n.fb-crumb-current {\n color: #444;\n font-weight: 500;\n padding: 2px 4px;\n}\n\n.fb-crumb-sep {\n color: #bbb;\n margin: 0 1px;\n}\n\n/* ---- Back button ---- */\n.fb-back-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: #5a7a3a;\n font-size: 0.82rem;\n padding: 6px 18px;\n text-align: left;\n border-bottom: 1px solid #eee;\n width: 100%;\n}\n\n.fb-back-btn:hover {\n background: #f0f5e8;\n}\n\n/* ---- Body (scrollable list) ---- */\n.fb-body {\n flex: 1;\n overflow-y: auto;\n padding: 6px 0;\n}\n\n/* ---- Rows ---- */\n.fb-row {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n background: none;\n border: none;\n padding: 8px 18px;\n cursor: pointer;\n text-align: left;\n font-size: 0.88rem;\n font-family: inherit;\n color: #1e1e1e;\n transition: background 0.1s;\n}\n\n.fb-row:hover {\n background: #f0f5e8;\n}\n\n.fb-dir {\n color: #2a4a6a;\n font-weight: 500;\n}\n\n.fb-icon {\n font-size: 1rem;\n flex-shrink: 0;\n}\n\n.fb-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.fb-size {\n font-size: 0.75rem;\n color: #999;\n flex-shrink: 0;\n}\n\n/* ---- Status messages ---- */\n.fb-status {\n padding: 24px 18px;\n text-align: center;\n color: #888;\n font-size: 0.87rem;\n}\n\n.fb-error {\n color: #b44;\n}\n\n.fb-empty {\n color: #aaa;\n}\n",".recording-step {\n padding: 0;\n}\n\n.recording-form {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.recording-form-group {\n margin-bottom: 0;\n}\n\n.recording-form-group label {\n display: block;\n margin-bottom: 8px;\n color: #333;\n font-weight: 500;\n font-size: 0.95em;\n}\n\n.recording-form-input {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 0.95em;\n font-family: inherit;\n background: #f9f9f9;\n transition: border-color 0.3s ease;\n}\n\n.recording-form-input:focus {\n outline: none;\n border-color: #8fa06e;\n background: white;\n}\n\n.recording-file-input {\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 0.95em;\n font-family: inherit;\n background: #f9f9f9;\n transition: border-color 0.3s ease, background 0.3s ease;\n}\n\n.recording-file-input:focus {\n outline: none;\n border-color: #8fa06e;\n background: white;\n}\n\n.file-input-hidden {\n display: none;\n}\n\n.file-upload-btn {\n width: 100%;\n padding: 14px 16px;\n border: 2px solid #8fa06e;\n border-radius: 6px;\n background: #f8f9ff;\n color: #8fa06e;\n font-size: 1em;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.file-upload-btn:hover {\n background: #eef2ff;\n border-color: #5568d3;\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2);\n}\n\n.file-upload-btn:active {\n transform: translateY(0);\n box-shadow: 0 2px 6px rgba(102, 126, 234, 0.1);\n}\n\n.file-info {\n margin-top: 6px;\n padding: 8px;\n background: #e8f5e9;\n border-radius: 4px;\n color: #2e7d32;\n font-size: 0.9em;\n}\n\n.channels-section {\n margin-bottom: 20px;\n}\n\n.channels-label {\n display: block;\n margin-bottom: 10px;\n color: #333;\n font-weight: 500;\n font-size: 0.95em;\n}\n\n.channels-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(50px, 1fr));\n gap: 8px;\n margin-bottom: 10px;\n padding: 12px;\n background: #f9f9f9;\n border-radius: 4px;\n}\n\n.checkbox-label {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n user-select: none;\n}\n\n.checkbox-input {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: #8fa06e;\n}\n\n.checkbox-text {\n font-size: 0.9em;\n color: #333;\n}\n\n.selected-text {\n margin-top: 8px;\n padding: 8px 12px;\n background: #e3f2fd;\n border-left: 3px solid #8fa06e;\n border-radius: 4px;\n color: #1565c0;\n font-size: 0.9em;\n}\n\n/* Keep existing styles for other sections */\n.step-container {\n animation: fadeIn 0.3s ease;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n\n to {\n opacity: 1;\n }\n}\n\n.step-container h2 {\n margin: 0 0 10px 0;\n color: #333;\n font-size: 1.8em;\n}\n\n.step-description {\n margin: 0 0 30px 0;\n color: #666;\n font-size: 1em;\n line-height: 1.5;\n}\n\n.form-section {\n margin-bottom: 30px;\n padding-bottom: 30px;\n border-bottom: 1px solid #eee;\n}\n\n.form-section:last-child {\n border-bottom: none;\n}\n\n.form-section h3 {\n margin: 0 0 15px 0;\n color: #333;\n font-size: 1.2em;\n}\n\n.section-description {\n margin: 0 0 15px 0;\n color: #666;\n font-size: 0.95em;\n}\n\n.form-group {\n margin-bottom: 20px;\n}\n\n.form-group label {\n display: block;\n margin-bottom: 8px;\n color: #333;\n font-weight: 500;\n}\n\n.form-input,\n.file-input {\n width: 100%;\n padding: 10px 12px;\n border: 2px solid #e0e0e0;\n border-radius: 6px;\n font-size: 1em;\n transition: border-color 0.3s ease;\n font-family: inherit;\n}\n\n.form-input:focus,\n.file-input:focus {\n outline: none;\n border-color: #8fa06e;\n}\n\n.file-input {\n cursor: pointer;\n}\n\n.file-info {\n margin-top: 8px;\n padding: 10px 12px;\n background: #f0f7ff;\n border-left: 4px solid #8fa06e;\n border-radius: 4px;\n color: #333;\n font-size: 0.95em;\n}\n\n.form-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 20px;\n}\n\n.bad-channels-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(50px, 1fr));\n gap: 8px;\n margin-bottom: 15px;\n}\n\n.channel-btn {\n padding: 8px;\n border: 2px solid #e0e0e0;\n border-radius: 6px;\n background: white;\n cursor: pointer;\n font-weight: 500;\n transition: all 0.2s ease;\n font-size: 0.9em;\n}\n\n.channel-btn:hover {\n border-color: #8fa06e;\n background: #f0f7ff;\n}\n\n.channel-btn.selected {\n background: #ff6b6b;\n color: white;\n border-color: #ff6b6b;\n}\n\n.bad-channels-list {\n padding: 12px;\n background: #fff3cd;\n border-left: 4px solid #ffc107;\n border-radius: 4px;\n color: #333;\n}\n\n.pipelines-table-wrapper {\n margin: 20px 0;\n overflow-x: auto;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.pipelines-table {\n width: 100%;\n border-collapse: collapse;\n background: white;\n}\n\n.pipelines-table thead {\n background: #f5f5f5;\n border-bottom: 2px solid #ddd;\n}\n\n.pipelines-table th {\n padding: 12px 15px;\n text-align: left;\n font-weight: 600;\n color: #333;\n font-size: 0.9em;\n}\n\n.pipelines-table tbody tr {\n border-bottom: 1px solid #eee;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.pipelines-table tbody tr:hover {\n background: #f9f9f9;\n}\n\n.pipelines-table tbody tr.selected {\n background: #f0f7ff;\n border-left: 4px solid #8fa06e;\n}\n\n.pipelines-table td {\n padding: 12px 15px;\n color: #333;\n font-size: 0.95em;\n}\n\n.checkbox-column {\n width: 60px;\n text-align: center;\n}\n\n.pipeline-checkbox {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: #8fa06e;\n}\n\n.pipeline-id {\n font-weight: 600;\n color: #8fa06e;\n width: 80px;\n}\n\n.pipeline-desc {\n flex: 1;\n max-width: 400px;\n word-break: break-word;\n}\n\n.steps-column {\n text-align: center;\n width: 70px;\n font-weight: 500;\n}\n\n.created-date {\n color: #999;\n font-size: 0.9em;\n width: 100px;\n}\n\n.selection-summary {\n margin-top: 20px;\n padding: 12px 15px;\n background: #d4edda;\n border-left: 4px solid #28a745;\n border-radius: 4px;\n color: #155724;\n font-size: 0.95em;\n}\n\n/* Single environment card */\n.environment-card-single {\n margin-bottom: 30px;\n padding: 20px;\n border: 2px solid #e0e0e0;\n border-radius: 8px;\n background: white;\n}\n\n.environment-checkbox-group {\n display: flex;\n align-items: flex-start;\n gap: 15px;\n}\n\n.environment-checkbox {\n width: 20px;\n height: 20px;\n margin-top: 5px;\n cursor: pointer;\n accent-color: #8fa06e;\n}\n\n.environment-label {\n cursor: pointer;\n flex: 1;\n}\n\n.env-title {\n font-weight: 600;\n color: #333;\n font-size: 1.05em;\n margin-bottom: 5px;\n}\n\n.env-description {\n color: #666;\n font-size: 0.95em;\n line-height: 1.5;\n}\n\n.env-details {\n background: #f9f9f9;\n padding: 15px;\n border-radius: 6px;\n}\n\n.detail-item {\n margin-bottom: 8px;\n color: #333;\n}\n\n.detail-item:last-child {\n margin-bottom: 0;\n}\n\n.detail-item strong {\n color: #333;\n margin-right: 10px;\n}\n\n.review-sections {\n margin-bottom: 30px;\n}\n\n.review-section {\n margin-bottom: 25px;\n padding: 20px;\n background: #f9f9f9;\n border-radius: 8px;\n border-left: 4px solid #8fa06e;\n}\n\n.review-section h3 {\n margin: 0 0 15px 0;\n color: #333;\n}\n\n.review-items {\n display: grid;\n grid-template-columns: 1fr;\n gap: 12px;\n}\n\n.review-item {\n display: grid;\n grid-template-columns: 200px 1fr;\n gap: 15px;\n padding: 10px 0;\n border-bottom: 1px solid #e0e0e0;\n}\n\n.review-item:last-child {\n border-bottom: none;\n}\n\n.review-item .label {\n font-weight: 600;\n color: #333;\n}\n\n.review-item .value {\n color: #666;\n word-break: break-word;\n}\n\n.info-box {\n background: #e7f3ff;\n border-left: 4px solid #8fa06e;\n padding: 15px;\n border-radius: 6px;\n margin-bottom: 20px;\n color: #333;\n line-height: 1.6;\n}\n\n.info-box ul {\n margin: 10px 0 0 0;\n padding-left: 20px;\n}\n\n.info-box li {\n margin-bottom: 8px;\n color: #666;\n}\n\n.empty-state {\n text-align: center;\n padding: 40px 20px;\n background: #f9f9f9;\n border-radius: 8px;\n color: #666;\n}\n\n.validation-note {\n padding: 12px 15px;\n background: #d4edda;\n border-left: 4px solid #28a745;\n border-radius: 4px;\n color: #155724;\n font-size: 0.95em;\n margin-top: 20px;\n}\n\n.error-message {\n background: #f8d7da;\n border-left: 4px solid #f5222d;\n padding: 15px;\n border-radius: 6px;\n color: #721c24;\n margin-bottom: 20px;\n font-weight: 500;\n}\n\n.submit-button {\n width: 100%;\n padding: 15px;\n background: linear-gradient(135deg, #8fa06e 0%, #7d8e5e 100%);\n color: white;\n border: none;\n border-radius: 8px;\n font-size: 1.1em;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n\n.submit-button:hover:not(:disabled) {\n transform: scale(1.02);\n box-shadow: 0 8px 24px rgba(102, 126, 234, 0.4);\n}\n\n.submit-button:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n\n/* ---- Server file browser field ---- */\n.fb-field {\n display: flex;\n align-items: center;\n gap: 8px;\n border: 1px solid #ddd;\n border-radius: 4px;\n padding: 6px 10px;\n background: #f9f9f9;\n}\n\n.fb-field-value {\n flex: 1;\n font-size: 0.9rem;\n color: #1e1e1e;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.fb-field-placeholder {\n color: #aaa;\n font-style: italic;\n}\n\n.fb-field-path {\n font-size: 0.75rem;\n color: #888;\n margin-top: 4px;\n word-break: break-all;\n}\n\n.fb-browse-btn {\n flex-shrink: 0;\n background: #8fa06e;\n color: #fff;\n border: none;\n border-radius: 4px;\n padding: 5px 12px;\n font-size: 0.82rem;\n cursor: pointer;\n font-family: inherit;\n}\n\n.fb-browse-btn:hover {\n background: #7a8c5e;\n}\n\n.fb-clear-btn {\n flex-shrink: 0;\n background: none;\n border: none;\n color: #999;\n cursor: pointer;\n font-size: 0.85rem;\n padding: 2px 4px;\n border-radius: 3px;\n}\n\n.fb-clear-btn:hover {\n background: #f0e0e0;\n color: #b44;\n}\n\n.files-loading {\n font-size: 0.85rem;\n color: #888;\n padding: 8px 0;\n}\n\n.files-empty {\n font-size: 0.8rem;\n color: #aaa;\n padding: 4px 0;\n}\n\n.files-error-banner {\n background: #fff3cd;\n border: 1px solid #ffc107;\n border-radius: 4px;\n padding: 10px 14px;\n margin-bottom: 16px;\n font-size: 0.85rem;\n color: #856404;\n}\n\n@media (max-width: 768px) {\n .form-row {\n grid-template-columns: 1fr;\n }\n\n .review-item {\n grid-template-columns: 1fr;\n }\n\n .environments-grid {\n grid-template-columns: 1fr;\n }\n\n .bad-channels-grid {\n grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));\n }\n}","/* ── Minimalist Wizard ── */\n.wizard-container {\n min-height: 100vh;\n background: #f0efe8;\n padding: 48px 56px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-sizing: border-box;\n}\n\n.wizard-header {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-bottom: 36px;\n}\n\n.wizard-header h1 {\n margin: 0;\n font-size: 1.9em;\n font-weight: 400;\n color: #1e1e1e;\n letter-spacing: -0.4px;\n}\n\n.back-btn {\n background: transparent;\n border: 1px solid #d4d3cc;\n color: #666;\n padding: 7px 14px;\n border-radius: 8px;\n font-size: 0.85em;\n font-weight: 500;\n cursor: pointer;\n transition: border-color 0.15s, color 0.15s;\n}\n\n.back-btn:hover {\n border-color: #999;\n color: #333;\n}\n\n/* Progress steps */\n.wizard-progress {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 0;\n margin-bottom: 32px;\n max-width: 500px;\n margin-left: auto;\n margin-right: auto;\n}\n\n.progress-step {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n opacity: 0.35;\n transition: opacity 0.2s;\n flex: 1;\n position: relative;\n}\n\n.progress-step + .progress-step::before {\n content: '';\n position: absolute;\n left: -50%;\n top: 14px;\n width: 100%;\n height: 1px;\n background: #d4d3cc;\n z-index: 0;\n}\n\n.progress-step.active {\n opacity: 1;\n}\n\n.step-number {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n background: #e8e7e0;\n color: #666;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 0.82em;\n border: 1px solid #d4d3cc;\n position: relative;\n z-index: 1;\n}\n\n.progress-step.active .step-number {\n background: #8fa06e;\n color: #fff;\n border-color: #8fa06e;\n}\n\n.step-label {\n color: #999;\n font-size: 0.78em;\n font-weight: 500;\n text-align: center;\n}\n\n.progress-step.active .step-label {\n color: #1e1e1e;\n}\n\n/* Content card */\n.wizard-content {\n background: #fff;\n border-radius: 14px;\n padding: 36px;\n max-width: 780px;\n margin: 0 auto 24px;\n border: 1px solid #e8e7e0;\n}\n\n/* Navigation */\n.wizard-navigation {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n max-width: 780px;\n margin: 0 auto;\n}\n\n.nav-button {\n padding: 10px 28px;\n border-radius: 8px;\n font-size: 0.9em;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n min-width: 120px;\n}\n\n.nav-button.primary {\n background: #8fa06e;\n color: #fff;\n border: none;\n}\n\n.nav-button.primary:hover:not(:disabled) {\n background: #7d8e5e;\n}\n\n.nav-button.secondary {\n background: transparent;\n color: #666;\n border: 1px solid #d4d3cc;\n}\n\n.nav-button.secondary:hover:not(:disabled) {\n border-color: #999;\n color: #333;\n}\n\n.nav-button:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n@media (max-width: 768px) {\n .wizard-container {\n padding: 32px 20px;\n }\n\n .wizard-header h1 {\n font-size: 1.5em;\n }\n\n .wizard-progress {\n gap: 0;\n }\n\n .wizard-content {\n padding: 20px;\n }\n}\n","/* ── Minimalist AddNewPipeline ── */\n.pipeline-form-container {\n min-height: 100vh;\n background: #f0efe8;\n padding: 48px 56px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-sizing: border-box;\n}\n\n.pipeline-form-header {\n margin-bottom: 32px;\n}\n\n.pipeline-form-header .back-btn {\n background: transparent;\n border: 1px solid #d4d3cc;\n color: #666;\n padding: 7px 14px;\n border-radius: 8px;\n font-size: 0.85em;\n font-weight: 500;\n cursor: pointer;\n transition: border-color 0.15s, color 0.15s;\n margin-bottom: 20px;\n display: inline-block;\n}\n\n.pipeline-form-header .back-btn:hover {\n border-color: #999;\n color: #333;\n}\n\n.pipeline-form-header h1 {\n margin: 0 0 6px 0;\n font-size: 1.9em;\n font-weight: 400;\n color: #1e1e1e;\n letter-spacing: -0.4px;\n}\n\n.pipeline-form-header .subtitle {\n margin: 0;\n font-size: 0.88em;\n color: #999;\n}\n\n/* Form card */\n.pipeline-form {\n background: #fff;\n border-radius: 14px;\n padding: 36px;\n max-width: 860px;\n border: 1px solid #e8e7e0;\n}\n\n.form-section {\n margin-bottom: 28px;\n padding-bottom: 28px;\n border-bottom: 1px solid #f0efe8;\n}\n\n.form-section:last-of-type {\n border-bottom: none;\n margin-bottom: 0;\n padding-bottom: 0;\n}\n\n.form-section h3 {\n margin: 0 0 6px 0;\n color: #aaa;\n font-size: 0.78em;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n}\n\n.section-description {\n margin: 0 0 18px 0;\n color: #888;\n font-size: 0.87em;\n line-height: 1.5;\n}\n\n/* JSON upload box */\n.json-upload-section {\n background: #fafaf8;\n padding: 24px;\n border-radius: 10px;\n border: 1px solid #eeede6;\n}\n\n.file-input {\n display: none;\n}\n\n.file-upload-box {\n position: relative;\n}\n\n.file-label {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 18px;\n padding: 36px 24px;\n border: 1.5px dashed #c8c7be;\n border-radius: 10px;\n background: #fff;\n cursor: pointer;\n transition: border-color 0.15s, background 0.15s;\n}\n\n.file-label:hover {\n border-color: #8fa06e;\n background: #f7f8f3;\n}\n\n.file-icon {\n font-size: 2.2em;\n opacity: 0.6;\n}\n\n.file-text {\n text-align: left;\n}\n\n.file-text strong {\n font-size: 0.95em;\n color: #333;\n display: block;\n margin-bottom: 4px;\n font-weight: 500;\n}\n\n.file-text small {\n color: #aaa;\n font-size: 0.82em;\n}\n\n/* Validation messages */\n.validation-error {\n margin-top: 12px;\n background: #fef2f0;\n border: 1px solid #f5c6c0;\n color: #c0392b;\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 0.85em;\n}\n\n.validation-success {\n margin-top: 12px;\n background: #f0f8f0;\n border: 1px solid #b8ddb8;\n color: #2d6a2d;\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 0.85em;\n}\n\n.error-message {\n background: #fef2f0;\n border-left: 3px solid #e87060;\n padding: 12px 16px;\n border-radius: 8px;\n color: #c0392b;\n margin-bottom: 18px;\n font-size: 0.88em;\n}\n\n.success-message {\n background: #f0f8f0;\n border-left: 3px solid #6aaa6a;\n padding: 12px 16px;\n border-radius: 8px;\n color: #2d6a2d;\n margin-bottom: 18px;\n font-size: 0.88em;\n}\n\n/* Form controls */\n.form-group {\n margin-bottom: 18px;\n}\n\n.form-group label {\n display: block;\n margin-bottom: 6px;\n color: #555;\n font-weight: 500;\n font-size: 0.85em;\n}\n\n.form-input,\n.form-textarea {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #e0dfd8;\n border-radius: 8px;\n font-size: 0.9em;\n font-family: inherit;\n background: #fafaf8;\n color: #1e1e1e;\n transition: border-color 0.15s;\n box-sizing: border-box;\n}\n\n.form-input:focus,\n.form-textarea:focus {\n outline: none;\n border-color: #8fa06e;\n background: #fff;\n}\n\n.form-textarea {\n resize: vertical;\n}\n\n/* Submit button */\n.form-actions {\n display: flex;\n gap: 12px;\n}\n\n.submit-btn {\n flex: 1;\n padding: 11px 24px;\n background: #8fa06e;\n color: #fff;\n border: none;\n border-radius: 8px;\n font-size: 0.9em;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.submit-btn:hover:not(:disabled) {\n background: #7d8e5e;\n}\n\n.submit-btn:disabled {\n background: #c0c9aa;\n cursor: not-allowed;\n}\n\n/* Step cards */\n.steps-container {\n display: grid;\n gap: 16px;\n margin-bottom: 18px;\n}\n\n.step-card {\n border: 1px solid #e8e7e0;\n border-radius: 10px;\n padding: 18px;\n background: #fafaf8;\n}\n\n.step-card:hover {\n border-color: #c0bfb8;\n}\n\n.step-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 14px;\n padding-bottom: 12px;\n border-bottom: 1px solid #f0efe8;\n}\n\n.step-header h4 {\n margin: 0;\n color: #1e1e1e;\n font-size: 0.9em;\n font-weight: 500;\n}\n\n.remove-step-btn {\n background: transparent;\n color: #ccc;\n border: 1px solid #e0dfd8;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n cursor: pointer;\n font-size: 1em;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.15s;\n}\n\n.remove-step-btn:hover {\n background: #fef2f0;\n border-color: #e87060;\n color: #c0392b;\n}\n\n.step-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.add-step-btn {\n display: block;\n width: 100%;\n padding: 10px 18px;\n background: transparent;\n border: 1.5px dashed #c8c7be;\n border-radius: 8px;\n color: #999;\n font-size: 0.88em;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n margin-bottom: 24px;\n}\n\n.add-step-btn:hover {\n border-color: #8fa06e;\n color: #8fa06e;\n background: #f7f8f3;\n}\n\n/* Pipeline table */\n.pipelines-table-wrapper {\n margin: 16px 0;\n overflow-x: auto;\n border-radius: 8px;\n border: 1px solid #e8e7e0;\n}\n\n.pipelines-table {\n width: 100%;\n border-collapse: collapse;\n background: #fff;\n}\n\n.pipelines-table thead {\n background: #fafaf8;\n border-bottom: 1px solid #e8e7e0;\n}\n\n.pipelines-table th {\n padding: 10px 14px;\n text-align: left;\n font-weight: 500;\n color: #aaa;\n font-size: 0.78em;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.pipelines-table tbody tr {\n border-bottom: 1px solid #f0efe8;\n cursor: pointer;\n transition: background 0.1s;\n}\n\n.pipelines-table tbody tr:hover {\n background: #fafaf8;\n}\n\n.pipelines-table tbody tr.selected {\n background: #f7f8f3;\n border-left: 3px solid #8fa06e;\n}\n\n.pipelines-table td {\n padding: 10px 14px;\n color: #333;\n font-size: 0.88em;\n}\n\n.pipeline-checkbox {\n width: 16px;\n height: 16px;\n cursor: pointer;\n accent-color: #8fa06e;\n}\n\n.pipeline-id {\n font-weight: 500;\n color: #8fa06e;\n}\n\n.selection-summary {\n margin-top: 14px;\n padding: 10px 14px;\n background: #f7f8f3;\n border-left: 3px solid #8fa06e;\n border-radius: 6px;\n color: #4a5c35;\n font-size: 0.87em;\n}\n\n/* Review styles */\n.review-sections {\n margin-bottom: 24px;\n}\n\n.review-section {\n margin-bottom: 18px;\n padding: 18px;\n background: #fafaf8;\n border-radius: 8px;\n border-left: 3px solid #c8c7be;\n}\n\n.review-section h3 {\n margin: 0 0 12px 0;\n color: #aaa;\n font-size: 0.78em;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n}\n\n.review-items {\n display: grid;\n gap: 8px;\n}\n\n.review-item {\n display: grid;\n grid-template-columns: 180px 1fr;\n gap: 12px;\n padding: 8px 0;\n border-bottom: 1px solid #f0efe8;\n font-size: 0.88em;\n}\n\n.review-item:last-child {\n border-bottom: none;\n}\n\n.review-item .label {\n font-weight: 500;\n color: #999;\n}\n\n.review-item .value {\n color: #333;\n word-break: break-word;\n}\n\n.info-box {\n background: #f7f8f3;\n border-left: 3px solid #8fa06e;\n padding: 14px;\n border-radius: 6px;\n margin-bottom: 18px;\n color: #444;\n font-size: 0.88em;\n line-height: 1.6;\n}\n\n.info-box ul {\n margin: 8px 0 0 0;\n padding-left: 18px;\n}\n\n.info-box li {\n margin-bottom: 6px;\n color: #666;\n}\n\n.validation-note {\n padding: 10px 14px;\n background: #f7f8f3;\n border-left: 3px solid #8fa06e;\n border-radius: 6px;\n color: #4a5c35;\n font-size: 0.87em;\n margin-top: 16px;\n}\n\n.empty-state {\n text-align: center;\n padding: 40px 20px;\n background: #fafaf8;\n border-radius: 8px;\n color: #aaa;\n font-size: 0.9em;\n border: 1px solid #e8e7e0;\n}\n\n.submit-button {\n width: 100%;\n padding: 11px;\n background: #8fa06e;\n color: #fff;\n border: none;\n border-radius: 8px;\n font-size: 0.9em;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.submit-button:hover:not(:disabled) {\n background: #7d8e5e;\n}\n\n.submit-button:disabled {\n background: #c0c9aa;\n cursor: not-allowed;\n}\n\n.help-text {\n display: block;\n margin-top: 5px;\n color: #bbb;\n font-size: 0.8em;\n}\n\n/* Steps preview */\n.steps-preview {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n\n.steps-preview li {\n padding: 10px 12px;\n margin-bottom: 6px;\n background: #fafaf8;\n border-radius: 6px;\n border-left: 3px solid #c8c7be;\n display: flex;\n justify-content: space-between;\n align-items: center;\n font-size: 0.88em;\n}\n\n.step-function {\n font-weight: 500;\n color: #8fa06e;\n}\n\n.step-deps {\n font-size: 0.82em;\n color: #aaa;\n background: #fff;\n padding: 3px 8px;\n border-radius: 4px;\n border: 1px solid #e8e7e0;\n}\n\n@media (max-width: 768px) {\n .pipeline-form-container {\n padding: 32px 20px;\n }\n\n .pipeline-form {\n padding: 20px;\n }\n\n .pipeline-form-header h1 {\n font-size: 1.5em;\n }\n\n .step-grid {\n grid-template-columns: 1fr;\n }\n\n .review-item {\n grid-template-columns: 1fr;\n }\n}\n","/* ── ManageJobs ── */\n.mj-container {\n min-height: 100vh;\n background: #f0efe8;\n padding: 48px 56px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-sizing: border-box;\n}\n\n/* Header */\n.mj-header {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-bottom: 36px;\n}\n\n.mj-title {\n margin: 0;\n font-size: 1.9em;\n font-weight: 400;\n color: #1e1e1e;\n letter-spacing: -0.4px;\n flex-grow: 1;\n}\n\n.mj-btn-ghost {\n background: transparent;\n border: 1px solid #d4d3cc;\n color: #666;\n padding: 7px 14px;\n border-radius: 8px;\n font-size: 0.85em;\n font-weight: 500;\n cursor: pointer;\n transition: border-color 0.15s, color 0.15s;\n}\n.mj-btn-ghost:hover { border-color: #999; color: #333; }\n\n/* Stats bar */\n.mj-stats {\n display: flex;\n gap: 12px;\n margin-bottom: 28px;\n flex-wrap: wrap;\n}\n\n.mj-stat {\n background: #fff;\n border: 1px solid #e8e7e0;\n border-radius: 10px;\n padding: 14px 22px;\n text-align: center;\n min-width: 80px;\n}\n\n.mj-stat-value {\n font-size: 1.6em;\n font-weight: 300;\n line-height: 1;\n margin-bottom: 4px;\n}\n\n.mj-stat-label {\n font-size: 0.72em;\n color: #aaa;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n}\n\n/* Filter tabs */\n.mj-filters {\n display: flex;\n gap: 8px;\n margin-bottom: 24px;\n flex-wrap: wrap;\n}\n\n.mj-filter {\n padding: 6px 16px;\n border: 1px solid #d4d3cc;\n background: transparent;\n color: #666;\n border-radius: 20px;\n font-size: 0.83em;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n}\n.mj-filter:hover { border-color: #999; color: #333; }\n.mj-filter.active { background: #1e1e1e; border-color: #1e1e1e; color: #fff; }\n\n/* Table */\n.mj-table {\n background: #fff;\n border: 1px solid #e8e7e0;\n border-radius: 12px;\n overflow: hidden;\n max-width: 1100px;\n}\n\n.mj-table-head {\n display: grid;\n grid-template-columns: 140px 110px 1fr 160px 180px;\n gap: 16px;\n padding: 11px 20px;\n background: #fafaf8;\n border-bottom: 1px solid #e8e7e0;\n font-size: 0.74em;\n font-weight: 600;\n color: #aaa;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n}\n\n.mj-table-row {\n display: grid;\n grid-template-columns: 140px 110px 1fr 160px 180px;\n gap: 16px;\n padding: 14px 20px;\n border-bottom: 1px solid #f0efe8;\n align-items: center;\n cursor: pointer;\n transition: background 0.1s;\n font-size: 0.88em;\n}\n.mj-table-row:last-child { border-bottom: none; }\n.mj-table-row:hover { background: #fafaf8; }\n\n.mj-job-id {\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 0.92em;\n color: #333;\n font-weight: 500;\n}\n\n.mj-date { color: #777; font-size: 0.88em; }\n\n.mj-status-pill {\n display: inline-block;\n padding: 3px 9px;\n border-radius: 20px;\n color: #fff;\n font-size: 0.72em;\n font-weight: 700;\n letter-spacing: 0.4px;\n white-space: nowrap;\n}\n\n/* Progress cell */\n.mj-progress-cell {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mj-progress-track {\n flex: 1;\n height: 5px;\n background: #f0efe8;\n border-radius: 3px;\n overflow: hidden;\n}\n\n.mj-progress-fill {\n height: 100%;\n border-radius: 3px;\n transition: width 0.3s ease;\n}\n\n.mj-progress-pct {\n font-size: 0.8em;\n color: #aaa;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Row action buttons */\n.mj-row-actions {\n display: flex;\n gap: 6px;\n align-items: center;\n}\n\n.mj-row-btn {\n padding: 5px 10px;\n border-radius: 7px;\n font-size: 0.8em;\n font-weight: 500;\n cursor: pointer;\n border: 1px solid transparent;\n transition: all 0.15s;\n white-space: nowrap;\n}\n.mj-row-btn:disabled { opacity: 0.3; cursor: not-allowed; }\n\n.mj-row-btn.cancel { background: #fff0f0; color: #c0392b; border-color: #f5c6c6; }\n.mj-row-btn.cancel:hover:not(:disabled) { background: #dc3545; border-color: #dc3545; color: #fff; }\n\n.mj-row-btn.resume { background: #f0faf3; color: #1a7a3a; border-color: #b8dfc5; }\n.mj-row-btn.resume:hover:not(:disabled) { background: #28a745; border-color: #28a745; color: #fff; }\n\n.mj-row-btn.details { background: transparent; color: #555; border-color: #d4d3cc; }\n.mj-row-btn.details:hover { background: #1e1e1e; border-color: #1e1e1e; color: #fff; }\n\n/* ── Detail view ─────────────────────────────────────────────────────────── */\n.mj-detail-card {\n background: #fff;\n border: 1px solid #e8e7e0;\n border-radius: 14px;\n padding: 36px;\n max-width: 700px;\n}\n\n/* Top row: ID + status */\n.mj-detail-top {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 28px;\n padding-bottom: 24px;\n border-bottom: 1px solid #f0efe8;\n}\n\n.mj-detail-id {\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 0.9em;\n color: #333;\n font-weight: 500;\n margin-bottom: 6px;\n word-break: break-all;\n}\n\n.mj-detail-date {\n font-size: 0.83em;\n color: #aaa;\n}\n\n/* Progress in detail */\n.mj-detail-progress {\n margin-bottom: 24px;\n padding-bottom: 24px;\n border-bottom: 1px solid #f0efe8;\n}\n\n.mj-progress-meta {\n display: flex;\n justify-content: space-between;\n font-size: 0.83em;\n color: #aaa;\n margin-bottom: 8px;\n}\n\n/* Actions */\n.mj-detail-actions {\n display: flex;\n gap: 10px;\n margin-bottom: 28px;\n padding-bottom: 28px;\n border-bottom: 1px solid #f0efe8;\n}\n\n.mj-action-cancel,\n.mj-action-resume {\n padding: 9px 20px;\n border-radius: 9px;\n font-size: 0.85em;\n font-weight: 600;\n cursor: pointer;\n border: 1px solid transparent;\n transition: all 0.15s;\n}\n.mj-action-cancel:disabled,\n.mj-action-resume:disabled { opacity: 0.3; cursor: not-allowed; }\n\n.mj-action-cancel { background: #fff0f0; color: #c0392b; border-color: #f5c6c6; }\n.mj-action-cancel:hover:not(:disabled) { background: #dc3545; border-color: #dc3545; color: #fff; }\n\n.mj-action-resume { background: #f0faf3; color: #1a7a3a; border-color: #b8dfc5; }\n.mj-action-resume:hover:not(:disabled) { background: #28a745; border-color: #28a745; color: #fff; }\n\n/* Pipeline step tracker */\n.mj-steps-section {}\n\n.mj-steps-label {\n font-size: 0.72em;\n font-weight: 600;\n color: #aaa;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n margin-bottom: 16px;\n}\n\n.mj-steps-track { display: flex; flex-direction: column; }\n\n.mj-step-row {\n display: flex;\n gap: 16px;\n align-items: stretch;\n}\n\n.mj-step-left {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 20px;\n flex-shrink: 0;\n}\n\n.mj-step-dot {\n width: 14px;\n height: 14px;\n border-radius: 50%;\n border: 2px solid #ccc;\n flex-shrink: 0;\n margin-top: 3px;\n transition: background 0.2s, border-color 0.2s;\n}\n\n.mj-step-line {\n width: 2px;\n flex: 1;\n background: #e8e7e0;\n margin: 4px 0;\n min-height: 20px;\n}\n\n.mj-step-body {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 6px 0 20px 0;\n flex: 1;\n border-bottom: 1px solid #f5f4ef;\n}\n\n.mj-step-row:last-child .mj-step-body {\n border-bottom: none;\n padding-bottom: 0;\n}\n\n.mj-step-name {\n font-size: 0.9em;\n font-weight: 500;\n color: #1e1e1e;\n text-transform: capitalize;\n}\n\n.mj-step-status {\n font-size: 0.8em;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n/* States */\n.mj-empty {\n text-align: center;\n padding: 64px 20px;\n background: #fff;\n border-radius: 12px;\n color: #aaa;\n font-size: 0.95em;\n border: 1px solid #e8e7e0;\n max-width: 1100px;\n}\n\n.mj-error {\n background: #fef2f0;\n border-left: 3px solid #e87060;\n padding: 12px 16px;\n border-radius: 8px;\n color: #c0392b;\n margin-bottom: 16px;\n max-width: 1100px;\n font-size: 0.88em;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .mj-container { padding: 24px 16px; }\n\n .mj-table-head,\n .mj-table-row { grid-template-columns: 1fr 90px; }\n\n .mj-table-head span:nth-child(3),\n .mj-table-head span:nth-child(4),\n .mj-table-row span:nth-child(3),\n .mj-table-row span:nth-child(4) { display: none; }\n\n .mj-detail-card { padding: 20px; }\n .mj-detail-top { flex-direction: column; gap: 12px; }\n}\n","/* ── Minimalist Dashboard ── */\n.dashboard-container {\n min-height: 100vh;\n background: #f0efe8;\n padding: 48px 56px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-sizing: border-box;\n}\n\n/* Greeting */\n.dashboard-greeting {\n margin-bottom: 48px;\n}\n\n.dashboard-greeting h1 {\n font-size: 2.6em;\n font-weight: 400;\n color: #1e1e1e;\n margin: 0 0 6px 0;\n letter-spacing: -0.5px;\n}\n\n.dashboard-greeting p {\n font-size: 0.95em;\n color: #888;\n margin: 0;\n font-weight: 400;\n}\n\n/* Section heading */\n.section-title {\n font-size: 1.25em;\n font-weight: 500;\n color: #1e1e1e;\n margin: 0 0 24px 0;\n letter-spacing: -0.2px;\n}\n\n/* Action cards grid */\n.dashboard-actions {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 20px;\n margin-bottom: 56px;\n}\n\n.action-card {\n border-radius: 14px;\n padding: 32px 28px 28px;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n gap: 12px;\n transition: transform 0.15s ease, opacity 0.15s ease;\n min-height: 220px;\n box-sizing: border-box;\n position: relative;\n}\n\n.action-card:hover {\n transform: translateY(-3px);\n opacity: 0.92;\n}\n\n/* Individual card colors */\n.create-job {\n background: #8fa06e;\n}\n\n.add-pipeline {\n background: #b57d5a;\n}\n\n.manage-jobs {\n background: #c5ca85;\n}\n\n/* Card icon */\n.card-icon-label {\n font-size: 0.8em;\n font-weight: 600;\n color: rgba(0, 0, 0, 0.45);\n text-transform: uppercase;\n letter-spacing: 1px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.card-icon-label svg {\n width: 14px;\n height: 14px;\n}\n\n.action-card h3 {\n margin: 4px 0 0;\n font-size: 1.25em;\n font-weight: 500;\n color: #1a1a1a;\n line-height: 1.3;\n}\n\n.action-card p {\n margin: 0;\n color: rgba(0, 0, 0, 0.55);\n font-size: 0.88em;\n line-height: 1.6;\n flex-grow: 1;\n}\n\n/* Tags at bottom of card */\n.card-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n\n.card-tag {\n background: rgba(0, 0, 0, 0.1);\n color: rgba(0, 0, 0, 0.6);\n font-size: 0.75em;\n padding: 4px 10px;\n border-radius: 20px;\n font-weight: 500;\n}\n\n/* Workspace section */\n.workspace-section {\n margin-top: 4px;\n}\n\n.workspace-grid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 20px;\n}\n\n.workspace-card {\n background: #ffffff;\n border-radius: 14px;\n padding: 28px;\n min-height: 140px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n box-sizing: border-box;\n border: 1px solid #e8e7e0;\n}\n\n.workspace-card h4 {\n margin: 0;\n font-size: 0.9em;\n font-weight: 500;\n color: #888;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.workspace-stat {\n font-size: 2.2em;\n font-weight: 300;\n color: #1e1e1e;\n margin: 0;\n line-height: 1;\n}\n\n.workspace-stat-label {\n font-size: 0.85em;\n color: #aaa;\n margin: 0;\n}\n\n/* Responsive */\n@media (max-width: 900px) {\n .dashboard-container {\n padding: 32px 24px;\n }\n\n .dashboard-actions,\n .workspace-grid {\n grid-template-columns: 1fr;\n }\n}\n"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/my-app/build/static/js/main.737d25b6.js b/my-app/build/static/js/main.737d25b6.js deleted file mode 100644 index a69e5cf..0000000 --- a/my-app/build/static/js/main.737d25b6.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see main.737d25b6.js.LICENSE.txt */ -(()=>{"use strict";var e={4:(e,t,n)=>{var r=n(853),l=n(43),a=n(950);function i(e){var t="https://react.dev/errors/"+e;if(1M||(e.current=D[M],D[M]=null,M--)}function B(e,t){M++,D[M]=e.current,e.current=t}var $=I(null),H=I(null),V=I(null),W=I(null);function q(e,t){switch(B(V,t),B(H,e),B($,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?ld(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)e=ad(t=ld(t),e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}U($),B($,e)}function Q(){U($),U(H),U(V)}function J(e){null!==e.memoizedState&&B(W,e);var t=$.current,n=ad(t,e.type);t!==n&&(B(H,e),B($,n))}function G(e){H.current===e&&(U($),U(H)),W.current===e&&(U(W),Jd._currentValue=A)}var K=Object.prototype.hasOwnProperty,Y=r.unstable_scheduleCallback,X=r.unstable_cancelCallback,Z=r.unstable_shouldYield,ee=r.unstable_requestPaint,te=r.unstable_now,ne=r.unstable_getCurrentPriorityLevel,re=r.unstable_ImmediatePriority,le=r.unstable_UserBlockingPriority,ae=r.unstable_NormalPriority,ie=r.unstable_LowPriority,oe=r.unstable_IdlePriority,se=r.log,ue=r.unstable_setDisableYieldValue,ce=null,de=null;function fe(e){if("function"===typeof se&&ue(e),de&&"function"===typeof de.setStrictMode)try{de.setStrictMode(ce,e)}catch(t){}}var pe=Math.clz32?Math.clz32:function(e){return 0===(e>>>=0)?32:31-(he(e)/me|0)|0},he=Math.log,me=Math.LN2;var ge=256,ve=4194304;function be(e){var t=42&e;if(0!==t)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:case 262144:case 524288:case 1048576:case 2097152:return 4194048&e;case 4194304:case 8388608:case 16777216:case 33554432:return 62914560&e;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function ye(e,t,n){var r=e.pendingLanes;if(0===r)return 0;var l=0,a=e.suspendedLanes,i=e.pingedLanes;e=e.warmLanes;var o=134217727&r;return 0!==o?0!==(r=o&~a)?l=be(r):0!==(i&=o)?l=be(i):n||0!==(n=o&~e)&&(l=be(n)):0!==(o=r&~a)?l=be(o):0!==i?l=be(i):n||0!==(n=r&~e)&&(l=be(n)),0===l?0:0!==t&&t!==l&&0===(t&a)&&((a=l&-l)>=(n=t&-t)||32===a&&0!==(4194048&n))?t:l}function xe(e,t){return 0===(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)}function ke(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;default:return-1}}function we(){var e=ge;return 0===(4194048&(ge<<=1))&&(ge=256),e}function Se(){var e=ve;return 0===(62914560&(ve<<=1))&&(ve=4194304),e}function je(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function Ne(e,t){e.pendingLanes|=t,268435456!==t&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Ce(e,t,n){e.pendingLanes|=t,e.suspendedLanes&=~t;var r=31-pe(t);e.entangledLanes|=t,e.entanglements[r]=1073741824|e.entanglements[r]|4194090&n}function Ee(e,t){var n=e.entangledLanes|=t;for(e=e.entanglements;n;){var r=31-pe(n),l=1<)":-1--l||s[r]!==u[l]){var c="\n"+s[r].replace(" at new "," at ");return e.displayName&&c.includes("")&&(c=c.replace("",e.displayName)),c}}while(1<=r&&0<=l);break}}}finally{at=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:"")?lt(n):""}function ot(e){switch(e.tag){case 26:case 27:case 5:return lt(e.type);case 16:return lt("Lazy");case 13:return lt("Suspense");case 19:return lt("SuspenseList");case 0:case 15:return it(e.type,!1);case 11:return it(e.type.render,!1);case 1:return it(e.type,!0);case 31:return lt("Activity");default:return""}}function st(e){try{var t="";do{t+=ot(e),e=e.return}while(e);return t}catch(n){return"\nError generating stack: "+n.message+"\n"+n.stack}}function ut(e){switch(typeof e){case"bigint":case"boolean":case"number":case"string":case"undefined":case"object":return e;default:return""}}function ct(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function dt(e){e._valueTracker||(e._valueTracker=function(e){var t=ct(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&"undefined"!==typeof n&&"function"===typeof n.get&&"function"===typeof n.set){var l=n.get,a=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return l.call(this)},set:function(e){r=""+e,a.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(e){r=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function ft(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=ct(e)?e.checked?"true":"false":e.value),(e=r)!==n&&(t.setValue(e),!0)}function pt(e){if("undefined"===typeof(e=e||("undefined"!==typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}var ht=/[\n"\\]/g;function mt(e){return e.replace(ht,function(e){return"\\"+e.charCodeAt(0).toString(16)+" "})}function gt(e,t,n,r,l,a,i,o){e.name="",null!=i&&"function"!==typeof i&&"symbol"!==typeof i&&"boolean"!==typeof i?e.type=i:e.removeAttribute("type"),null!=t?"number"===i?(0===t&&""===e.value||e.value!=t)&&(e.value=""+ut(t)):e.value!==""+ut(t)&&(e.value=""+ut(t)):"submit"!==i&&"reset"!==i||e.removeAttribute("value"),null!=t?bt(e,i,ut(t)):null!=n?bt(e,i,ut(n)):null!=r&&e.removeAttribute("value"),null==l&&null!=a&&(e.defaultChecked=!!a),null!=l&&(e.checked=l&&"function"!==typeof l&&"symbol"!==typeof l),null!=o&&"function"!==typeof o&&"symbol"!==typeof o&&"boolean"!==typeof o?e.name=""+ut(o):e.removeAttribute("name")}function vt(e,t,n,r,l,a,i,o){if(null!=a&&"function"!==typeof a&&"symbol"!==typeof a&&"boolean"!==typeof a&&(e.type=a),null!=t||null!=n){if(!("submit"!==a&&"reset"!==a||void 0!==t&&null!==t))return;n=null!=n?""+ut(n):"",t=null!=t?""+ut(t):n,o||t===e.value||(e.value=t),e.defaultValue=t}r="function"!==typeof(r=null!=r?r:l)&&"symbol"!==typeof r&&!!r,e.checked=o?e.checked:!!r,e.defaultChecked=!!r,null!=i&&"function"!==typeof i&&"symbol"!==typeof i&&"boolean"!==typeof i&&(e.name=i)}function bt(e,t,n){"number"===t&&pt(e.ownerDocument)===e||e.defaultValue===""+n||(e.defaultValue=""+n)}function yt(e,t,n,r){if(e=e.options,t){t={};for(var l=0;l=Sn),Cn=String.fromCharCode(32),En=!1;function Pn(e,t){switch(e){case"keyup":return-1!==kn.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function _n(e){return"object"===typeof(e=e.detail)&&"data"in e?e.data:null}var zn=!1;var Tn={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function On(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!Tn[e.type]:"textarea"===t}function Ln(e,t,n,r){Ot?Lt?Lt.push(r):Lt=[r]:Ot=r,0<(t=Vc(t,"onChange")).length&&(n=new Zt("onChange","change",null,n,r),e.push({event:n,listeners:t}))}var Rn=null,Fn=null;function An(e){Ac(e,0)}function Dn(e){if(ft(He(e)))return e}function Mn(e,t){if("change"===e)return t}var In=!1;if(Mt){var Un;if(Mt){var Bn="oninput"in document;if(!Bn){var $n=document.createElement("div");$n.setAttribute("oninput","return;"),Bn="function"===typeof $n.oninput}Un=Bn}else Un=!1;In=Un&&(!document.documentMode||9=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=Yn(r)}}function Zn(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?Zn(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function er(e){for(var t=pt((e=null!=e&&null!=e.ownerDocument&&null!=e.ownerDocument.defaultView?e.ownerDocument.defaultView:window).document);t instanceof e.HTMLIFrameElement;){try{var n="string"===typeof t.contentWindow.location.href}catch(r){n=!1}if(!n)break;t=pt((e=t.contentWindow).document)}return t}function tr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}var nr=Mt&&"documentMode"in document&&11>=document.documentMode,rr=null,lr=null,ar=null,ir=!1;function or(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;ir||null==rr||rr!==pt(r)||("selectionStart"in(r=rr)&&tr(r)?r={start:r.selectionStart,end:r.selectionEnd}:r={anchorNode:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset},ar&&Kn(ar,r)||(ar=r,0<(r=Vc(lr,"onSelect")).length&&(t=new Zt("onSelect","select",null,t,n),e.push({event:t,listeners:r}),t.target=rr)))}function sr(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var ur={animationend:sr("Animation","AnimationEnd"),animationiteration:sr("Animation","AnimationIteration"),animationstart:sr("Animation","AnimationStart"),transitionrun:sr("Transition","TransitionRun"),transitionstart:sr("Transition","TransitionStart"),transitioncancel:sr("Transition","TransitionCancel"),transitionend:sr("Transition","TransitionEnd")},cr={},dr={};function fr(e){if(cr[e])return cr[e];if(!ur[e])return e;var t,n=ur[e];for(t in n)if(n.hasOwnProperty(t)&&t in dr)return cr[e]=n[t];return e}Mt&&(dr=document.createElement("div").style,"AnimationEvent"in window||(delete ur.animationend.animation,delete ur.animationiteration.animation,delete ur.animationstart.animation),"TransitionEvent"in window||delete ur.transitionend.transition);var pr=fr("animationend"),hr=fr("animationiteration"),mr=fr("animationstart"),gr=fr("transitionrun"),vr=fr("transitionstart"),br=fr("transitioncancel"),yr=fr("transitionend"),xr=new Map,kr="abort auxClick beforeToggle cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");function wr(e,t){xr.set(e,t),Je(t,[e])}kr.push("scrollEnd");var Sr=new WeakMap;function jr(e,t){if("object"===typeof e&&null!==e){var n=Sr.get(e);return void 0!==n?n:(t={value:e,source:t,stack:st(t)},Sr.set(e,t),t)}return{value:e,source:t,stack:st(t)}}var Nr=[],Cr=0,Er=0;function Pr(){for(var e=Cr,t=Er=Cr=0;t>=i,l-=i,Yr=1<<32-pe(t)+l|n<a?a:8;var i=R.T,o={};R.T=o,Ui(e,!1,t,n);try{var s=l(),u=R.S;if(null!==u&&u(o,s),null!==s&&"object"===typeof s&&"function"===typeof s.then)Ii(e,t,function(e,t){var n=[],r={status:"pending",value:null,reason:null,then:function(e){n.push(e)}};return e.then(function(){r.status="fulfilled",r.value=t;for(var e=0;eh?(m=d,d=null):m=d.sibling;var g=p(l,d,o[h],s);if(null===g){null===d&&(d=m);break}e&&d&&null===g.alternate&&t(l,d),i=a(g,i,h),null===c?u=g:c.sibling=g,c=g,d=m}if(h===o.length)return n(l,d),al&&Zr(l,h),u;if(null===d){for(;hm?(g=h,h=null):g=h.sibling;var y=p(l,h,b.value,u);if(null===y){null===h&&(h=g);break}e&&h&&null===y.alternate&&t(l,h),o=a(y,o,m),null===d?c=y:d.sibling=y,d=y,h=g}if(b.done)return n(l,h),al&&Zr(l,m),c;if(null===h){for(;!b.done;m++,b=s.next())null!==(b=f(l,b.value,u))&&(o=a(b,o,m),null===d?c=b:d.sibling=b,d=b);return al&&Zr(l,m),c}for(h=r(h);!b.done;m++,b=s.next())null!==(b=v(h,l,m,b.value,u))&&(e&&null!==b.alternate&&h.delete(null===b.key?m:b.key),o=a(b,o,m),null===d?c=b:d.sibling=b,d=b);return e&&h.forEach(function(e){return t(l,e)}),al&&Zr(l,m),c}(s,u,c=y.call(c),d)}if("function"===typeof c.then)return b(s,u,Ki(c),d);if(c.$$typeof===k)return b(s,u,El(s,c),d);Xi(s,c)}return"string"===typeof c&&""!==c||"number"===typeof c||"bigint"===typeof c?(c=""+c,null!==u&&6===u.tag?(n(s,u.sibling),(d=l(u,c)).return=s,s=d):(n(s,u),(d=$r(c,s.mode,d)).return=s,s=d),o(s)):n(s,u)}return function(e,t,n,r){try{Gi=0;var l=b(e,t,n,r);return Ji=null,l}catch(i){if(i===Wl||i===Ql)throw i;var a=Ar(29,i,null,e.mode);return a.lanes=r,a.return=e,a}}}var to=eo(!0),no=eo(!1),ro=I(null),lo=null;function ao(e){var t=e.alternate;B(uo,1&uo.current),B(ro,e),null===lo&&(null===t||null!==pa.current||null!==t.memoizedState)&&(lo=e)}function io(e){if(22===e.tag){if(B(uo,uo.current),B(ro,e),null===lo){var t=e.alternate;null!==t&&null!==t.memoizedState&&(lo=e)}}else oo()}function oo(){B(uo,uo.current),B(ro,ro.current)}function so(e){U(ro),lo===e&&(lo=null),U(uo)}var uo=I(0);function co(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||gd(n)))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!==(128&t.flags))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}function fo(e,t,n,r){n=null===(n=n(r,t=e.memoizedState))||void 0===n?t:f({},t,n),e.memoizedState=n,0===e.lanes&&(e.updateQueue.baseState=n)}var po={enqueueSetState:function(e,t,n){e=e._reactInternals;var r=Ru(),l=la(r);l.payload=t,void 0!==n&&null!==n&&(l.callback=n),null!==(t=aa(e,l,r))&&(Au(t,e,r),ia(t,e,r))},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var r=Ru(),l=la(r);l.tag=1,l.payload=t,void 0!==n&&null!==n&&(l.callback=n),null!==(t=aa(e,l,r))&&(Au(t,e,r),ia(t,e,r))},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=Ru(),r=la(n);r.tag=2,void 0!==t&&null!==t&&(r.callback=t),null!==(t=aa(e,r,n))&&(Au(t,e,n),ia(t,e,n))}};function ho(e,t,n,r,l,a,i){return"function"===typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(r,a,i):!t.prototype||!t.prototype.isPureReactComponent||(!Kn(n,r)||!Kn(l,a))}function mo(e,t,n,r){e=t.state,"function"===typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,r),"function"===typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,r),t.state!==e&&po.enqueueReplaceState(t,t.state,null)}function go(e,t){var n=t;if("ref"in t)for(var r in n={},t)"ref"!==r&&(n[r]=t[r]);if(e=e.defaultProps)for(var l in n===t&&(n=f({},n)),e)void 0===n[l]&&(n[l]=e[l]);return n}var vo="function"===typeof reportError?reportError:function(e){if("object"===typeof window&&"function"===typeof window.ErrorEvent){var t=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:"object"===typeof e&&null!==e&&"string"===typeof e.message?String(e.message):String(e),error:e});if(!window.dispatchEvent(t))return}else if("object"===typeof process&&"function"===typeof process.emit)return void process.emit("uncaughtException",e);console.error(e)};function bo(e){vo(e)}function yo(e){console.error(e)}function xo(e){vo(e)}function ko(e,t){try{(0,e.onUncaughtError)(t.value,{componentStack:t.stack})}catch(n){setTimeout(function(){throw n})}}function wo(e,t,n){try{(0,e.onCaughtError)(n.value,{componentStack:n.stack,errorBoundary:1===t.tag?t.stateNode:null})}catch(r){setTimeout(function(){throw r})}}function So(e,t,n){return(n=la(n)).tag=3,n.payload={element:null},n.callback=function(){ko(e,t)},n}function jo(e){return(e=la(e)).tag=3,e}function No(e,t,n,r){var l=n.type.getDerivedStateFromError;if("function"===typeof l){var a=r.value;e.payload=function(){return l(a)},e.callback=function(){wo(t,n,r)}}var i=n.stateNode;null!==i&&"function"===typeof i.componentDidCatch&&(e.callback=function(){wo(t,n,r),"function"!==typeof l&&(null===ju?ju=new Set([this]):ju.add(this));var e=r.stack;this.componentDidCatch(r.value,{componentStack:null!==e?e:""})})}var Co=Error(i(461)),Eo=!1;function Po(e,t,n,r){t.child=null===e?no(t,null,n,r):to(t,e.child,n,r)}function _o(e,t,n,r,l){n=n.render;var a=t.ref;if("ref"in r){var i={};for(var o in r)"ref"!==o&&(i[o]=r[o])}else i=r;return Nl(t),r=Ta(e,t,n,i,a,l),o=Fa(),null===e||Eo?(al&&o&&tl(t),t.flags|=1,Po(e,t,r,l),t.child):(Aa(e,t,l),Go(e,t,l))}function zo(e,t,n,r,l){if(null===e){var a=n.type;return"function"!==typeof a||Dr(a)||void 0!==a.defaultProps||null!==n.compare?((e=Ur(n.type,null,r,t,t.mode,l)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=a,To(e,t,a,r,l))}if(a=e.child,!Ko(e,l)){var i=a.memoizedProps;if((n=null!==(n=n.compare)?n:Kn)(i,r)&&e.ref===t.ref)return Go(e,t,l)}return t.flags|=1,(e=Mr(a,r)).ref=t.ref,e.return=t,t.child=e}function To(e,t,n,r,l){if(null!==e){var a=e.memoizedProps;if(Kn(a,r)&&e.ref===t.ref){if(Eo=!1,t.pendingProps=r=a,!Ko(e,l))return t.lanes=e.lanes,Go(e,t,l);0!==(131072&e.flags)&&(Eo=!0)}}return Fo(e,t,n,r,l)}function Oo(e,t,n){var r=t.pendingProps,l=r.children,a=null!==e?e.memoizedState:null;if("hidden"===r.mode){if(0!==(128&t.flags)){if(r=null!==a?a.baseLanes|n:n,null!==e){for(l=t.child=e.child,a=0;null!==l;)a=a|l.lanes|l.childLanes,l=l.sibling;t.childLanes=a&~r}else t.childLanes=0,t.child=null;return Lo(e,t,r,n)}if(0===(536870912&n))return t.lanes=t.childLanes=536870912,Lo(e,t,null!==a?a.baseLanes|n:n,n);t.memoizedState={baseLanes:0,cachePool:null},null!==e&&Hl(0,null!==a?a.cachePool:null),null!==a?ma(t,a):ga(),io(t)}else null!==a?(Hl(0,a.cachePool),ma(t,a),oo(),t.memoizedState=null):(null!==e&&Hl(0,null),ga(),oo());return Po(e,t,l,n),t.child}function Lo(e,t,n,r){var l=$l();return l=null===l?null:{parent:Ol._currentValue,pool:l},t.memoizedState={baseLanes:n,cachePool:l},null!==e&&Hl(0,null),ga(),io(t),null!==e&&Sl(e,t,r,!0),null}function Ro(e,t){var n=t.ref;if(null===n)null!==e&&null!==e.ref&&(t.flags|=4194816);else{if("function"!==typeof n&&"object"!==typeof n)throw Error(i(284));null!==e&&e.ref===n||(t.flags|=4194816)}}function Fo(e,t,n,r,l){return Nl(t),n=Ta(e,t,n,r,void 0,l),r=Fa(),null===e||Eo?(al&&r&&tl(t),t.flags|=1,Po(e,t,n,l),t.child):(Aa(e,t,l),Go(e,t,l))}function Ao(e,t,n,r,l,a){return Nl(t),t.updateQueue=null,n=La(t,r,n,l),Oa(e),r=Fa(),null===e||Eo?(al&&r&&tl(t),t.flags|=1,Po(e,t,n,a),t.child):(Aa(e,t,a),Go(e,t,a))}function Do(e,t,n,r,l){if(Nl(t),null===t.stateNode){var a=Rr,i=n.contextType;"object"===typeof i&&null!==i&&(a=Cl(i)),a=new n(r,a),t.memoizedState=null!==a.state&&void 0!==a.state?a.state:null,a.updater=po,t.stateNode=a,a._reactInternals=t,(a=t.stateNode).props=r,a.state=t.memoizedState,a.refs={},na(t),i=n.contextType,a.context="object"===typeof i&&null!==i?Cl(i):Rr,a.state=t.memoizedState,"function"===typeof(i=n.getDerivedStateFromProps)&&(fo(t,n,i,r),a.state=t.memoizedState),"function"===typeof n.getDerivedStateFromProps||"function"===typeof a.getSnapshotBeforeUpdate||"function"!==typeof a.UNSAFE_componentWillMount&&"function"!==typeof a.componentWillMount||(i=a.state,"function"===typeof a.componentWillMount&&a.componentWillMount(),"function"===typeof a.UNSAFE_componentWillMount&&a.UNSAFE_componentWillMount(),i!==a.state&&po.enqueueReplaceState(a,a.state,null),ca(t,r,a,l),ua(),a.state=t.memoizedState),"function"===typeof a.componentDidMount&&(t.flags|=4194308),r=!0}else if(null===e){a=t.stateNode;var o=t.memoizedProps,s=go(n,o);a.props=s;var u=a.context,c=n.contextType;i=Rr,"object"===typeof c&&null!==c&&(i=Cl(c));var d=n.getDerivedStateFromProps;c="function"===typeof d||"function"===typeof a.getSnapshotBeforeUpdate,o=t.pendingProps!==o,c||"function"!==typeof a.UNSAFE_componentWillReceiveProps&&"function"!==typeof a.componentWillReceiveProps||(o||u!==i)&&mo(t,a,r,i),ta=!1;var f=t.memoizedState;a.state=f,ca(t,r,a,l),ua(),u=t.memoizedState,o||f!==u||ta?("function"===typeof d&&(fo(t,n,d,r),u=t.memoizedState),(s=ta||ho(t,n,s,r,f,u,i))?(c||"function"!==typeof a.UNSAFE_componentWillMount&&"function"!==typeof a.componentWillMount||("function"===typeof a.componentWillMount&&a.componentWillMount(),"function"===typeof a.UNSAFE_componentWillMount&&a.UNSAFE_componentWillMount()),"function"===typeof a.componentDidMount&&(t.flags|=4194308)):("function"===typeof a.componentDidMount&&(t.flags|=4194308),t.memoizedProps=r,t.memoizedState=u),a.props=r,a.state=u,a.context=i,r=s):("function"===typeof a.componentDidMount&&(t.flags|=4194308),r=!1)}else{a=t.stateNode,ra(e,t),c=go(n,i=t.memoizedProps),a.props=c,d=t.pendingProps,f=a.context,u=n.contextType,s=Rr,"object"===typeof u&&null!==u&&(s=Cl(u)),(u="function"===typeof(o=n.getDerivedStateFromProps)||"function"===typeof a.getSnapshotBeforeUpdate)||"function"!==typeof a.UNSAFE_componentWillReceiveProps&&"function"!==typeof a.componentWillReceiveProps||(i!==d||f!==s)&&mo(t,a,r,s),ta=!1,f=t.memoizedState,a.state=f,ca(t,r,a,l),ua();var p=t.memoizedState;i!==d||f!==p||ta||null!==e&&null!==e.dependencies&&jl(e.dependencies)?("function"===typeof o&&(fo(t,n,o,r),p=t.memoizedState),(c=ta||ho(t,n,c,r,f,p,s)||null!==e&&null!==e.dependencies&&jl(e.dependencies))?(u||"function"!==typeof a.UNSAFE_componentWillUpdate&&"function"!==typeof a.componentWillUpdate||("function"===typeof a.componentWillUpdate&&a.componentWillUpdate(r,p,s),"function"===typeof a.UNSAFE_componentWillUpdate&&a.UNSAFE_componentWillUpdate(r,p,s)),"function"===typeof a.componentDidUpdate&&(t.flags|=4),"function"===typeof a.getSnapshotBeforeUpdate&&(t.flags|=1024)):("function"!==typeof a.componentDidUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!==typeof a.getSnapshotBeforeUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=1024),t.memoizedProps=r,t.memoizedState=p),a.props=r,a.state=p,a.context=s,r=c):("function"!==typeof a.componentDidUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!==typeof a.getSnapshotBeforeUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=1024),r=!1)}return a=r,Ro(e,t),r=0!==(128&t.flags),a||r?(a=t.stateNode,n=r&&"function"!==typeof n.getDerivedStateFromError?null:a.render(),t.flags|=1,null!==e&&r?(t.child=to(t,e.child,null,l),t.child=to(t,null,n,l)):Po(e,t,n,l),t.memoizedState=a.state,e=t.child):e=Go(e,t,l),e}function Mo(e,t,n,r){return pl(),t.flags|=256,Po(e,t,n,r),t.child}var Io={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function Uo(e){return{baseLanes:e,cachePool:Vl()}}function Bo(e,t,n){return e=null!==e?e.childLanes&~n:0,t&&(e|=gu),e}function $o(e,t,n){var r,l=t.pendingProps,a=!1,o=0!==(128&t.flags);if((r=o)||(r=(null===e||null!==e.memoizedState)&&0!==(2&uo.current)),r&&(a=!0,t.flags&=-129),r=0!==(32&t.flags),t.flags&=-33,null===e){if(al){if(a?ao(t):oo(),al){var s,u=ll;if(s=u){e:{for(s=u,u=ol;8!==s.nodeType;){if(!u){u=null;break e}if(null===(s=vd(s.nextSibling))){u=null;break e}}u=s}null!==u?(t.memoizedState={dehydrated:u,treeContext:null!==Kr?{id:Yr,overflow:Xr}:null,retryLane:536870912,hydrationErrors:null},(s=Ar(18,null,null,0)).stateNode=u,s.return=t,t.child=s,rl=t,ll=null,s=!0):s=!1}s||ul(t)}if(null!==(u=t.memoizedState)&&null!==(u=u.dehydrated))return gd(u)?t.lanes=32:t.lanes=536870912,null;so(t)}return u=l.children,l=l.fallback,a?(oo(),u=Vo({mode:"hidden",children:u},a=t.mode),l=Br(l,a,n,null),u.return=t,l.return=t,u.sibling=l,t.child=u,(a=t.child).memoizedState=Uo(n),a.childLanes=Bo(e,r,n),t.memoizedState=Io,l):(ao(t),Ho(t,u))}if(null!==(s=e.memoizedState)&&null!==(u=s.dehydrated)){if(o)256&t.flags?(ao(t),t.flags&=-257,t=Wo(e,t,n)):null!==t.memoizedState?(oo(),t.child=e.child,t.flags|=128,t=null):(oo(),a=l.fallback,u=t.mode,l=Vo({mode:"visible",children:l.children},u),(a=Br(a,u,n,null)).flags|=2,l.return=t,a.return=t,l.sibling=a,t.child=l,to(t,e.child,null,n),(l=t.child).memoizedState=Uo(n),l.childLanes=Bo(e,r,n),t.memoizedState=Io,t=a);else if(ao(t),gd(u)){if(r=u.nextSibling&&u.nextSibling.dataset)var c=r.dgst;r=c,(l=Error(i(419))).stack="",l.digest=r,ml({value:l,source:null,stack:null}),t=Wo(e,t,n)}else if(Eo||Sl(e,t,n,!1),r=0!==(n&e.childLanes),Eo||r){if(null!==(r=ru)&&(0!==(l=0!==((l=0!==(42&(l=n&-n))?1:Pe(l))&(r.suspendedLanes|n))?0:l)&&l!==s.retryLane))throw s.retryLane=l,Tr(e,l),Au(r,e,l),Co;"$?"===u.data||Qu(),t=Wo(e,t,n)}else"$?"===u.data?(t.flags|=192,t.child=e.child,t=null):(e=s.treeContext,ll=vd(u.nextSibling),rl=t,al=!0,il=null,ol=!1,null!==e&&(Jr[Gr++]=Yr,Jr[Gr++]=Xr,Jr[Gr++]=Kr,Yr=e.id,Xr=e.overflow,Kr=t),(t=Ho(t,l.children)).flags|=4096);return t}return a?(oo(),a=l.fallback,u=t.mode,c=(s=e.child).sibling,(l=Mr(s,{mode:"hidden",children:l.children})).subtreeFlags=65011712&s.subtreeFlags,null!==c?a=Mr(c,a):(a=Br(a,u,n,null)).flags|=2,a.return=t,l.return=t,l.sibling=a,t.child=l,l=a,a=t.child,null===(u=e.child.memoizedState)?u=Uo(n):(null!==(s=u.cachePool)?(c=Ol._currentValue,s=s.parent!==c?{parent:c,pool:c}:s):s=Vl(),u={baseLanes:u.baseLanes|n,cachePool:s}),a.memoizedState=u,a.childLanes=Bo(e,r,n),t.memoizedState=Io,l):(ao(t),e=(n=e.child).sibling,(n=Mr(n,{mode:"visible",children:l.children})).return=t,n.sibling=null,null!==e&&(null===(r=t.deletions)?(t.deletions=[e],t.flags|=16):r.push(e)),t.child=n,t.memoizedState=null,n)}function Ho(e,t){return(t=Vo({mode:"visible",children:t},e.mode)).return=e,e.child=t}function Vo(e,t){return(e=Ar(22,e,null,t)).lanes=0,e.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null},e}function Wo(e,t,n){return to(t,e.child,null,n),(e=Ho(t,t.pendingProps.children)).flags|=2,t.memoizedState=null,e}function qo(e,t,n){e.lanes|=t;var r=e.alternate;null!==r&&(r.lanes|=t),kl(e.return,t,n)}function Qo(e,t,n,r,l){var a=e.memoizedState;null===a?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:r,tail:n,tailMode:l}:(a.isBackwards=t,a.rendering=null,a.renderingStartTime=0,a.last=r,a.tail=n,a.tailMode=l)}function Jo(e,t,n){var r=t.pendingProps,l=r.revealOrder,a=r.tail;if(Po(e,t,r.children,n),0!==(2&(r=uo.current)))r=1&r|2,t.flags|=128;else{if(null!==e&&0!==(128&e.flags))e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&qo(e,n,t);else if(19===e.tag)qo(e,n,t);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}r&=1}switch(B(uo,r),l){case"forwards":for(n=t.child,l=null;null!==n;)null!==(e=n.alternate)&&null===co(e)&&(l=n),n=n.sibling;null===(n=l)?(l=t.child,t.child=null):(l=n.sibling,n.sibling=null),Qo(t,!1,l,n,a);break;case"backwards":for(n=null,l=t.child,t.child=null;null!==l;){if(null!==(e=l.alternate)&&null===co(e)){t.child=l;break}e=l.sibling,l.sibling=n,n=l,l=e}Qo(t,!0,n,null,a);break;case"together":Qo(t,!1,null,null,void 0);break;default:t.memoizedState=null}return t.child}function Go(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),pu|=t.lanes,0===(n&t.childLanes)){if(null===e)return null;if(Sl(e,t,n,!1),0===(n&t.childLanes))return null}if(null!==e&&t.child!==e.child)throw Error(i(153));if(null!==t.child){for(n=Mr(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=Mr(e,e.pendingProps)).return=t;n.sibling=null}return t.child}function Ko(e,t){return 0!==(e.lanes&t)||!(null===(e=e.dependencies)||!jl(e))}function Yo(e,t,n){if(null!==e)if(e.memoizedProps!==t.pendingProps)Eo=!0;else{if(!Ko(e,n)&&0===(128&t.flags))return Eo=!1,function(e,t,n){switch(t.tag){case 3:q(t,t.stateNode.containerInfo),yl(0,Ol,e.memoizedState.cache),pl();break;case 27:case 5:J(t);break;case 4:q(t,t.stateNode.containerInfo);break;case 10:yl(0,t.type,t.memoizedProps.value);break;case 13:var r=t.memoizedState;if(null!==r)return null!==r.dehydrated?(ao(t),t.flags|=128,null):0!==(n&t.child.childLanes)?$o(e,t,n):(ao(t),null!==(e=Go(e,t,n))?e.sibling:null);ao(t);break;case 19:var l=0!==(128&e.flags);if((r=0!==(n&t.childLanes))||(Sl(e,t,n,!1),r=0!==(n&t.childLanes)),l){if(r)return Jo(e,t,n);t.flags|=128}if(null!==(l=t.memoizedState)&&(l.rendering=null,l.tail=null,l.lastEffect=null),B(uo,uo.current),r)break;return null;case 22:case 23:return t.lanes=0,Oo(e,t,n);case 24:yl(0,Ol,e.memoizedState.cache)}return Go(e,t,n)}(e,t,n);Eo=0!==(131072&e.flags)}else Eo=!1,al&&0!==(1048576&t.flags)&&el(t,Qr,t.index);switch(t.lanes=0,t.tag){case 16:e:{e=t.pendingProps;var r=t.elementType,l=r._init;if(r=l(r._payload),t.type=r,"function"!==typeof r){if(void 0!==r&&null!==r){if((l=r.$$typeof)===w){t.tag=11,t=_o(null,t,r,e,n);break e}if(l===N){t.tag=14,t=zo(null,t,r,e,n);break e}}throw t=O(r)||r,Error(i(306,t,""))}Dr(r)?(e=go(r,e),t.tag=1,t=Do(null,t,r,e,n)):(t.tag=0,t=Fo(null,t,r,e,n))}return t;case 0:return Fo(e,t,t.type,t.pendingProps,n);case 1:return Do(e,t,r=t.type,l=go(r,t.pendingProps),n);case 3:e:{if(q(t,t.stateNode.containerInfo),null===e)throw Error(i(387));r=t.pendingProps;var a=t.memoizedState;l=a.element,ra(e,t),ca(t,r,null,n);var o=t.memoizedState;if(r=o.cache,yl(0,Ol,r),r!==a.cache&&wl(t,[Ol],n,!0),ua(),r=o.element,a.isDehydrated){if(a={element:r,isDehydrated:!1,cache:o.cache},t.updateQueue.baseState=a,t.memoizedState=a,256&t.flags){t=Mo(e,t,r,n);break e}if(r!==l){ml(l=jr(Error(i(424)),t)),t=Mo(e,t,r,n);break e}if(9===(e=t.stateNode.containerInfo).nodeType)e=e.body;else e="HTML"===e.nodeName?e.ownerDocument.body:e;for(ll=vd(e.firstChild),rl=t,al=!0,il=null,ol=!0,n=no(t,null,r,n),t.child=n;n;)n.flags=-3&n.flags|4096,n=n.sibling}else{if(pl(),r===l){t=Go(e,t,n);break e}Po(e,t,r,n)}t=t.child}return t;case 26:return Ro(e,t),null===e?(n=Pd(t.type,null,t.pendingProps,null))?t.memoizedState=n:al||(n=t.type,e=t.pendingProps,(r=rd(V.current).createElement(n))[Oe]=t,r[Le]=e,ed(r,n,e),We(r),t.stateNode=r):t.memoizedState=Pd(t.type,e.memoizedProps,t.pendingProps,e.memoizedState),null;case 27:return J(t),null===e&&al&&(r=t.stateNode=xd(t.type,t.pendingProps,V.current),rl=t,ol=!0,l=ll,pd(t.type)?(bd=l,ll=vd(r.firstChild)):ll=l),Po(e,t,t.pendingProps.children,n),Ro(e,t),null===e&&(t.flags|=4194304),t.child;case 5:return null===e&&al&&((l=r=ll)&&(null!==(r=function(e,t,n,r){for(;1===e.nodeType;){var l=n;if(e.nodeName.toLowerCase()!==t.toLowerCase()){if(!r&&("INPUT"!==e.nodeName||"hidden"!==e.type))break}else if(r){if(!e[Ie])switch(t){case"meta":if(!e.hasAttribute("itemprop"))break;return e;case"link":if("stylesheet"===(a=e.getAttribute("rel"))&&e.hasAttribute("data-precedence"))break;if(a!==l.rel||e.getAttribute("href")!==(null==l.href||""===l.href?null:l.href)||e.getAttribute("crossorigin")!==(null==l.crossOrigin?null:l.crossOrigin)||e.getAttribute("title")!==(null==l.title?null:l.title))break;return e;case"style":if(e.hasAttribute("data-precedence"))break;return e;case"script":if(((a=e.getAttribute("src"))!==(null==l.src?null:l.src)||e.getAttribute("type")!==(null==l.type?null:l.type)||e.getAttribute("crossorigin")!==(null==l.crossOrigin?null:l.crossOrigin))&&a&&e.hasAttribute("async")&&!e.hasAttribute("itemprop"))break;return e;default:return e}}else{if("input"!==t||"hidden"!==e.type)return e;var a=null==l.name?null:""+l.name;if("hidden"===l.type&&e.getAttribute("name")===a)return e}if(null===(e=vd(e.nextSibling)))break}return null}(r,t.type,t.pendingProps,ol))?(t.stateNode=r,rl=t,ll=vd(r.firstChild),ol=!1,l=!0):l=!1),l||ul(t)),J(t),l=t.type,a=t.pendingProps,o=null!==e?e.memoizedProps:null,r=a.children,id(l,a)?r=null:null!==o&&id(l,o)&&(t.flags|=32),null!==t.memoizedState&&(l=Ta(e,t,Ra,null,null,n),Jd._currentValue=l),Ro(e,t),Po(e,t,r,n),t.child;case 6:return null===e&&al&&((e=n=ll)&&(null!==(n=function(e,t,n){if(""===t)return null;for(;3!==e.nodeType;){if((1!==e.nodeType||"INPUT"!==e.nodeName||"hidden"!==e.type)&&!n)return null;if(null===(e=vd(e.nextSibling)))return null}return e}(n,t.pendingProps,ol))?(t.stateNode=n,rl=t,ll=null,e=!0):e=!1),e||ul(t)),null;case 13:return $o(e,t,n);case 4:return q(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=to(t,null,r,n):Po(e,t,r,n),t.child;case 11:return _o(e,t,t.type,t.pendingProps,n);case 7:return Po(e,t,t.pendingProps,n),t.child;case 8:case 12:return Po(e,t,t.pendingProps.children,n),t.child;case 10:return r=t.pendingProps,yl(0,t.type,r.value),Po(e,t,r.children,n),t.child;case 9:return l=t.type._context,r=t.pendingProps.children,Nl(t),r=r(l=Cl(l)),t.flags|=1,Po(e,t,r,n),t.child;case 14:return zo(e,t,t.type,t.pendingProps,n);case 15:return To(e,t,t.type,t.pendingProps,n);case 19:return Jo(e,t,n);case 31:return r=t.pendingProps,n=t.mode,r={mode:r.mode,children:r.children},null===e?((n=Vo(r,n)).ref=t.ref,t.child=n,n.return=t,t=n):((n=Mr(e.child,r)).ref=t.ref,t.child=n,n.return=t,t=n),t;case 22:return Oo(e,t,n);case 24:return Nl(t),r=Cl(Ol),null===e?(null===(l=$l())&&(l=ru,a=Ll(),l.pooledCache=a,a.refCount++,null!==a&&(l.pooledCacheLanes|=n),l=a),t.memoizedState={parent:r,cache:l},na(t),yl(0,Ol,l)):(0!==(e.lanes&n)&&(ra(e,t),ca(t,null,null,n),ua()),l=e.memoizedState,a=t.memoizedState,l.parent!==r?(l={parent:r,cache:r},t.memoizedState=l,0===t.lanes&&(t.memoizedState=t.updateQueue.baseState=l),yl(0,Ol,r)):(r=a.cache,yl(0,Ol,r),r!==l.cache&&wl(t,[Ol],n,!0))),Po(e,t,t.pendingProps.children,n),t.child;case 29:throw t.pendingProps}throw Error(i(156,t.tag))}function Xo(e){e.flags|=4}function Zo(e,t){if("stylesheet"!==t.type||0!==(4&t.state.loading))e.flags&=-16777217;else if(e.flags|=16777216,!Bd(t)){if(null!==(t=ro.current)&&((4194048&au)===au?null!==lo:(62914560&au)!==au&&0===(536870912&au)||t!==lo))throw Xl=Jl,ql;e.flags|=8192}}function es(e,t){null!==t&&(e.flags|=4),16384&e.flags&&(t=22!==e.tag?Se():536870912,e.lanes|=t,vu|=t)}function ts(e,t){if(!al)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var r=null;null!==n;)null!==n.alternate&&(r=n),n=n.sibling;null===r?t||null===e.tail?e.tail=null:e.tail.sibling=null:r.sibling=null}}function ns(e){var t=null!==e.alternate&&e.alternate.child===e.child,n=0,r=0;if(t)for(var l=e.child;null!==l;)n|=l.lanes|l.childLanes,r|=65011712&l.subtreeFlags,r|=65011712&l.flags,l.return=e,l=l.sibling;else for(l=e.child;null!==l;)n|=l.lanes|l.childLanes,r|=l.subtreeFlags,r|=l.flags,l.return=e,l=l.sibling;return e.subtreeFlags|=r,e.childLanes=n,t}function rs(e,t,n){var r=t.pendingProps;switch(nl(t),t.tag){case 31:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:case 1:return ns(t),null;case 3:return n=t.stateNode,r=null,null!==e&&(r=e.memoizedState.cache),t.memoizedState.cache!==r&&(t.flags|=2048),xl(Ol),Q(),n.pendingContext&&(n.context=n.pendingContext,n.pendingContext=null),null!==e&&null!==e.child||(fl(t)?Xo(t):null===e||e.memoizedState.isDehydrated&&0===(256&t.flags)||(t.flags|=1024,hl())),ns(t),null;case 26:return n=t.memoizedState,null===e?(Xo(t),null!==n?(ns(t),Zo(t,n)):(ns(t),t.flags&=-16777217)):n?n!==e.memoizedState?(Xo(t),ns(t),Zo(t,n)):(ns(t),t.flags&=-16777217):(e.memoizedProps!==r&&Xo(t),ns(t),t.flags&=-16777217),null;case 27:G(t),n=V.current;var l=t.type;if(null!==e&&null!=t.stateNode)e.memoizedProps!==r&&Xo(t);else{if(!r){if(null===t.stateNode)throw Error(i(166));return ns(t),null}e=$.current,fl(t)?cl(t):(e=xd(l,r,n),t.stateNode=e,Xo(t))}return ns(t),null;case 5:if(G(t),n=t.type,null!==e&&null!=t.stateNode)e.memoizedProps!==r&&Xo(t);else{if(!r){if(null===t.stateNode)throw Error(i(166));return ns(t),null}if(e=$.current,fl(t))cl(t);else{switch(l=rd(V.current),e){case 1:e=l.createElementNS("http://www.w3.org/2000/svg",n);break;case 2:e=l.createElementNS("http://www.w3.org/1998/Math/MathML",n);break;default:switch(n){case"svg":e=l.createElementNS("http://www.w3.org/2000/svg",n);break;case"math":e=l.createElementNS("http://www.w3.org/1998/Math/MathML",n);break;case"script":(e=l.createElement("div")).innerHTML="