diff --git a/.claude/settings.json b/.claude/settings.json index 77b80d2..8227578 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -2,7 +2,19 @@ "permissions": { "allow": [ "Bash(npm install:*)", - "Bash(go build:*)" + "Bash(go build:*)", + "Bash(npx svelte-check:*)", + "Bash(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:8090/api/settings)", + "Bash(npm run:*)", + "Bash(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:8090/)", + "Bash(go vet:*)", + "Bash(git checkout:*)", + "Bash(git stash:*)", + "Bash(echo \"EXIT: $?\")" + ], + "additionalDirectories": [ + "C:\\Users\\Alexei\\Documents\\docker-watcher\\internal", + "C:\\Users\\Alexei\\Documents\\docker-watcher\\web\\src\\routes\\projects\\[id]\\volumes\\[volId]" ] } } diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..dc6e444 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,10 @@ +# Docker Watcher + +## Dev Server + +Start/restart with: `./scripts/dev-server.sh` + +- Runs on port **8090** (avoids 8080 conflict with other local services) +- Auto-generates `ENCRYPTION_KEY` if not set +- Default login: `admin` / `admin123` +- Override port: `LISTEN_ADDR=:9000 ./scripts/dev-server.sh` diff --git a/PLAN.md b/PLAN.md deleted file mode 100644 index 836fc8e..0000000 --- a/PLAN.md +++ /dev/null @@ -1,512 +0,0 @@ -# Docker Watcher — Implementation Plan - -## Overview - -A self-hosted tool that automates Docker container deployment with Nginx Proxy Manager integration. Detects new images from Gitea/GitHub registries, deploys containers, and configures reverse proxy routing — all from a web dashboard. Supports multiple simultaneous versions of the same project. DNS is handled by a Cloudflare wildcard record (`*.dolgolyov-family.by`) — no per-project DNS management needed. - -## Architecture - -```text -Gitea CI → pushes image → Registry - │ ↓ - │ Docker Watcher (Go) - │ ├── Secret webhook URL (instant) - │ └── Registry poller (fallback) - │ ↓ - └── or: POST /api/webhook/ - with {"image": "registry/org/app:tag"} - ↓ - Known project? ──────────────────┐ - ↓ yes ↓ no - Match tag → stage Auto-create project - ↓ with defaults from - auto_deploy? image inspection - ↓ yes ↓ no (EXPOSE, labels) - Deploy now Notify, wait ↓ - ↓ for UI trigger Deploy with defaults - ↓ ↓ - Pull image - Start new container on shared network - (old container stays if multi-instance) - ↓ - NPM API: create proxy host (if first deploy for this subdomain) - (DNS already handled by Cloudflare wildcard *.domain) - ↓ - Health check - → success: done, notify - → failure: remove new container, alert -``` - -## Decisions - -| Decision | Choice | Rationale | -|----------|--------|-----------| -| Language | Go | Single binary, excellent Docker SDK, low resource usage | -| Web UI | SvelteKit (embedded in Go binary) | User's existing stack, lightweight | -| Reverse proxy | Nginx Proxy Manager | Already deployed, API available | -| DNS | Cloudflare wildcard `*.{domain}` | One-time setup, all subdomains auto-resolve | -| Routing | Subdomain-based | No sub-path issues with SPAs | -| Image detection | Secret webhook URL + polling | Webhook for speed, polling as fallback | -| Config storage | SQLite (YAML for initial seed only) | Editable via UI, no manual file editing | -| Credentials | Encrypted in SQLite (AES-256) | Single ENCRYPTION_KEY env var | -| Webhook auth | Secret UUID in URL | No tokens needed, simple CI integration | -| Multi-instance | Yes | Multiple tags of same project can run simultaneously | -| Deployment target | Same TrueNAS host | Docker socket mounted | - -## Subdomain Convention - -| Type | Pattern | Example | -|------|---------|---------| -| Dev (default) | `stage-dev-{project}.{domain}` | `stage-dev-web-app-launcher.dolgolyov-family.by` | -| Dev (specific tag) | `stage-dev-{project}-{tag}.{domain}` | `stage-dev-web-app-launcher-abc123.dolgolyov-family.by` | -| Release (default) | `stage-rel-{project}.{domain}` | `stage-rel-web-app-launcher.dolgolyov-family.by` | -| Release (specific tag) | `stage-rel-{project}-{tag}.{domain}` | `stage-rel-web-app-launcher-v1-2-0.dolgolyov-family.by` | -| Production | `{custom}.{domain}` | `launcher.dolgolyov-family.by` | - -Tags are sanitized for DNS: dots → dashes, lowercase, truncated to fit DNS limits. - -## Configuration - -### First Launch - -```text -YAML seed file exists? → import into SQLite → done -No YAML? → empty state, configure everything via UI -``` - -After import, all configuration lives in SQLite and is managed via the Web UI. -YAML is never read again unless user clicks "Re-import config" or "Export config". - -### Seed Config Format (optional) - -```yaml -global: - domain: dolgolyov-family.by - server_ip: 93.84.96.191 - network: staging-net - subdomain_pattern: "stage-{stage}-{project}" - notification_url: https://notify.dolgolyov-family.by/webhook - npm: - url: http://npm:81 - email: docker-watcher@dolgolyov-family.by - password: "npm-password-here" -registries: - gitea: - url: https://git.dolgolyov-family.by - type: gitea - token: "gitea-token-here" - -projects: - web-app-launcher: - registry: gitea - image: git.dolgolyov-family.by/alexei/web-app-launcher - port: 3000 - healthcheck: /api/health - env: - NODE_ENV: production - stages: - dev: - tag_pattern: "dev-*" - auto_deploy: true - max_instances: 5 - rel: - tag_pattern: "v*" - auto_deploy: false - max_instances: 2 - prod: - tag_pattern: "v*" - auto_deploy: false - confirm: true - promote_from: rel - max_instances: 2 - subdomain: launcher -``` - -## Web UI Sections - -### Dashboard - -Overview of all projects with their running instances: -- Project name, running instance count, latest activity -- Quick status indicators (healthy / stopped / failing) -- "Quick Deploy" button for ad-hoc image deployment - -### Project Detail - -Per-project view with stages and instances: -- Each stage shows all running instances with: tag, status, URL, uptime -- Controls per instance: Stop, Start, Restart, Remove -- "Deploy new version" dropdown — lists available tags from registry -- Deploy history log - -### Quick Deploy - -For deploying images not yet configured as projects: -1. Paste image URL (e.g., `git.dolgolyov-family.by/alexei/my-app:dev-abc123`) -2. Docker Watcher pulls and inspects image (EXPOSE port, HEALTHCHECK, labels) -3. Pre-fills form with sensible defaults (project name, port, stage, subdomain) -4. User reviews, tweaks, clicks "Deploy" -5. Project is auto-created in the DB for future use - -### Settings - -- **Registries** — add/edit/delete registries, test connection -- **Credentials** — NPM, registry tokens (encrypted, shown as `••••••••`) -- **Global** — domain, server IP, Docker network, subdomain pattern, polling interval -- **Notifications** — webhook URL -- **Webhook URL** — shows the secret deploy URL, "Regenerate" button - -### Projects Config - -- Add / edit / delete projects via UI -- Configure image, port, healthcheck, env vars, volumes per project -- Add / remove stages, set tag patterns, auto-deploy, subdomain overrides, max instances - -## Project Structure - -```text -docker-watcher/ -├── cmd/ -│ └── server/ -│ └── main.go # Entry point -├── internal/ -│ ├── config/ -│ │ ├── config.go # YAML seed parsing -│ │ └── config_test.go -│ ├── docker/ -│ │ ├── client.go # Docker Engine API wrapper -│ │ ├── container.go # Create, start, stop, remove, inspect -│ │ └── client_test.go -│ ├── npm/ -│ │ ├── client.go # NPM API client (auth, CRUD proxy hosts) -│ │ └── client_test.go -│ ├── registry/ -│ │ ├── registry.go # Interface -│ │ ├── gitea.go # Gitea registry implementation -│ │ ├── github.go # GitHub Container Registry (future) -│ │ ├── poller.go # Periodic tag polling -│ │ └── registry_test.go -│ ├── deployer/ -│ │ ├── deployer.go # Orchestrates full deploy flow -│ │ ├── rollback.go # Rollback on failure -│ │ └── deployer_test.go -│ ├── health/ -│ │ ├── checker.go # HTTP health checks with retries -│ │ └── checker_test.go -│ ├── notify/ -│ │ ├── notifier.go # Webhook notifications -│ │ └── notifier_test.go -│ ├── webhook/ -│ │ ├── handler.go # Secret URL webhook receiver -│ │ └── handler_test.go -│ ├── api/ -│ │ ├── router.go # HTTP API for web UI -│ │ ├── projects.go # Project CRUD endpoints -│ │ ├── registries.go # Registry CRUD endpoints -│ │ ├── settings.go # Global settings endpoints -│ │ ├── instances.go # Instance start/stop/restart/remove -│ │ ├── deploys.go # Deploy + quick deploy endpoints -│ │ └── middleware.go # Auth, logging, CORS -│ ├── store/ -│ │ ├── store.go # SQLite schema, migrations -│ │ ├── projects.go # Project queries -│ │ ├── instances.go # Instance queries -│ │ ├── registries.go # Registry queries -│ │ ├── settings.go # Settings queries -│ │ ├── deploys.go # Deploy history queries -│ │ └── store_test.go -│ └── crypto/ -│ └── crypto.go # AES-256 encrypt/decrypt for credentials -├── web/ # SvelteKit frontend -│ ├── src/ -│ │ ├── routes/ -│ │ │ ├── +page.svelte # Dashboard -│ │ │ ├── projects/ -│ │ │ │ ├── +page.svelte # Projects list + add -│ │ │ │ └── [id]/ -│ │ │ │ └── +page.svelte # Project detail + instances -│ │ │ ├── deploy/ -│ │ │ │ └── +page.svelte # Quick deploy -│ │ │ └── settings/ -│ │ │ ├── +page.svelte # Global settings -│ │ │ ├── registries/ -│ │ │ │ └── +page.svelte -│ │ │ └── credentials/ -│ │ │ └── +page.svelte -│ │ ├── lib/ -│ │ │ ├── api.ts # API client -│ │ │ ├── types.ts # Shared types -│ │ │ └── components/ # Reusable UI components -│ │ └── app.html -│ ├── package.json -│ ├── svelte.config.js -│ └── vite.config.ts -├── docker-watcher.example.yaml # Example seed config -├── Dockerfile -├── docker-compose.yml -├── go.mod -└── go.sum -``` - -## Implementation Phases - -### Phase 1: Foundation ✅ - -Core infrastructure — store, config import, Docker client, NPM client. - -1. **Go project init** — go.mod, directory structure, dependencies -2. **SQLite store** — schema, migrations, CRUD for projects/registries/settings/instances/deploys -3. **Crypto** — AES-256 encrypt/decrypt for credential storage -4. **Config seed loader** — parse YAML, import into SQLite on first launch -5. **Docker client** — connect to socket, pull image, inspect image, list/start/stop/remove containers, manage networks -6. **NPM client** — authenticate (JWT), create/update/delete proxy hosts, list existing hosts - -### Phase 2: Detection & Deployment (Registry & Poller ✅, Webhook ✅, Deployer ✅) - -The core loop — detecting new images and deploying them. - -8. **Registry client** ✅ — Gitea registry API: list tags for an image, detect new tags -9. **Poller** ✅ — periodic check for new tags matching configured patterns -10. **Secret webhook handler** ✅ — UUID-based URL, receives image push notifications, auto-creates unknown projects -11. **Deployer** ✅ — orchestrate: pull → start container → NPM proxy → health check -12. **Multi-instance support** ✅ — multiple versions per project/stage, tag-based subdomains, max_instances limit -13. **Health checker** ✅ — HTTP GET with retries and timeout (3 retries, 5s interval, 10s timeout) -14. **Rollback** ✅ — on health check failure: remove new container, clean up NPM, alert -15. **Notifications** ✅ — send webhook on deploy success/failure (fire-and-forget) - -### Phase 3: Web UI - -Full dashboard for visibility, manual control, and configuration. - -16. **API layer** — REST endpoints for all CRUD operations + deploy/control actions -17. **SvelteKit dashboard** — project overview, instance status, quick status indicators -18. **Project detail view** — stages, instances, controls (stop/start/restart/remove), deploy history -19. **Quick Deploy page** — paste image URL, auto-inspect, pre-fill form, one-click deploy -20. **Settings pages** — registries, credentials, global settings, webhook URL management -21. **Project config pages** — add/edit/delete projects and stages via UI -22. **Embed in Go** ✅ — build SvelteKit to static, embed with `go:embed`, serve from Go -23. **Real-time updates** ✅ — SSE for deploy progress and instance status changes - -### Phase 4: Volumes & Environment (Phase 13) -- COMPLETED - -Persistent storage and app-specific configuration for deployed containers. - -24. **Environment variables per project** — key/value pairs stored in SQLite, sensitive values encrypted -25. **Per-stage env overrides** — e.g., `NODE_ENV=development` for dev, `NODE_ENV=production` for prod -26. **Volume mounts per project** — configurable source/target paths with shared/isolated modes -27. **Shared volumes** — all instances of a project mount the same host path (for stateless apps or shared uploads) -28. **Isolated volumes** — each instance gets its own subdirectory: `{source}/{stage}-{tag}/` → `{target}` (for stateful apps with local DBs/files) -29. **UI for volumes & env** — project settings page with key/value editor, volume list, shared/isolated toggle, per-stage override support - -#### Phase 13 Handoff Notes - -- New tables: `stage_env` (id, stage_id, key, value, encrypted, timestamps), `volumes` (id, project_id, source, target, mode, timestamps) -- `stage_env` has UNIQUE(stage_id, key) constraint to prevent duplicate keys per stage -- Volume mode is either "shared" or "isolated"; default is "shared" -- Encrypted env values are encrypted with `crypto.Encrypt` before storage and decrypted at deploy time -- API masks encrypted env values as "••••••••" in responses -- Env merge order in deployer: project-level JSON `env` field parsed first, then stage-level `stage_env` records overlay (stage wins on key conflict) -- `computeVolumeMounts` appends `/{stage}-{tag}/` to source for isolated volumes -- Docker `ContainerConfig` now has `Mounts []mount.Mount` field, passed to `HostConfig.Mounts` -- Both `executeDeploy` and `blueGreenDeploy` updated to use `mergeEnvVars` and `computeVolumeMounts` -- API routes: GET/POST `/api/projects/{id}/stages/{stage}/env`, PUT/DELETE `.../env/{envId}`, GET/POST `/api/projects/{id}/volumes`, PUT/DELETE `.../volumes/{volId}` -- Frontend pages: `/projects/[id]/env` (per-stage env editor with inherited/overridden indicators), `/projects/[id]/volumes` (volume editor with shared/isolated toggle) -- Project detail page now has navigation links to env and volumes pages - -Volume config per project: -```yaml -env: - NODE_ENV: production - DATABASE_URL: postgres://db:5432/myapp # shared external DB - SECRET_KEY: "..." # encrypted in SQLite -volumes: - - source: /data/my-app/uploads - target: /app/uploads - mode: shared # all instances share this path - - source: /data/my-app/data - target: /app/data - mode: isolated # auto-appends /{stage}-{tag}/ to source -``` - -Stage-level env overrides: -```yaml -stages: - dev: - env: - NODE_ENV: development # overrides project-level - DATABASE_URL: postgres://db:5432/myapp_dev - prod: - env: - NODE_ENV: production # uses project-level default -``` - -### Phase 5: Hardening (Phase 12) -- COMPLETED - -30. **Blue-green deploys** -- start new, health check, swap, stop old (zero downtime) -31. **Promote flow** -- enforce `promote_from` for production deploys -32. **Auth on dashboard** -- two modes, configurable via settings: - - **Local auth** -- username/password stored in SQLite (bcrypt hashed), JWT session tokens - - **OAuth2 / OpenID Connect** -- integration with any OIDC provider (configurable client ID/secret/discovery URL) -33. **Graceful shutdown** -- drain in-progress deploys on SIGTERM, close DB, stop poller -34. **Structured logging** -- JSON logs via `log/slog` with deploy context -35. **Config export** -- download current SQLite state as YAML -36. **Dockerfile** -- multi-stage build (Node.js 20 + Go 1.23 build, alpine runtime) -37. **docker-compose.yml** -- production-ready compose with volumes, network, env -38. **Auth middleware** -- protects all /api/* routes except webhook and auth endpoints -39. **Auth settings UI** -- settings page to toggle auth mode, configure OIDC, manage users -40. **Login page** -- username/password form with OIDC SSO option -41. **Final wiring** -- all services properly initialized and shut down in main.go - -#### Phase 12 Handoff Notes - -- Auth: `auth.LocalAuth` handles JWT generation/validation, `auth.OIDCProvider` handles OIDC flow -- Default admin user created on first launch (ADMIN_PASSWORD env var, default: "admin") -- JWT secret derived from ENCRYPTION_KEY via HMAC-SHA256 -- Blue-green: triggered automatically when stage has `max_instances=1`; otherwise standard deploy -- Promote: validated in `TriggerDeploy` before deploy begins -- Graceful shutdown: `deployer.Drain()` waits for in-progress deploys; poller stopped; HTTP server drained; DB closed -- Structured logging: all API, deployer, and main.go use `log/slog` JSON handler -- New dependencies: `github.com/golang-jwt/jwt/v5`, `golang.org/x/crypto/bcrypt`, `github.com/coreos/go-oidc/v3`, `golang.org/x/oauth2` -- New tables: `users` (id, username, password_hash, email, role, timestamps), `auth_settings` (single-row: auth_mode, OIDC config) -- Auth middleware applied to all `/api/*` routes except `/api/auth/login`, `/api/auth/oidc/*`, `/api/webhook/*`, `/api/config/export` -- Frontend: token stored in `localStorage`, sent as `Authorization: Bearer` header -- Run `go mod tidy` after checkout to resolve transitive dependencies - -## Key Dependencies (Go) - -- `github.com/docker/docker` — Docker Engine API -- `github.com/go-chi/chi` or `net/http` — HTTP routing -- `gopkg.in/yaml.v3` — YAML seed config -- `modernc.org/sqlite` — SQLite (CGo-free) -- `github.com/robfig/cron` — Polling scheduler -- `github.com/google/uuid` — Webhook secret URL generation - -## Docker Compose (self-deployment) - -```yaml -services: - docker-watcher: - image: docker-watcher:latest - container_name: docker-watcher - restart: unless-stopped - ports: - - "8080:8080" - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ./docker-watcher.yaml:/app/seed.yaml:ro # optional, first launch only - - ./data:/app/data # SQLite DB - environment: - - ENCRYPTION_KEY=${ENCRYPTION_KEY} # protects all credentials in DB - networks: - - staging-net - -networks: - staging-net: - external: true -``` - -## API Endpoints - -```text -# Projects -GET /api/projects — list all projects with instance counts -POST /api/projects — create project -GET /api/projects/:id — project detail + stages + instances -PUT /api/projects/:id — update project config -DELETE /api/projects/:id — delete project + all instances - -# Stages -POST /api/projects/:id/stages — add stage to project -PUT /api/projects/:id/stages/:stage — update stage config -DELETE /api/projects/:id/stages/:stage — delete stage + its instances - -# Stage Env Overrides -GET /api/projects/:id/stages/:stage/env — list stage env vars (secrets masked) -POST /api/projects/:id/stages/:stage/env — create stage env var -PUT /api/projects/:id/stages/:stage/env/:envId — update stage env var -DELETE /api/projects/:id/stages/:stage/env/:envId — delete stage env var - -# Project Volumes -GET /api/projects/:id/volumes — list project volumes -POST /api/projects/:id/volumes — create project volume -PUT /api/projects/:id/volumes/:volId — update project volume -DELETE /api/projects/:id/volumes/:volId — delete project volume - -# Instances (running containers) -GET /api/projects/:id/stages/:stage/instances — list instances for stage -POST /api/projects/:id/stages/:stage/instances — deploy new instance (pick tag) -DELETE /api/projects/:id/stages/:stage/instances/:iid — remove instance (container + NPM proxy) -POST /api/projects/:id/stages/:stage/instances/:iid/stop — stop container -POST /api/projects/:id/stages/:stage/instances/:iid/start — start stopped container -POST /api/projects/:id/stages/:stage/instances/:iid/restart — restart container - -# Quick Deploy -POST /api/deploy/inspect — pull + inspect image, return defaults -POST /api/deploy/quick — create project + deploy in one step - -# Registry -GET /api/registries — list registries -POST /api/registries — add registry -PUT /api/registries/:id — update registry -DELETE /api/registries/:id — delete registry -POST /api/registries/:id/test — test connection -GET /api/registries/:id/tags/:image — list available tags - -# Settings -GET /api/settings — get global settings -PUT /api/settings — update global settings -GET /api/settings/webhook-url — get secret webhook URL -POST /api/settings/webhook-url/regenerate — regenerate webhook URL - -# Deploy history -GET /api/deploys — recent deploys across all projects -GET /api/deploys/:id/logs — deploy log stream (SSE) - -# Webhook (secret URL — no auth needed) -POST /api/webhook/:secret-uuid — receive image push notification -``` - -## User Workflows - -### Auto-Deploy (zero effort) - -```text -Push code → CI builds → pushes tag → Docker Watcher detects → -auto_deploy: true → deployed → notification with URL -``` - -### Manual Deploy via UI (one click) - -```text -Open dashboard → project → stage → "Deploy new version" → -pick tag from dropdown → click Deploy -``` - -### Quick Deploy (new project, paste image URL) - -```text -Open dashboard → "Quick Deploy" → paste image URL → -review auto-filled defaults → click Deploy → -project auto-created + deployed -``` - -### Deploy via CI Webhook (zero effort after CI setup) - -```text -# In .gitea/workflows/build.yml -- name: Notify Docker Watcher - run: | - curl -X POST https://watcher.dolgolyov-family.by/api/webhook/d8f2a1e9-... \ - -d '{"image": "git.dolgolyov-family.by/alexei/my-app:dev-${{ github.sha }}"}' -``` - -Known project → deploys per stage config. -Unknown project → auto-creates with defaults from image inspection, deploys. - -### Production Deploy (two clicks) - -```text -Open dashboard → project → prod stage → "Deploy new version" → -dropdown shows only tags running in "rel" stage (promote_from) → -pick tag → confirmation dialog → Deploy -``` diff --git a/docker-watcher b/docker-watcher new file mode 100644 index 0000000..a38faf1 Binary files /dev/null and b/docker-watcher differ diff --git a/docker-watcher.exe b/docker-watcher.exe new file mode 100644 index 0000000..481d0a2 Binary files /dev/null and b/docker-watcher.exe differ diff --git a/docs/docker-diagnostic-hints.md b/docs/docker-diagnostic-hints.md new file mode 100644 index 0000000..958c022 --- /dev/null +++ b/docs/docker-diagnostic-hints.md @@ -0,0 +1,101 @@ +## Feature: Docker Diagnostic Hints on Disconnection + +**Problem:** When Docker is unreachable, the UI shows a generic "Docker disconnected" label with no actionable guidance. Users (especially on Windows/macOS where Docker Desktop must be running) have no idea what's wrong or how to fix it. + +**Goal:** Enrich the health-check response with a structured diagnostic object so the frontend can display platform-aware, actionable hints. + +--- + +### Backend Changes + +**1. Enhance `GET /api/health` response** ([health.go](../internal/api/health.go)) + +Currently returns `{ "docker": true|false }`. Change to: + +```json +{ + "docker": { + "connected": false, + "error": "dial unix /var/run/docker.sock: connect: no such file or directory", + "category": "socket_not_found", + "hints": [ + "Docker Desktop does not appear to be running.", + "Start Docker Desktop and wait for it to finish initializing.", + "If using a custom socket path, check DOCKER_HOST env variable." + ], + "platform": "windows", + "checked_at": "2026-03-30T12:34:56Z" + } +} +``` + +**2. Create a Docker diagnostics module** (new file, e.g. `internal/docker/diagnostics.go`) + +Classify the Ping error into a diagnostic category and generate platform-specific hints. Follow the pattern already established in [hints.go](../internal/proxy/hints.go) for proxy validation. + +Error categories to handle: + +| Category | Error signature | Windows hints | Linux hints | macOS hints | +|---|---|---|---|---| +| `socket_not_found` | `no such file or directory`, `The system cannot find the file specified` | Docker Desktop not running; start it from Start Menu or system tray | Docker daemon not running; `sudo systemctl start docker` | Docker Desktop not running; start from Applications or `open -a Docker` | +| `connection_refused` | `connection refused` | Docker Desktop is starting up — wait ~30s and retry | Docker daemon is starting; `sudo systemctl status docker` | Docker Desktop is starting; check the whale icon in the menu bar | +| `permission_denied` | `permission denied` | Run the application as Administrator, or add your user to the `docker-users` group | Add your user to the `docker` group: `sudo usermod -aG docker $USER` then re-login | Check Docker Desktop settings -> Resources -> File Sharing | +| `timeout` | `context deadline exceeded`, `i/o timeout` | Docker Desktop may be overloaded or hanging — restart it | Docker daemon may be overloaded; check `journalctl -u docker` | Docker Desktop may be unresponsive; restart from menu bar | +| `tls_error` | `tls:`, `certificate` | Check Docker TLS cert configuration and `DOCKER_TLS_VERIFY` | Verify certs in `~/.docker/` match daemon config | Check `~/.docker/` TLS configuration | +| `unknown` | (fallback) | Show raw error with link to Docker Desktop troubleshooting docs | Show raw error with `dockerd` docs link | Show raw error with Docker Desktop docs link | + +Detect the platform via `runtime.GOOS` in the diagnostics module (the binary runs on the host, so this is accurate). + +**3. Expose `runtime.GOOS` once** in diagnostics, don't scatter it through handlers. + +**4. Preserve backward compat** — if any external consumer depends on the old `"docker": bool` shape, consider a migration path or version the health endpoint. Internal-only API can break freely. + +--- + +### Frontend Changes + +**5. Update the API type** ([api.ts](../web/src/lib/api.ts)) + +```typescript +interface DockerHealth { + connected: boolean; + error?: string; + category?: string; + hints?: string[]; + platform?: string; + checked_at?: string; +} + +export function getHealth(): Promise<{ docker: DockerHealth }> { + return get<{ docker: DockerHealth }>('/api/health'); +} +``` + +**6. Enhance the health indicator** ([+layout.svelte](../web/src/routes/+layout.svelte)) + +When `dockerConnected === false`: +- Show a clickable/expandable area (tooltip, popover, or collapsible panel) below the red dot. +- Display the `hints` array as a bulleted list. +- Optionally show the raw `error` in a `
` collapse for advanced users. +- Show `checked_at` as relative time ("last checked 15s ago"). +- Add a manual "Retry now" button that triggers an immediate health check instead of waiting for the 30s poll. + +**7. Add i18n keys** ([en.json](../web/src/lib/i18n/en.json), [ru.json](../web/src/lib/i18n/ru.json)) + +Add keys for each hint category so hints can be translated. The backend should return `category` + `platform` identifiers; the frontend can use them to look up localized hint text instead of displaying raw English strings from the backend. This keeps i18n centralized in the frontend. + +--- + +### Architecture Notes + +- The proxy validator ([validator.go](../internal/proxy/validator.go), [hints.go](../internal/proxy/hints.go)) already implements a similar pattern: classifying errors by substring match and returning human-readable hints. Reuse that approach for consistency. +- Keep diagnostics pure — a function that takes an `error` and `runtime.GOOS` and returns `(category string, hints []string)`. No side effects, easy to unit-test. +- Consider caching the diagnostic result for a few seconds to avoid spamming Docker if the frontend retries rapidly. + +--- + +### Testing + +- Unit-test the diagnostics function with synthetic errors for each category x platform combination. +- Integration-test the health endpoint with a mock Docker client that returns each error type. +- Frontend: test that the hint UI renders correctly for each category and collapses/expands properly. diff --git a/internal/api/dns.go b/internal/api/dns.go index cd2d729..1432010 100644 --- a/internal/api/dns.go +++ b/internal/api/dns.go @@ -208,8 +208,8 @@ func (s *Server) buildConsumerNameMap() map[string]string { // getOrCreateDNSProvider returns the server's DNS provider, or creates a temporary one from settings. func (s *Server) getOrCreateDNSProvider(settings store.Settings) dns.Provider { - if s.dnsProvider != nil { - return s.dnsProvider + if p := s.getDNSProviderLocked(); p != nil { + return p } if settings.WildcardDNS || settings.DNSProvider == "" || settings.CloudflareAPIToken == "" { diff --git a/internal/api/router.go b/internal/api/router.go index cc63817..b01f57e 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -3,6 +3,7 @@ package api import ( "context" "log/slog" + "sync" "github.com/go-chi/chi/v5" @@ -36,7 +37,8 @@ type Server struct { staleScanner *stale.Scanner proxyManager *proxy.Manager - dnsProvider dns.Provider + dnsProviderMu sync.RWMutex + dnsProvider dns.Provider onDNSProviderChanged DNSProviderChangedFunc } @@ -86,9 +88,18 @@ func (s *Server) SetProxyManager(pm *proxy.Manager) { // SetDNSProvider sets the current DNS provider on the server. func (s *Server) SetDNSProvider(provider dns.Provider) { + s.dnsProviderMu.Lock() + defer s.dnsProviderMu.Unlock() s.dnsProvider = provider } +// getDNSProviderLocked returns the current DNS provider under read lock. +func (s *Server) getDNSProviderLocked() dns.Provider { + s.dnsProviderMu.RLock() + defer s.dnsProviderMu.RUnlock() + return s.dnsProvider +} + // SetDNSProviderChangedCallback sets the callback for when DNS settings change. func (s *Server) SetDNSProviderChangedCallback(fn DNSProviderChangedFunc) { s.onDNSProviderChanged = fn @@ -272,7 +283,7 @@ func (s *Server) Router() chi.Router { // DNS management endpoints. r.Post("/settings/dns/test", s.testDNSConnection) - r.Get("/settings/dns/zones", s.listDNSZones) + r.Post("/settings/dns/zones", s.listDNSZones) r.Get("/dns/records", s.listDNSRecords) r.Post("/dns/sync", s.syncDNSRecords) r.Delete("/dns/records/{fqdn}", s.deleteDNSRecord) diff --git a/internal/api/settings.go b/internal/api/settings.go index 4a93d78..2541660 100644 --- a/internal/api/settings.go +++ b/internal/api/settings.go @@ -176,7 +176,8 @@ func (s *Server) updateSettings(w http.ResponseWriter, r *http.Request) { existing.CloudflareZoneID != updated.CloudflareZoneID || (req.CloudflareAPIToken != "" && req.CloudflareAPIToken != "unchanged") if dnsChanged { - go s.handleDNSSettingsChange(existing, updated) + oldProvider := s.getDNSProviderLocked() + go s.handleDNSSettingsChange(oldProvider, existing, updated) } respondJSON(w, http.StatusOK, map[string]string{"status": "updated"}) @@ -374,17 +375,17 @@ func (s *Server) reapplySSLToAllProxies(settings store.Settings) { // handleDNSSettingsChange reacts to DNS configuration changes: // - If switching to wildcard mode: remove all managed DNS records from the provider. // - If switching provider or credentials: remove old records, create new provider, re-sync. -func (s *Server) handleDNSSettingsChange(oldSettings, newSettings store.Settings) { +func (s *Server) handleDNSSettingsChange(oldProvider dns.Provider, oldSettings, newSettings store.Settings) { ctx := context.Background() // Step 1: If there was an old provider, remove all managed DNS records from it. - if !oldSettings.WildcardDNS && oldSettings.DNSProvider != "" && s.dnsProvider != nil { + if !oldSettings.WildcardDNS && oldSettings.DNSProvider != "" && oldProvider != nil { records, err := s.store.ListDNSRecords() if err != nil { slog.Error("dns settings change: list records for cleanup", "error", err) } else { for _, rec := range records { - if err := s.dnsProvider.DeleteRecord(ctx, rec.FQDN); err != nil { + if err := oldProvider.DeleteRecord(ctx, rec.FQDN); err != nil { slog.Warn("dns settings change: delete old record", "fqdn", rec.FQDN, "error", err) } if err := s.store.DeleteDNSRecord(rec.FQDN); err != nil { @@ -420,7 +421,7 @@ func (s *Server) handleDNSSettingsChange(oldSettings, newSettings store.Settings } // Step 3: Update the server's DNS provider and notify dependents. - s.dnsProvider = newProvider + s.SetDNSProvider(newProvider) if s.onDNSProviderChanged != nil { s.onDNSProviderChanged(newProvider) } @@ -488,10 +489,19 @@ func (s *Server) testDNSConnection(w http.ResponseWriter, r *http.Request) { }) } -// listDNSZones handles GET /api/settings/dns/zones. +// dnsZonesRequest is the expected JSON body for listing DNS zones. +type dnsZonesRequest struct { + Token string `json:"token"` +} + +// listDNSZones handles POST /api/settings/dns/zones. func (s *Server) listDNSZones(w http.ResponseWriter, r *http.Request) { - token := r.URL.Query().Get("token") - // If no token in query, use stored one. + var req dnsZonesRequest + if !decodeJSON(w, r, &req) { + return + } + token := req.Token + // If no token in body, use stored one. if token == "" { settings, err := s.store.GetSettings() if err != nil { diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index 7fb9bd8..e6cd9f7 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -33,6 +33,7 @@ type Deployer struct { notifier *notify.Notifier eventBus EventPublisher encKey [32]byte + dnsMu sync.RWMutex dns dns.Provider // nil when wildcard DNS is active // Graceful shutdown: tracks in-progress deploys. @@ -69,9 +70,18 @@ func New( // SetDNSProvider sets the DNS provider for managing DNS records during deployments. // Pass nil to disable DNS management (wildcard DNS mode). func (d *Deployer) SetDNSProvider(provider dns.Provider) { + d.dnsMu.Lock() + defer d.dnsMu.Unlock() d.dns = provider } +// getDNS returns the current DNS provider under read lock. +func (d *Deployer) getDNS() dns.Provider { + d.dnsMu.RLock() + defer d.dnsMu.RUnlock() + return d.dns +} + // Drain waits for all in-progress deploys to complete. Call this during graceful shutdown. func (d *Deployer) Drain() { d.shuttingDown.Store(true) @@ -744,7 +754,8 @@ func (d *Deployer) publishInstanceStatus(instanceID, projectID, stageID, status // ensureDNS creates or updates a DNS record for the given FQDN. Best-effort: logs warnings on failure. func (d *Deployer) ensureDNS(ctx context.Context, fqdn, consumerType, consumerID, deployID string) { - if d.dns == nil { + dnsProvider := d.getDNS() + if dnsProvider == nil { return } settings, err := d.store.GetSettings() @@ -757,7 +768,7 @@ func (d *Deployer) ensureDNS(ctx context.Context, fqdn, consumerType, consumerID return } - recordID, err := d.dns.EnsureRecord(ctx, fqdn, settings.ServerIP) + recordID, err := dnsProvider.EnsureRecord(ctx, fqdn, settings.ServerIP) if err != nil { msg := fmt.Sprintf("DNS: failed to create/update record for %s: %v", fqdn, err) slog.Warn(msg) @@ -789,11 +800,12 @@ func (d *Deployer) ensureDNS(ctx context.Context, fqdn, consumerType, consumerID // removeDNS deletes a DNS record for the given FQDN. Best-effort: logs warnings on failure. func (d *Deployer) removeDNS(ctx context.Context, fqdn, deployID string) { - if d.dns == nil { + dnsProvider := d.getDNS() + if dnsProvider == nil { return } - if err := d.dns.DeleteRecord(ctx, fqdn); err != nil { + if err := dnsProvider.DeleteRecord(ctx, fqdn); err != nil { msg := fmt.Sprintf("DNS: failed to delete record for %s: %v", fqdn, err) slog.Warn(msg) if deployID != "" { diff --git a/internal/proxy/manager.go b/internal/proxy/manager.go index e8c5ff6..ac24615 100644 --- a/internal/proxy/manager.go +++ b/internal/proxy/manager.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "log/slog" + "sync" "github.com/alexei/docker-watcher/internal/dns" "github.com/alexei/docker-watcher/internal/npm" @@ -15,6 +16,7 @@ import ( type Manager struct { store *store.Store npm *npm.Client + dnsMu sync.RWMutex dns dns.Provider // nil when wildcard DNS is active } @@ -28,9 +30,18 @@ func NewManager(st *store.Store, npmClient *npm.Client) *Manager { // SetDNSProvider sets the DNS provider for managing DNS records. func (m *Manager) SetDNSProvider(provider dns.Provider) { + m.dnsMu.Lock() + defer m.dnsMu.Unlock() m.dns = provider } +// getDNS returns the current DNS provider under read lock. +func (m *Manager) getDNS() dns.Provider { + m.dnsMu.RLock() + defer m.dnsMu.RUnlock() + return m.dns +} + // CreateProxyRequest is the input for creating a standalone proxy. type CreateProxyRequest struct { Domain string `json:"domain"` @@ -315,7 +326,8 @@ func (m *Manager) ListAllProxies() ([]ProxyView, error) { // ensureDNS creates or updates a DNS record for a standalone proxy domain. Best-effort. func (m *Manager) ensureDNS(ctx context.Context, domain, proxyID string) { - if m.dns == nil { + dnsProvider := m.getDNS() + if dnsProvider == nil { return } settings, err := m.store.GetSettings() @@ -328,7 +340,7 @@ func (m *Manager) ensureDNS(ctx context.Context, domain, proxyID string) { return } - recordID, err := m.dns.EnsureRecord(ctx, domain, settings.ServerIP) + recordID, err := dnsProvider.EnsureRecord(ctx, domain, settings.ServerIP) if err != nil { slog.Warn("dns: failed to create/update record for standalone proxy", "domain", domain, "error", err) return @@ -350,10 +362,11 @@ func (m *Manager) ensureDNS(ctx context.Context, domain, proxyID string) { // removeDNS deletes a DNS record for a standalone proxy domain. Best-effort. func (m *Manager) removeDNS(ctx context.Context, domain string) { - if m.dns == nil { + dnsProvider := m.getDNS() + if dnsProvider == nil { return } - if err := m.dns.DeleteRecord(ctx, domain); err != nil { + if err := dnsProvider.DeleteRecord(ctx, domain); err != nil { slog.Warn("dns: failed to delete record for standalone proxy", "domain", domain, "error", err) return } diff --git a/scripts/dev-server.sh b/scripts/dev-server.sh new file mode 100644 index 0000000..7ed6100 --- /dev/null +++ b/scripts/dev-server.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# Start (or restart) the Docker Watcher dev server on port 8090. +# Usage: ./scripts/dev-server.sh + +set -euo pipefail + +PORT="${LISTEN_ADDR:-:8090}" +PORT_NUM="${PORT#:}" + +# Kill existing process on the port if any. +PID=$(netstat -aon 2>/dev/null | grep ":${PORT_NUM}.*LISTEN" | awk '{print $5}' | head -1) +if [ -n "$PID" ] && [ "$PID" != "0" ]; then + echo "Stopping existing process on port ${PORT_NUM} (PID ${PID})..." + taskkill //F //PID "$PID" 2>/dev/null || kill "$PID" 2>/dev/null || true + sleep 1 +fi + +# Generate a random encryption key if not set. +export ENCRYPTION_KEY="${ENCRYPTION_KEY:-$(openssl rand -hex 32)}" +export ADMIN_PASSWORD="${ADMIN_PASSWORD:-admin123}" +export LISTEN_ADDR="${PORT}" + +echo "Starting Docker Watcher on http://localhost:${PORT_NUM}" +echo "Login: admin / ${ADMIN_PASSWORD}" +exec go run ./cmd/server diff --git a/server.exe b/server.exe new file mode 100644 index 0000000..90d1028 Binary files /dev/null and b/server.exe differ diff --git a/web/.svelte-kit/ambient.d.ts b/web/.svelte-kit/ambient.d.ts new file mode 100644 index 0000000..3de0b3a --- /dev/null +++ b/web/.svelte-kit/ambient.d.ts @@ -0,0 +1,424 @@ + +// this file is generated — do not edit it + + +/// + +/** + * This module provides access to environment variables that are injected _statically_ into your bundle at build time and are limited to _private_ access. + * + * | | Runtime | Build time | + * | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ | + * | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) | + * | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) | + * + * Static environment variables are [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env` at build time and then statically injected into your bundle at build time, enabling optimisations like dead code elimination. + * + * **_Private_ access:** + * + * - This module cannot be imported into client-side code + * - This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured) + * + * For example, given the following build time environment: + * + * ```env + * ENVIRONMENT=production + * PUBLIC_BASE_URL=http://site.com + * ``` + * + * With the default `publicPrefix` and `privatePrefix`: + * + * ```ts + * import { ENVIRONMENT, PUBLIC_BASE_URL } from '$env/static/private'; + * + * console.log(ENVIRONMENT); // => "production" + * console.log(PUBLIC_BASE_URL); // => throws error during build + * ``` + * + * The above values will be the same _even if_ different values for `ENVIRONMENT` or `PUBLIC_BASE_URL` are set at runtime, as they are statically replaced in your code with their build time values. + */ +declare module '$env/static/private' { + export const ACSetupSvcPort: string; + export const ACSvcPort: string; + export const ALLUSERSPROFILE: string; + export const ANDROID_SDK_HOME: string; + export const APPDATA: string; + export const APPLICATIONINSIGHTS_CONFIGURATION_CONTENT: string; + export const APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL: string; + export const APPLICATION_INSIGHTS_NO_STATSBEAT: string; + export const CHROME_CRASHPAD_PIPE_NAME: string; + export const CLAUDECODE: string; + export const CLAUDE_AGENT_SDK_VERSION: string; + export const CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING: string; + export const CLAUDE_CODE_ENTRYPOINT: string; + export const COLOR: string; + export const COMMONPROGRAMFILES: string; + export const CommonProgramW6432: string; + export const COMPUTERNAME: string; + export const COMSPEC: string; + export const COPILOT_OTEL_ENABLED: string; + export const COPILOT_OTEL_EXPORTER_TYPE: string; + export const COPILOT_OTEL_FILE_EXPORTER_PATH: string; + export const COREPACK_ENABLE_AUTO_PIN: string; + export const CUDA_PATH: string; + export const CUDA_PATH_V10_1: string; + export const CUDA_PATH_V12_0: string; + export const CUDA_PATH_V12_4: string; + export const CUDA_PATH_V13_1: string; + export const CUDA_PATH_V13_2: string; + export const DriverData: string; + export const EDITOR: string; + export const ELECTRON_RUN_AS_NODE: string; + export const EXEPATH: string; + export const FPS_BROWSER_APP_PROFILE_STRING: string; + export const FPS_BROWSER_USER_PROFILE_STRING: string; + export const GIT_EDITOR: string; + export const GOPATH: string; + export const HOME: string; + export const HOMEDRIVE: string; + export const HOMEPATH: string; + export const INIT_CWD: string; + export const LOCALAPPDATA: string; + export const LOGONSERVER: string; + export const MSYSTEM: string; + export const NODE: string; + export const NoDefaultCurrentDirectoryInExePath: string; + export const NODE_ENV: string; + export const NODE_UNC_HOST_ALLOWLIST: string; + export const npm_command: string; + export const npm_config_cache: string; + export const npm_config_globalconfig: string; + export const npm_config_global_prefix: string; + export const npm_config_init_module: string; + export const npm_config_local_prefix: string; + export const npm_config_metrics_registry: string; + export const npm_config_node_gyp: string; + export const npm_config_noproxy: string; + export const npm_config_prefix: string; + export const npm_config_userconfig: string; + export const npm_config_user_agent: string; + export const npm_execpath: string; + export const npm_lifecycle_event: string; + export const npm_lifecycle_script: string; + export const npm_node_execpath: string; + export const npm_package_json: string; + export const npm_package_name: string; + export const npm_package_version: string; + export const NUMBER_OF_PROCESSORS: string; + export const NVCUDASAMPLES10_1_ROOT: string; + export const NVCUDASAMPLES_ROOT: string; + export const NVTOOLSEXT_PATH: string; + export const OLDPWD: string; + export const OneDrive: string; + export const OneDriveConsumer: string; + export const OS: string; + export const OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: string; + export const OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT: string; + export const PATH: string; + export const PATHEXT: string; + export const PLINK_PROTOCOL: string; + export const PROCESSOR_ARCHITECTURE: string; + export const PROCESSOR_IDENTIFIER: string; + export const PROCESSOR_LEVEL: string; + export const PROCESSOR_REVISION: string; + export const ProgramData: string; + export const PROGRAMFILES: string; + export const ProgramW6432: string; + export const PROMPT: string; + export const PSModulePath: string; + export const PUBLIC: string; + export const PWD: string; + export const PyCharm: string; + export const QtMsBuild: string; + export const RlsSvcPort: string; + export const SESSIONNAME: string; + export const SHELL: string; + export const SHLVL: string; + export const SYSTEMDRIVE: string; + export const SYSTEMROOT: string; + export const TEMP: string; + export const TERM: string; + export const TMP: string; + export const USERDOMAIN: string; + export const USERDOMAIN_ROAMINGPROFILE: string; + export const USERNAME: string; + export const USERPROFILE: string; + export const VIRTUAL_ENV: string; + export const VSCODE_CODE_CACHE_PATH: string; + export const VSCODE_CRASH_REPORTER_PROCESS_TYPE: string; + export const VSCODE_CWD: string; + export const VSCODE_DOTNET_INSTALL_TOOL_ORIGINAL_HOME: string; + export const VSCODE_ESM_ENTRYPOINT: string; + export const VSCODE_HANDLES_UNCAUGHT_ERRORS: string; + export const VSCODE_IPC_HOOK: string; + export const VSCODE_L10N_BUNDLE_LOCATION: string; + export const VSCODE_NLS_CONFIG: string; + export const VSCODE_PID: string; + export const VsPythonPath: string; + export const WebStorm: string; + export const WINDIR: string; + export const _: string; +} + +/** + * This module provides access to environment variables that are injected _statically_ into your bundle at build time and are _publicly_ accessible. + * + * | | Runtime | Build time | + * | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ | + * | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) | + * | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) | + * + * Static environment variables are [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env` at build time and then statically injected into your bundle at build time, enabling optimisations like dead code elimination. + * + * **_Public_ access:** + * + * - This module _can_ be imported into client-side code + * - **Only** variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`) are included + * + * For example, given the following build time environment: + * + * ```env + * ENVIRONMENT=production + * PUBLIC_BASE_URL=http://site.com + * ``` + * + * With the default `publicPrefix` and `privatePrefix`: + * + * ```ts + * import { ENVIRONMENT, PUBLIC_BASE_URL } from '$env/static/public'; + * + * console.log(ENVIRONMENT); // => throws error during build + * console.log(PUBLIC_BASE_URL); // => "http://site.com" + * ``` + * + * The above values will be the same _even if_ different values for `ENVIRONMENT` or `PUBLIC_BASE_URL` are set at runtime, as they are statically replaced in your code with their build time values. + */ +declare module '$env/static/public' { + +} + +/** + * This module provides access to environment variables set _dynamically_ at runtime and that are limited to _private_ access. + * + * | | Runtime | Build time | + * | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ | + * | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) | + * | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) | + * + * Dynamic environment variables are defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`. + * + * **_Private_ access:** + * + * - This module cannot be imported into client-side code + * - This module includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured) + * + * > [!NOTE] In `dev`, `$env/dynamic` includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter. + * + * > [!NOTE] To get correct types, environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed: + * > + * > ```env + * > MY_FEATURE_FLAG= + * > ``` + * > + * > You can override `.env` values from the command line like so: + * > + * > ```sh + * > MY_FEATURE_FLAG="enabled" npm run dev + * > ``` + * + * For example, given the following runtime environment: + * + * ```env + * ENVIRONMENT=production + * PUBLIC_BASE_URL=http://site.com + * ``` + * + * With the default `publicPrefix` and `privatePrefix`: + * + * ```ts + * import { env } from '$env/dynamic/private'; + * + * console.log(env.ENVIRONMENT); // => "production" + * console.log(env.PUBLIC_BASE_URL); // => undefined + * ``` + */ +declare module '$env/dynamic/private' { + export const env: { + ACSetupSvcPort: string; + ACSvcPort: string; + ALLUSERSPROFILE: string; + ANDROID_SDK_HOME: string; + APPDATA: string; + APPLICATIONINSIGHTS_CONFIGURATION_CONTENT: string; + APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL: string; + APPLICATION_INSIGHTS_NO_STATSBEAT: string; + CHROME_CRASHPAD_PIPE_NAME: string; + CLAUDECODE: string; + CLAUDE_AGENT_SDK_VERSION: string; + CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING: string; + CLAUDE_CODE_ENTRYPOINT: string; + COLOR: string; + COMMONPROGRAMFILES: string; + CommonProgramW6432: string; + COMPUTERNAME: string; + COMSPEC: string; + COPILOT_OTEL_ENABLED: string; + COPILOT_OTEL_EXPORTER_TYPE: string; + COPILOT_OTEL_FILE_EXPORTER_PATH: string; + COREPACK_ENABLE_AUTO_PIN: string; + CUDA_PATH: string; + CUDA_PATH_V10_1: string; + CUDA_PATH_V12_0: string; + CUDA_PATH_V12_4: string; + CUDA_PATH_V13_1: string; + CUDA_PATH_V13_2: string; + DriverData: string; + EDITOR: string; + ELECTRON_RUN_AS_NODE: string; + EXEPATH: string; + FPS_BROWSER_APP_PROFILE_STRING: string; + FPS_BROWSER_USER_PROFILE_STRING: string; + GIT_EDITOR: string; + GOPATH: string; + HOME: string; + HOMEDRIVE: string; + HOMEPATH: string; + INIT_CWD: string; + LOCALAPPDATA: string; + LOGONSERVER: string; + MSYSTEM: string; + NODE: string; + NoDefaultCurrentDirectoryInExePath: string; + NODE_ENV: string; + NODE_UNC_HOST_ALLOWLIST: string; + npm_command: string; + npm_config_cache: string; + npm_config_globalconfig: string; + npm_config_global_prefix: string; + npm_config_init_module: string; + npm_config_local_prefix: string; + npm_config_metrics_registry: string; + npm_config_node_gyp: string; + npm_config_noproxy: string; + npm_config_prefix: string; + npm_config_userconfig: string; + npm_config_user_agent: string; + npm_execpath: string; + npm_lifecycle_event: string; + npm_lifecycle_script: string; + npm_node_execpath: string; + npm_package_json: string; + npm_package_name: string; + npm_package_version: string; + NUMBER_OF_PROCESSORS: string; + NVCUDASAMPLES10_1_ROOT: string; + NVCUDASAMPLES_ROOT: string; + NVTOOLSEXT_PATH: string; + OLDPWD: string; + OneDrive: string; + OneDriveConsumer: string; + OS: string; + OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: string; + OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT: string; + PATH: string; + PATHEXT: string; + PLINK_PROTOCOL: string; + PROCESSOR_ARCHITECTURE: string; + PROCESSOR_IDENTIFIER: string; + PROCESSOR_LEVEL: string; + PROCESSOR_REVISION: string; + ProgramData: string; + PROGRAMFILES: string; + ProgramW6432: string; + PROMPT: string; + PSModulePath: string; + PUBLIC: string; + PWD: string; + PyCharm: string; + QtMsBuild: string; + RlsSvcPort: string; + SESSIONNAME: string; + SHELL: string; + SHLVL: string; + SYSTEMDRIVE: string; + SYSTEMROOT: string; + TEMP: string; + TERM: string; + TMP: string; + USERDOMAIN: string; + USERDOMAIN_ROAMINGPROFILE: string; + USERNAME: string; + USERPROFILE: string; + VIRTUAL_ENV: string; + VSCODE_CODE_CACHE_PATH: string; + VSCODE_CRASH_REPORTER_PROCESS_TYPE: string; + VSCODE_CWD: string; + VSCODE_DOTNET_INSTALL_TOOL_ORIGINAL_HOME: string; + VSCODE_ESM_ENTRYPOINT: string; + VSCODE_HANDLES_UNCAUGHT_ERRORS: string; + VSCODE_IPC_HOOK: string; + VSCODE_L10N_BUNDLE_LOCATION: string; + VSCODE_NLS_CONFIG: string; + VSCODE_PID: string; + VsPythonPath: string; + WebStorm: string; + WINDIR: string; + _: string; + [key: `PUBLIC_${string}`]: undefined; + [key: `${string}`]: string | undefined; + } +} + +/** + * This module provides access to environment variables set _dynamically_ at runtime and that are _publicly_ accessible. + * + * | | Runtime | Build time | + * | ------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ | + * | Private | [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) | + * | Public | [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) | + * + * Dynamic environment variables are defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`. + * + * **_Public_ access:** + * + * - This module _can_ be imported into client-side code + * - **Only** variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`) are included + * + * > [!NOTE] In `dev`, `$env/dynamic` includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter. + * + * > [!NOTE] To get correct types, environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed: + * > + * > ```env + * > MY_FEATURE_FLAG= + * > ``` + * > + * > You can override `.env` values from the command line like so: + * > + * > ```sh + * > MY_FEATURE_FLAG="enabled" npm run dev + * > ``` + * + * For example, given the following runtime environment: + * + * ```env + * ENVIRONMENT=production + * PUBLIC_BASE_URL=http://example.com + * ``` + * + * With the default `publicPrefix` and `privatePrefix`: + * + * ```ts + * import { env } from '$env/dynamic/public'; + * console.log(env.ENVIRONMENT); // => undefined, not public + * console.log(env.PUBLIC_BASE_URL); // => "http://example.com" + * ``` + * + * ``` + * + * ``` + */ +declare module '$env/dynamic/public' { + export const env: { + [key: `PUBLIC_${string}`]: string | undefined; + } +} diff --git a/web/.svelte-kit/generated/client-optimized/app.js b/web/.svelte-kit/generated/client-optimized/app.js new file mode 100644 index 0000000..39d73d8 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/app.js @@ -0,0 +1,62 @@ +export { matchers } from './matchers.js'; + +export const nodes = [ + () => import('./nodes/0'), + () => import('./nodes/1'), + () => import('./nodes/2'), + () => import('./nodes/3'), + () => import('./nodes/4'), + () => import('./nodes/5'), + () => import('./nodes/6'), + () => import('./nodes/7'), + () => import('./nodes/8'), + () => import('./nodes/9'), + () => import('./nodes/10'), + () => import('./nodes/11'), + () => import('./nodes/12'), + () => import('./nodes/13'), + () => import('./nodes/14'), + () => import('./nodes/15'), + () => import('./nodes/16'), + () => import('./nodes/17'), + () => import('./nodes/18'), + () => import('./nodes/19') +]; + +export const server_loads = []; + +export const dictionary = { + "/": [3], + "/containers/stale": [4], + "/deploy": [5], + "/events": [6], + "/login": [7], + "/projects": [8], + "/projects/[id]": [9], + "/projects/[id]/env": [10], + "/projects/[id]/volumes": [11], + "/projects/[id]/volumes/[volId]/browse": [12], + "/proxies": [13], + "/proxies/create": [14], + "/proxies/[id]/edit": [15], + "/settings": [16,[2]], + "/settings/auth": [17,[2]], + "/settings/credentials": [18,[2]], + "/settings/registries": [19,[2]] + }; + +export const hooks = { + handleError: (({ error }) => { console.error(error) }), + + reroute: (() => {}), + transport: {} +}; + +export const decoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.decode])); +export const encoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.encode])); + +export const hash = false; + +export const decode = (type, value) => decoders[type](value); + +export { default as root } from '../root.js'; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/matchers.js b/web/.svelte-kit/generated/client-optimized/matchers.js new file mode 100644 index 0000000..f6bd30a --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/matchers.js @@ -0,0 +1 @@ +export const matchers = {}; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/0.js b/web/.svelte-kit/generated/client-optimized/nodes/0.js new file mode 100644 index 0000000..b2e56b2 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/0.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/+layout.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/+layout.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/1.js b/web/.svelte-kit/generated/client-optimized/nodes/1.js new file mode 100644 index 0000000..bf58bad --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/1.js @@ -0,0 +1 @@ +export { default as component } from "../../../../node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/10.js b/web/.svelte-kit/generated/client-optimized/nodes/10.js new file mode 100644 index 0000000..e6a2138 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/10.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/projects/[id]/env/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/11.js b/web/.svelte-kit/generated/client-optimized/nodes/11.js new file mode 100644 index 0000000..845e958 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/11.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/projects/[id]/volumes/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/12.js b/web/.svelte-kit/generated/client-optimized/nodes/12.js new file mode 100644 index 0000000..5063af2 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/12.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/projects/[id]/volumes/[volId]/browse/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/projects/[id]/volumes/[volId]/browse/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/13.js b/web/.svelte-kit/generated/client-optimized/nodes/13.js new file mode 100644 index 0000000..1dd3e67 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/13.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/proxies/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/proxies/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/14.js b/web/.svelte-kit/generated/client-optimized/nodes/14.js new file mode 100644 index 0000000..aad2c84 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/14.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/proxies/create/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/proxies/create/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/15.js b/web/.svelte-kit/generated/client-optimized/nodes/15.js new file mode 100644 index 0000000..f6aa48d --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/15.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/proxies/[id]/edit/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/proxies/[id]/edit/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/16.js b/web/.svelte-kit/generated/client-optimized/nodes/16.js new file mode 100644 index 0000000..c50e736 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/16.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/settings/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/17.js b/web/.svelte-kit/generated/client-optimized/nodes/17.js new file mode 100644 index 0000000..c9d4556 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/17.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/settings/auth/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/18.js b/web/.svelte-kit/generated/client-optimized/nodes/18.js new file mode 100644 index 0000000..89f61fb --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/18.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/settings/credentials/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/19.js b/web/.svelte-kit/generated/client-optimized/nodes/19.js new file mode 100644 index 0000000..0dbce1c --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/19.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/settings/registries/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/2.js b/web/.svelte-kit/generated/client-optimized/nodes/2.js new file mode 100644 index 0000000..2e594ab --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/2.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/settings/+layout.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/3.js b/web/.svelte-kit/generated/client-optimized/nodes/3.js new file mode 100644 index 0000000..1cb4f85 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/3.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/4.js b/web/.svelte-kit/generated/client-optimized/nodes/4.js new file mode 100644 index 0000000..f0ad0c3 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/4.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/containers/stale/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/containers/stale/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/5.js b/web/.svelte-kit/generated/client-optimized/nodes/5.js new file mode 100644 index 0000000..bbb7e92 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/5.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/deploy/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/6.js b/web/.svelte-kit/generated/client-optimized/nodes/6.js new file mode 100644 index 0000000..dc4cd24 --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/6.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/events/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/events/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/7.js b/web/.svelte-kit/generated/client-optimized/nodes/7.js new file mode 100644 index 0000000..f2b26cd --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/7.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/login/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/8.js b/web/.svelte-kit/generated/client-optimized/nodes/8.js new file mode 100644 index 0000000..0d2d91a --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/8.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/projects/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client-optimized/nodes/9.js b/web/.svelte-kit/generated/client-optimized/nodes/9.js new file mode 100644 index 0000000..a9df14e --- /dev/null +++ b/web/.svelte-kit/generated/client-optimized/nodes/9.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/projects/[id]/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/app.js b/web/.svelte-kit/generated/client/app.js new file mode 100644 index 0000000..f53b18c --- /dev/null +++ b/web/.svelte-kit/generated/client/app.js @@ -0,0 +1,64 @@ +export { matchers } from './matchers.js'; + +export const nodes = [ + () => import('./nodes/0'), + () => import('./nodes/1'), + () => import('./nodes/2'), + () => import('./nodes/3'), + () => import('./nodes/4'), + () => import('./nodes/5'), + () => import('./nodes/6'), + () => import('./nodes/7'), + () => import('./nodes/8'), + () => import('./nodes/9'), + () => import('./nodes/10'), + () => import('./nodes/11'), + () => import('./nodes/12'), + () => import('./nodes/13'), + () => import('./nodes/14'), + () => import('./nodes/15'), + () => import('./nodes/16'), + () => import('./nodes/17'), + () => import('./nodes/18'), + () => import('./nodes/19'), + () => import('./nodes/20') +]; + +export const server_loads = []; + +export const dictionary = { + "/": [3], + "/containers/stale": [4], + "/deploy": [5], + "/dns": [6], + "/events": [7], + "/login": [8], + "/projects": [9], + "/projects/[id]": [10], + "/projects/[id]/env": [11], + "/projects/[id]/volumes": [12], + "/projects/[id]/volumes/[volId]/browse": [13], + "/proxies": [14], + "/proxies/create": [15], + "/proxies/[id]/edit": [16], + "/settings": [17,[2]], + "/settings/auth": [18,[2]], + "/settings/credentials": [19,[2]], + "/settings/registries": [20,[2]] + }; + +export const hooks = { + handleError: (({ error }) => { console.error(error) }), + + reroute: (() => {}), + transport: {} +}; + +export const decoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.decode])); +export const encoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.encode])); + +export const hash = false; + +export const decode = (type, value) => decoders[type](value); + +export { default as root } from '../root.js'; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/matchers.js b/web/.svelte-kit/generated/client/matchers.js new file mode 100644 index 0000000..f6bd30a --- /dev/null +++ b/web/.svelte-kit/generated/client/matchers.js @@ -0,0 +1 @@ +export const matchers = {}; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/0.js b/web/.svelte-kit/generated/client/nodes/0.js new file mode 100644 index 0000000..b2e56b2 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/0.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/+layout.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/+layout.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/1.js b/web/.svelte-kit/generated/client/nodes/1.js new file mode 100644 index 0000000..bf58bad --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/1.js @@ -0,0 +1 @@ +export { default as component } from "../../../../node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/10.js b/web/.svelte-kit/generated/client/nodes/10.js new file mode 100644 index 0000000..a9df14e --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/10.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/projects/[id]/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/11.js b/web/.svelte-kit/generated/client/nodes/11.js new file mode 100644 index 0000000..e6a2138 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/11.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/projects/[id]/env/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/12.js b/web/.svelte-kit/generated/client/nodes/12.js new file mode 100644 index 0000000..845e958 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/12.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/projects/[id]/volumes/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/13.js b/web/.svelte-kit/generated/client/nodes/13.js new file mode 100644 index 0000000..5063af2 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/13.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/projects/[id]/volumes/[volId]/browse/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/projects/[id]/volumes/[volId]/browse/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/14.js b/web/.svelte-kit/generated/client/nodes/14.js new file mode 100644 index 0000000..1dd3e67 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/14.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/proxies/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/proxies/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/15.js b/web/.svelte-kit/generated/client/nodes/15.js new file mode 100644 index 0000000..aad2c84 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/15.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/proxies/create/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/proxies/create/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/16.js b/web/.svelte-kit/generated/client/nodes/16.js new file mode 100644 index 0000000..f6aa48d --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/16.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/proxies/[id]/edit/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/proxies/[id]/edit/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/17.js b/web/.svelte-kit/generated/client/nodes/17.js new file mode 100644 index 0000000..c50e736 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/17.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/settings/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/18.js b/web/.svelte-kit/generated/client/nodes/18.js new file mode 100644 index 0000000..c9d4556 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/18.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/settings/auth/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/19.js b/web/.svelte-kit/generated/client/nodes/19.js new file mode 100644 index 0000000..89f61fb --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/19.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/settings/credentials/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/2.js b/web/.svelte-kit/generated/client/nodes/2.js new file mode 100644 index 0000000..2e594ab --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/2.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/settings/+layout.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/20.js b/web/.svelte-kit/generated/client/nodes/20.js new file mode 100644 index 0000000..0dbce1c --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/20.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/settings/registries/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/3.js b/web/.svelte-kit/generated/client/nodes/3.js new file mode 100644 index 0000000..1cb4f85 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/3.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/4.js b/web/.svelte-kit/generated/client/nodes/4.js new file mode 100644 index 0000000..f0ad0c3 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/4.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/containers/stale/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/containers/stale/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/5.js b/web/.svelte-kit/generated/client/nodes/5.js new file mode 100644 index 0000000..bbb7e92 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/5.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/deploy/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/6.js b/web/.svelte-kit/generated/client/nodes/6.js new file mode 100644 index 0000000..060758e --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/6.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/dns/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/7.js b/web/.svelte-kit/generated/client/nodes/7.js new file mode 100644 index 0000000..dc4cd24 --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/7.js @@ -0,0 +1,3 @@ +import * as universal from "../../../../src/routes/events/+page.ts"; +export { universal }; +export { default as component } from "../../../../src/routes/events/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/8.js b/web/.svelte-kit/generated/client/nodes/8.js new file mode 100644 index 0000000..f2b26cd --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/8.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/login/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/client/nodes/9.js b/web/.svelte-kit/generated/client/nodes/9.js new file mode 100644 index 0000000..0d2d91a --- /dev/null +++ b/web/.svelte-kit/generated/client/nodes/9.js @@ -0,0 +1 @@ +export { default as component } from "../../../../src/routes/projects/+page.svelte"; \ No newline at end of file diff --git a/web/.svelte-kit/generated/root.js b/web/.svelte-kit/generated/root.js new file mode 100644 index 0000000..4d1e892 --- /dev/null +++ b/web/.svelte-kit/generated/root.js @@ -0,0 +1,3 @@ +import { asClassComponent } from 'svelte/legacy'; +import Root from './root.svelte'; +export default asClassComponent(Root); \ No newline at end of file diff --git a/web/.svelte-kit/generated/root.svelte b/web/.svelte-kit/generated/root.svelte new file mode 100644 index 0000000..1c16fc8 --- /dev/null +++ b/web/.svelte-kit/generated/root.svelte @@ -0,0 +1,80 @@ + + + + +{#if constructors[1]} + {@const Pyramid_0 = constructors[0]} + + + {#if constructors[2]} + {@const Pyramid_1 = constructors[1]} + + + + + + + {:else} + {@const Pyramid_1 = constructors[1]} + + + + {/if} + + +{:else} + {@const Pyramid_0 = constructors[0]} + + + +{/if} + +{#if mounted} +
+ {#if navigated} + {title} + {/if} +
+{/if} \ No newline at end of file diff --git a/web/.svelte-kit/generated/server/internal.js b/web/.svelte-kit/generated/server/internal.js new file mode 100644 index 0000000..59dd322 --- /dev/null +++ b/web/.svelte-kit/generated/server/internal.js @@ -0,0 +1,54 @@ + +import root from '../root.js'; +import { set_building, set_prerendering } from '__sveltekit/environment'; +import { set_assets } from '$app/paths/internal/server'; +import { set_manifest, set_read_implementation } from '__sveltekit/server'; +import { set_private_env, set_public_env } from '../../../node_modules/@sveltejs/kit/src/runtime/shared-server.js'; + +export const options = { + app_template_contains_nonce: false, + async: false, + csp: {"mode":"auto","directives":{"upgrade-insecure-requests":false,"block-all-mixed-content":false},"reportOnly":{"upgrade-insecure-requests":false,"block-all-mixed-content":false}}, + csrf_check_origin: true, + csrf_trusted_origins: [], + embedded: false, + env_public_prefix: 'PUBLIC_', + env_private_prefix: '', + hash_routing: false, + hooks: null, // added lazily, via `get_hooks` + preload_strategy: "modulepreload", + root, + service_worker: false, + service_worker_options: undefined, + server_error_boundaries: false, + templates: { + app: ({ head, body, assets, nonce, env }) => "\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t" + head + "\r\n\t\r\n\t\r\n\t\t
" + body + "
\r\n\t\r\n\r\n", + error: ({ status, message }) => "\n\n\t\n\t\t\n\t\t" + message + "\n\n\t\t\n\t\n\t\n\t\t
\n\t\t\t" + status + "\n\t\t\t
\n\t\t\t\t

" + message + "

\n\t\t\t
\n\t\t
\n\t\n\n" + }, + version_hash: "1rlkqzj" +}; + +export async function get_hooks() { + let handle; + let handleFetch; + let handleError; + let handleValidationError; + let init; + + + let reroute; + let transport; + + + return { + handle, + handleFetch, + handleError, + handleValidationError, + init, + reroute, + transport + }; +} + +export { set_assets, set_building, set_manifest, set_prerendering, set_private_env, set_public_env, set_read_implementation }; diff --git a/web/.svelte-kit/non-ambient.d.ts b/web/.svelte-kit/non-ambient.d.ts new file mode 100644 index 0000000..c91a09b --- /dev/null +++ b/web/.svelte-kit/non-ambient.d.ts @@ -0,0 +1,69 @@ + +// this file is generated — do not edit it + + +declare module "svelte/elements" { + export interface HTMLAttributes { + 'data-sveltekit-keepfocus'?: true | '' | 'off' | undefined | null; + 'data-sveltekit-noscroll'?: true | '' | 'off' | undefined | null; + 'data-sveltekit-preload-code'?: + | true + | '' + | 'eager' + | 'viewport' + | 'hover' + | 'tap' + | 'off' + | undefined + | null; + 'data-sveltekit-preload-data'?: true | '' | 'hover' | 'tap' | 'off' | undefined | null; + 'data-sveltekit-reload'?: true | '' | 'off' | undefined | null; + 'data-sveltekit-replacestate'?: true | '' | 'off' | undefined | null; + } +} + +export {}; + + +declare module "$app/types" { + type MatcherParam = M extends (param : string) => param is (infer U extends string) ? U : string; + + export interface AppTypes { + RouteId(): "/" | "/containers" | "/containers/stale" | "/deploy" | "/dns" | "/events" | "/login" | "/projects" | "/projects/[id]" | "/projects/[id]/env" | "/projects/[id]/volumes" | "/projects/[id]/volumes/[volId]" | "/projects/[id]/volumes/[volId]/browse" | "/proxies" | "/proxies/create" | "/proxies/[id]" | "/proxies/[id]/edit" | "/settings" | "/settings/auth" | "/settings/credentials" | "/settings/registries"; + RouteParams(): { + "/projects/[id]": { id: string }; + "/projects/[id]/env": { id: string }; + "/projects/[id]/volumes": { id: string }; + "/projects/[id]/volumes/[volId]": { id: string; volId: string }; + "/projects/[id]/volumes/[volId]/browse": { id: string; volId: string }; + "/proxies/[id]": { id: string }; + "/proxies/[id]/edit": { id: string } + }; + LayoutParams(): { + "/": { id?: string; volId?: string }; + "/containers": Record; + "/containers/stale": Record; + "/deploy": Record; + "/dns": Record; + "/events": Record; + "/login": Record; + "/projects": { id?: string; volId?: string }; + "/projects/[id]": { id: string; volId?: string }; + "/projects/[id]/env": { id: string }; + "/projects/[id]/volumes": { id: string; volId?: string }; + "/projects/[id]/volumes/[volId]": { id: string; volId: string }; + "/projects/[id]/volumes/[volId]/browse": { id: string; volId: string }; + "/proxies": { id?: string }; + "/proxies/create": Record; + "/proxies/[id]": { id: string }; + "/proxies/[id]/edit": { id: string }; + "/settings": Record; + "/settings/auth": Record; + "/settings/credentials": Record; + "/settings/registries": Record + }; + Pathname(): "/" | "/containers/stale" | "/deploy" | "/dns" | "/events" | "/login" | "/projects" | `/projects/${string}` & {} | `/projects/${string}/env` & {} | `/projects/${string}/volumes` & {} | `/projects/${string}/volumes/${string}/browse` & {} | "/proxies" | "/proxies/create" | `/proxies/${string}/edit` & {} | "/settings" | "/settings/auth" | "/settings/credentials" | "/settings/registries"; + ResolvedPathname(): `${"" | `/${string}`}${ReturnType}`; + Asset(): string & {}; + } +} \ No newline at end of file diff --git a/web/.svelte-kit/output/client/.vite/manifest.json b/web/.svelte-kit/output/client/.vite/manifest.json new file mode 100644 index 0000000..d079a9c --- /dev/null +++ b/web/.svelte-kit/output/client/.vite/manifest.json @@ -0,0 +1,949 @@ +{ + ".svelte-kit/generated/client-optimized/app.js": { + "file": "_app/immutable/entry/app.C3eO1cEh.js", + "name": "entry/app", + "src": ".svelte-kit/generated/client-optimized/app.js", + "isEntry": true, + "imports": [ + "_DKemW7Dm.js", + "_BJdXET8u.js", + "_phMGo29-.js", + "_BSXRhUWv.js", + "_BoGS7hWi.js" + ], + "dynamicImports": [ + ".svelte-kit/generated/client-optimized/nodes/0.js", + ".svelte-kit/generated/client-optimized/nodes/1.js", + ".svelte-kit/generated/client-optimized/nodes/2.js", + ".svelte-kit/generated/client-optimized/nodes/3.js", + ".svelte-kit/generated/client-optimized/nodes/4.js", + ".svelte-kit/generated/client-optimized/nodes/5.js", + ".svelte-kit/generated/client-optimized/nodes/6.js", + ".svelte-kit/generated/client-optimized/nodes/7.js", + ".svelte-kit/generated/client-optimized/nodes/8.js", + ".svelte-kit/generated/client-optimized/nodes/9.js", + ".svelte-kit/generated/client-optimized/nodes/10.js", + ".svelte-kit/generated/client-optimized/nodes/11.js", + ".svelte-kit/generated/client-optimized/nodes/12.js", + ".svelte-kit/generated/client-optimized/nodes/13.js", + ".svelte-kit/generated/client-optimized/nodes/14.js", + ".svelte-kit/generated/client-optimized/nodes/15.js", + ".svelte-kit/generated/client-optimized/nodes/16.js", + ".svelte-kit/generated/client-optimized/nodes/17.js", + ".svelte-kit/generated/client-optimized/nodes/18.js", + ".svelte-kit/generated/client-optimized/nodes/19.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/0.js": { + "file": "_app/immutable/nodes/0.BMqZW0X_.js", + "name": "nodes/0", + "src": ".svelte-kit/generated/client-optimized/nodes/0.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_phMGo29-.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_CnPWu_ZO.js", + "_kfynmD3Z.js", + "_DELaSNrV.js", + "_BSEsuAwr.js", + "_BlV-f-zB.js", + "_CjZL2MYp.js", + "_LFhQE6G2.js", + "_R0-LJft-.js", + "_CGCp4lb_.js", + "_CcoMVVg8.js", + "_DrzuxmSv.js", + "_Hsiz6fBZ.js", + "_CWCQOKDd.js", + "_CvtQ6g1S.js", + "_DPFeFjvi.js", + "_DTyrBG6r.js", + "_Bpb8V1MF.js" + ], + "css": [ + "_app/immutable/assets/0.DnmtykcB.css" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/1.js": { + "file": "_app/immutable/nodes/1.Bdu_R2Hn.js", + "name": "nodes/1", + "src": ".svelte-kit/generated/client-optimized/nodes/1.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_BSEsuAwr.js", + "_DKemW7Dm.js", + "_BlV-f-zB.js", + "_CWhLh9u1.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/10.js": { + "file": "_app/immutable/nodes/10.DFEGHcUu.js", + "name": "nodes/10", + "src": ".svelte-kit/generated/client-optimized/nodes/10.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_kfynmD3Z.js", + "_DgtbvmBB.js", + "_Bxa5VUw6.js", + "_DELaSNrV.js", + "_Bpb8V1MF.js", + "_CjZL2MYp.js", + "_scnZuc49.js", + "_C6FeVxU4.js", + "_LFhQE6G2.js", + "_R0-LJft-.js", + "_Icw0y4KW.js", + "_BFW91e3Y.js", + "_CPatcLwq.js", + "_CpnAtA5t.js", + "_BberSjRt.js", + "_BE_zO38m.js", + "_CexodXHl.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/11.js": { + "file": "_app/immutable/nodes/11.DMrjUtpD.js", + "name": "nodes/11", + "src": ".svelte-kit/generated/client-optimized/nodes/11.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_kfynmD3Z.js", + "_DgtbvmBB.js", + "_Bxa5VUw6.js", + "_DELaSNrV.js", + "_Bpb8V1MF.js", + "_CjZL2MYp.js", + "_scnZuc49.js", + "_C6FeVxU4.js", + "_LFhQE6G2.js", + "_R0-LJft-.js", + "_Icw0y4KW.js", + "_BphdEXYy.js", + "_BvIWRct8.js", + "_CPatcLwq.js", + "_BE_zO38m.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/12.js": { + "file": "_app/immutable/nodes/12.BO7G7YPE.js", + "name": "nodes/12", + "src": ".svelte-kit/generated/client-optimized/nodes/12.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_kfynmD3Z.js", + "_BoGS7hWi.js", + "_DELaSNrV.js", + "_Bpb8V1MF.js", + "_CjZL2MYp.js", + "_Icw0y4KW.js", + "_BFW91e3Y.js", + "_BE_zO38m.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/13.js": { + "file": "_app/immutable/nodes/13.DJV70kty.js", + "name": "nodes/13", + "src": ".svelte-kit/generated/client-optimized/nodes/13.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_phMGo29-.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_Bpb8V1MF.js", + "_kfynmD3Z.js", + "_BphdEXYy.js", + "_CPatcLwq.js", + "_CpnAtA5t.js", + "_CnPWu_ZO.js", + "_Icw0y4KW.js", + "_Bxa5VUw6.js", + "_R0-LJft-.js", + "_BvIWRct8.js", + "_CexodXHl.js", + "_DrzuxmSv.js", + "_BFW91e3Y.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/14.js": { + "file": "_app/immutable/nodes/14.udJGaOK1.js", + "name": "nodes/14", + "src": ".svelte-kit/generated/client-optimized/nodes/14.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_BSEsuAwr.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_ecfdBtDb.js", + "_BlV-f-zB.js", + "_CWhLh9u1.js", + "_kfynmD3Z.js", + "_DsQCf6vC.js", + "_DrzuxmSv.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/15.js": { + "file": "_app/immutable/nodes/15.BC8amYnm.js", + "name": "nodes/15", + "src": ".svelte-kit/generated/client-optimized/nodes/15.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_phMGo29-.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_ecfdBtDb.js", + "_DELaSNrV.js", + "_CWhLh9u1.js", + "_Bpb8V1MF.js", + "_kfynmD3Z.js", + "_DsQCf6vC.js", + "_DrzuxmSv.js", + "_BFW91e3Y.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/16.js": { + "file": "_app/immutable/nodes/16.DrkZ20qh.js", + "name": "nodes/16", + "src": ".svelte-kit/generated/client-optimized/nodes/16.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_kfynmD3Z.js", + "_Bpb8V1MF.js", + "_DfwQ65vN.js", + "_BxXVdbgr.js", + "_CjZL2MYp.js", + "_R0-LJft-.js", + "_DhEbbC3M.js", + "_BFW91e3Y.js", + "_BE_zO38m.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/17.js": { + "file": "_app/immutable/nodes/17.CjAaIU5M.js", + "name": "nodes/17", + "src": ".svelte-kit/generated/client-optimized/nodes/17.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_phMGo29-.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_kfynmD3Z.js", + "_DgtbvmBB.js", + "_Bxa5VUw6.js", + "_scnZuc49.js", + "_C6FeVxU4.js", + "_BFW91e3Y.js", + "_CexodXHl.js", + "_DTyrBG6r.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/18.js": { + "file": "_app/immutable/nodes/18.C3f1k8vs.js", + "name": "nodes/18", + "src": ".svelte-kit/generated/client-optimized/nodes/18.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_kfynmD3Z.js", + "_Bpb8V1MF.js", + "_DfwQ65vN.js", + "_BE_zO38m.js", + "_CjZL2MYp.js", + "_LFhQE6G2.js", + "_BFW91e3Y.js", + "_CPatcLwq.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/19.js": { + "file": "_app/immutable/nodes/19.CiwgThsf.js", + "name": "nodes/19", + "src": ".svelte-kit/generated/client-optimized/nodes/19.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_Bxa5VUw6.js", + "_Bpb8V1MF.js", + "_DfwQ65vN.js", + "_CexodXHl.js", + "_BE_zO38m.js", + "_CjZL2MYp.js", + "_kfynmD3Z.js", + "_scnZuc49.js", + "_C6FeVxU4.js", + "_BFW91e3Y.js", + "_CPatcLwq.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/2.js": { + "file": "_app/immutable/nodes/2.DWWtnNKd.js", + "name": "nodes/2", + "src": ".svelte-kit/generated/client-optimized/nodes/2.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CnPWu_ZO.js", + "_CZnXUJhL.js", + "_kfynmD3Z.js", + "_DELaSNrV.js", + "_CWCQOKDd.js", + "_DqoiTw6k.js", + "_DhEbbC3M.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/3.js": { + "file": "_app/immutable/nodes/3.C0WC8trC.js", + "name": "nodes/3", + "src": ".svelte-kit/generated/client-optimized/nodes/3.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_kfynmD3Z.js", + "_Bpb8V1MF.js", + "_BPqRr2-s.js", + "_ip4Jv8C8.js", + "_CexodXHl.js", + "_CGCp4lb_.js", + "_CvtQ6g1S.js", + "_Hsiz6fBZ.js", + "_DVE7XZFM.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/4.js": { + "file": "_app/immutable/nodes/4.BxW_ZYFP.js", + "name": "nodes/4", + "src": ".svelte-kit/generated/client-optimized/nodes/4.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_Bpb8V1MF.js", + "_kfynmD3Z.js", + "_scnZuc49.js", + "_DVE7XZFM.js", + "_C8zo5-Sk.js", + "_CexodXHl.js", + "_ip4Jv8C8.js", + "_BFW91e3Y.js", + "_CjZL2MYp.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/5.js": { + "file": "_app/immutable/nodes/5.C24PPPF_.js", + "name": "nodes/5", + "src": ".svelte-kit/generated/client-optimized/nodes/5.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_ecfdBtDb.js", + "_kfynmD3Z.js", + "_Bxa5VUw6.js", + "_Bpb8V1MF.js", + "_DfwQ65vN.js", + "_BxXVdbgr.js", + "_CjZL2MYp.js", + "_Hsiz6fBZ.js", + "_BvIWRct8.js", + "_BFW91e3Y.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/6.js": { + "file": "_app/immutable/nodes/6.CEvKoBqC.js", + "name": "nodes/6", + "src": ".svelte-kit/generated/client-optimized/nodes/6.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_phMGo29-.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_BoGS7hWi.js", + "_kfynmD3Z.js", + "_Bpb8V1MF.js", + "_DPFeFjvi.js", + "_CexodXHl.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/7.js": { + "file": "_app/immutable/nodes/7.DneEC9SR.js", + "name": "nodes/7", + "src": ".svelte-kit/generated/client-optimized/nodes/7.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_phMGo29-.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_kfynmD3Z.js", + "_DgtbvmBB.js", + "_CWhLh9u1.js", + "_DELaSNrV.js", + "_CcoMVVg8.js", + "_BFW91e3Y.js", + "_DTyrBG6r.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/8.js": { + "file": "_app/immutable/nodes/8.BQus6eSQ.js", + "name": "nodes/8", + "src": ".svelte-kit/generated/client-optimized/nodes/8.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_kfynmD3Z.js", + "_Bpb8V1MF.js", + "_C6FeVxU4.js", + "_BvIWRct8.js", + "_BFW91e3Y.js", + "_DfwQ65vN.js", + "_BE_zO38m.js", + "_CexodXHl.js", + "_BxXVdbgr.js" + ] + }, + ".svelte-kit/generated/client-optimized/nodes/9.js": { + "file": "_app/immutable/nodes/9.g1C7u4k3.js", + "name": "nodes/9", + "src": ".svelte-kit/generated/client-optimized/nodes/9.js", + "isEntry": true, + "isDynamicEntry": true, + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_ecfdBtDb.js", + "_kfynmD3Z.js", + "_DgtbvmBB.js", + "_Bxa5VUw6.js", + "_DELaSNrV.js", + "_Bpb8V1MF.js", + "_BPqRr2-s.js", + "_BE_zO38m.js", + "_C8zo5-Sk.js", + "_scnZuc49.js", + "_BphdEXYy.js", + "_CexodXHl.js", + "_Hsiz6fBZ.js", + "_C6FeVxU4.js", + "_LFhQE6G2.js", + "_R0-LJft-.js", + "_Icw0y4KW.js", + "_DqoiTw6k.js", + "_BFW91e3Y.js", + "_DVE7XZFM.js", + "_CPatcLwq.js", + "_DfwQ65vN.js", + "_BberSjRt.js", + "_CjZL2MYp.js" + ] + }, + "_BE_zO38m.js": { + "file": "_app/immutable/chunks/BE_zO38m.js", + "name": "Skeleton", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_BFW91e3Y.js": { + "file": "_app/immutable/chunks/BFW91e3Y.js", + "name": "IconLoader", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_BJdXET8u.js": { + "file": "_app/immutable/chunks/BJdXET8u.js", + "name": "disclose-version", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_BPqRr2-s.js": { + "file": "_app/immutable/chunks/BPqRr2-s.js", + "name": "StatusBadge", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_kfynmD3Z.js" + ] + }, + "_BSEsuAwr.js": { + "file": "_app/immutable/chunks/BSEsuAwr.js", + "name": "legacy", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_BSXRhUWv.js": { + "file": "_app/immutable/chunks/BSXRhUWv.js", + "name": "props", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_BberSjRt.js": { + "file": "_app/immutable/chunks/BberSjRt.js", + "name": "ToggleSwitch", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_BlV-f-zB.js": { + "file": "_app/immutable/chunks/BlV-f-zB.js", + "name": "lifecycle", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_BoGS7hWi.js": { + "file": "_app/immutable/chunks/BoGS7hWi.js", + "name": "this", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_Bpb8V1MF.js": { + "file": "_app/immutable/chunks/Bpb8V1MF.js", + "name": "api", + "imports": [ + "_DTyrBG6r.js" + ] + }, + "_BphdEXYy.js": { + "file": "_app/immutable/chunks/BphdEXYy.js", + "name": "IconExternalLink", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_BvIWRct8.js": { + "file": "_app/immutable/chunks/BvIWRct8.js", + "name": "IconSearch", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_BxXVdbgr.js": { + "file": "_app/immutable/chunks/BxXVdbgr.js", + "name": "EntityPicker", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_CZnXUJhL.js", + "_kfynmD3Z.js", + "_DgtbvmBB.js", + "_BoGS7hWi.js", + "_R0-LJft-.js", + "_BvIWRct8.js" + ], + "css": [ + "_app/immutable/assets/EntityPicker.D4Qf6tQ2.css" + ] + }, + "_Bxa5VUw6.js": { + "file": "_app/immutable/chunks/Bxa5VUw6.js", + "name": "select", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_C6FeVxU4.js": { + "file": "_app/immutable/chunks/C6FeVxU4.js", + "name": "IconPlus", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_C8zo5-Sk.js": { + "file": "_app/immutable/chunks/C8zo5-Sk.js", + "name": "ConfirmDialog", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_kfynmD3Z.js", + "_CGCp4lb_.js" + ] + }, + "_CGCp4lb_.js": { + "file": "_app/immutable/chunks/CGCp4lb_.js", + "name": "IconAlert", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_CPatcLwq.js": { + "file": "_app/immutable/chunks/CPatcLwq.js", + "name": "IconEdit", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_CWCQOKDd.js": { + "file": "_app/immutable/chunks/CWCQOKDd.js", + "name": "IconSettings", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_CWhLh9u1.js": { + "file": "_app/immutable/chunks/CWhLh9u1.js", + "name": "entry", + "imports": [ + "_DKemW7Dm.js", + "_phMGo29-.js" + ] + }, + "_CZnXUJhL.js": { + "file": "_app/immutable/chunks/CZnXUJhL.js", + "name": "each", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_CcoMVVg8.js": { + "file": "_app/immutable/chunks/CcoMVVg8.js", + "name": "theme", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_CexodXHl.js": { + "file": "_app/immutable/chunks/CexodXHl.js", + "name": "EmptyState", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_kfynmD3Z.js" + ] + }, + "_CjZL2MYp.js": { + "file": "_app/immutable/chunks/CjZL2MYp.js", + "name": "toast", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_CnPWu_ZO.js": { + "file": "_app/immutable/chunks/CnPWu_ZO.js", + "name": "snippet", + "imports": [ + "_DKemW7Dm.js", + "_BSXRhUWv.js" + ] + }, + "_CpnAtA5t.js": { + "file": "_app/immutable/chunks/CpnAtA5t.js", + "name": "IconLock", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_CvtQ6g1S.js": { + "file": "_app/immutable/chunks/CvtQ6g1S.js", + "name": "IconProxies", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_DELaSNrV.js": { + "file": "_app/immutable/chunks/DELaSNrV.js", + "name": "stores", + "imports": [ + "_CWhLh9u1.js" + ] + }, + "_DKemW7Dm.js": { + "file": "_app/immutable/chunks/DKemW7Dm.js", + "name": "runtime" + }, + "_DPFeFjvi.js": { + "file": "_app/immutable/chunks/DPFeFjvi.js", + "name": "sse", + "imports": [ + "_DTyrBG6r.js" + ] + }, + "_DTyrBG6r.js": { + "file": "_app/immutable/chunks/DTyrBG6r.js", + "name": "auth" + }, + "_DVE7XZFM.js": { + "file": "_app/immutable/chunks/DVE7XZFM.js", + "name": "IconClock", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_DfwQ65vN.js": { + "file": "_app/immutable/chunks/DfwQ65vN.js", + "name": "FormField", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_kfynmD3Z.js", + "_DgtbvmBB.js" + ] + }, + "_DgtbvmBB.js": { + "file": "_app/immutable/chunks/DgtbvmBB.js", + "name": "input", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_DhEbbC3M.js": { + "file": "_app/immutable/chunks/DhEbbC3M.js", + "name": "IconShield", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_DqoiTw6k.js": { + "file": "_app/immutable/chunks/DqoiTw6k.js", + "name": "IconKey", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_DrzuxmSv.js": { + "file": "_app/immutable/chunks/DrzuxmSv.js", + "name": "IconGlobe", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_DsQCf6vC.js": { + "file": "_app/immutable/chunks/DsQCf6vC.js", + "name": "ProxyForm", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_BSXRhUWv.js", + "_Bpb8V1MF.js", + "_DfwQ65vN.js", + "_CZnXUJhL.js", + "_LFhQE6G2.js", + "_R0-LJft-.js", + "_BFW91e3Y.js", + "_kfynmD3Z.js", + "_C8zo5-Sk.js" + ] + }, + "_EntityPicker.D4Qf6tQ2.css": { + "file": "_app/immutable/assets/EntityPicker.D4Qf6tQ2.css", + "src": "_EntityPicker.D4Qf6tQ2.css" + }, + "_Hsiz6fBZ.js": { + "file": "_app/immutable/chunks/Hsiz6fBZ.js", + "name": "IconDeploy", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_Icw0y4KW.js": { + "file": "_app/immutable/chunks/Icw0y4KW.js", + "name": "IconChevronRight", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_LFhQE6G2.js": { + "file": "_app/immutable/chunks/LFhQE6G2.js", + "name": "IconCheck", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_R0-LJft-.js": { + "file": "_app/immutable/chunks/R0-LJft-.js", + "name": "IconX", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "_ecfdBtDb.js": { + "file": "_app/immutable/chunks/ecfdBtDb.js", + "name": "svelte-head", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_ip4Jv8C8.js": { + "file": "_app/immutable/chunks/ip4Jv8C8.js", + "name": "SkeletonCard", + "imports": [ + "_BJdXET8u.js", + "_BSEsuAwr.js", + "_DKemW7Dm.js", + "_BE_zO38m.js" + ] + }, + "_kfynmD3Z.js": { + "file": "_app/immutable/chunks/kfynmD3Z.js", + "name": "index", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_phMGo29-.js": { + "file": "_app/immutable/chunks/phMGo29-.js", + "name": "index-client", + "imports": [ + "_DKemW7Dm.js" + ] + }, + "_scnZuc49.js": { + "file": "_app/immutable/chunks/scnZuc49.js", + "name": "IconTrash", + "imports": [ + "_BJdXET8u.js", + "_DKemW7Dm.js", + "_kfynmD3Z.js", + "_BSXRhUWv.js" + ] + }, + "node_modules/@sveltejs/kit/src/runtime/client/entry.js": { + "file": "_app/immutable/entry/start.BU-sFgwv.js", + "name": "entry/start", + "src": "node_modules/@sveltejs/kit/src/runtime/client/entry.js", + "isEntry": true, + "imports": [ + "_CWhLh9u1.js" + ] + } +} \ No newline at end of file diff --git a/web/.svelte-kit/output/client/_app/immutable/assets/0.DnmtykcB.css b/web/.svelte-kit/output/client/_app/immutable/assets/0.DnmtykcB.css new file mode 100644 index 0000000..b93e6c6 --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/assets/0.DnmtykcB.css @@ -0,0 +1 @@ +/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-900:oklch(41.4% .112 45.904);--color-amber-950:oklch(27.9% .077 45.635);--color-yellow-400:oklch(85.2% .199 91.936);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-900:oklch(37.8% .077 168.94);--color-emerald-950:oklch(26.2% .051 172.552);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-900:oklch(37.9% .146 265.522);--color-blue-950:oklch(28.2% .091 267.935);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-950:oklch(25.7% .09 281.288);--color-violet-50:oklch(96.9% .016 293.756);--color-violet-300:oklch(81.1% .111 293.571);--color-violet-400:oklch(70.2% .183 293.541);--color-violet-500:oklch(60.6% .25 292.717);--color-violet-700:oklch(49.1% .27 292.581);--color-violet-900:oklch(38% .189 293.745);--color-violet-950:oklch(28.3% .141 291.089);--color-purple-50:oklch(97.7% .014 308.299);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-700:oklch(49.6% .265 301.924);--color-purple-900:oklch(38.1% .176 304.987);--color-purple-950:oklch(29.1% .149 302.717);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-sm:24rem;--container-md:28rem;--container-2xl:42rem;--container-4xl:56rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--shadow-sm:0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;--shadow-md:0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;--shadow-lg:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--shadow-xl:0 20px 25px -5px #0000001a, 0 8px 10px -6px #0000001a;--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.inset-y-0{inset-block:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.top-1\/2{top:50%}.top-4{top:calc(var(--spacing) * 4)}.right-4{right:calc(var(--spacing) * 4)}.left-0{left:calc(var(--spacing) * 0)}.left-2\.5{left:calc(var(--spacing) * 2.5)}.left-3{left:calc(var(--spacing) * 3)}.z-40{z-index:40}.z-50{z-index:50}.z-\[100\]{z-index:100}.col-span-full{grid-column:1/-1}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mx-0\.5{margin-inline:calc(var(--spacing) * .5)}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-3{margin-left:calc(var(--spacing) * 3)}.ml-7{margin-left:calc(var(--spacing) * 7)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-4\.5{height:calc(var(--spacing) * 4.5)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-\[38px\]{height:38px}.h-full{height:100%}.h-screen{height:100vh}.min-h-\[1\.5rem\]{min-height:1.5rem}.min-h-screen{min-height:100vh}.w-0\.5{width:calc(var(--spacing) * .5)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-4\.5{width:calc(var(--spacing) * 4.5)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-12{width:calc(var(--spacing) * 12)}.w-16{width:calc(var(--spacing) * 16)}.w-24{width:calc(var(--spacing) * 24)}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.w-px{width:1px}.max-w-2xl{max-width:var(--container-2xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-7xl{max-width:var(--container-7xl)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[180px\]{min-width:180px}.min-w-full{min-width:100%}.flex-1{flex:1}.flex-shrink{flex-shrink:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.-translate-x-full{--tw-translate-x:-100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-0{--tw-translate-x:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-90{rotate:90deg}.rotate-180{rotate:180deg}.animate-ping{animation:var(--animate-ping)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-y-1{row-gap:calc(var(--spacing) * 1)}.gap-y-1\.5{row-gap:calc(var(--spacing) * 1.5)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-\[var\(--border-primary\)\]>:not(:last-child)){border-color:var(--border-primary)}:where(.divide-\[var\(--border-secondary\)\]>:not(:last-child)){border-color:var(--border-secondary)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-\[var\(--border-input\)\]{border-color:var(--border-input)}.border-\[var\(--border-primary\)\]{border-color:var(--border-primary)}.border-\[var\(--border-secondary\)\]{border-color:var(--border-secondary)}.border-\[var\(--color-danger\)\]{border-color:var(--color-danger)}.border-\[var\(--color-danger-light\)\]{border-color:var(--color-danger-light)}.border-red-200{border-color:var(--color-red-200)}.border-red-300{border-color:var(--color-red-300)}.bg-\[var\(--border-primary\)\]{background-color:var(--border-primary)}.bg-\[var\(--color-brand-50\)\],.bg-\[var\(--color-brand-50\)\]\/30{background-color:var(--color-brand-50)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--color-brand-50\)\]\/30{background-color:color-mix(in oklab,var(--color-brand-50) 30%,transparent)}}.bg-\[var\(--color-brand-100\)\]{background-color:var(--color-brand-100)}.bg-\[var\(--color-brand-600\)\]{background-color:var(--color-brand-600)}.bg-\[var\(--color-danger\)\]{background-color:var(--color-danger)}.bg-\[var\(--color-danger-light\)\]{background-color:var(--color-danger-light)}.bg-\[var\(--color-info\)\]{background-color:var(--color-info)}.bg-\[var\(--color-success\)\]{background-color:var(--color-success)}.bg-\[var\(--color-warning\)\]{background-color:var(--color-warning)}.bg-\[var\(--surface-card\)\]{background-color:var(--surface-card)}.bg-\[var\(--surface-card-hover\)\]{background-color:var(--surface-card-hover)}.bg-\[var\(--surface-input\)\]{background-color:var(--surface-input)}.bg-\[var\(--surface-overlay\)\]{background-color:var(--surface-overlay)}.bg-\[var\(--surface-page\)\]{background-color:var(--surface-page)}.bg-\[var\(--surface-sidebar\)\]{background-color:var(--surface-sidebar)}.bg-\[var\(--text-tertiary\)\]{background-color:var(--text-tertiary)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-400{background-color:var(--color-blue-400)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-emerald-400{background-color:var(--color-emerald-400)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-300{background-color:var(--color-gray-300)}.bg-gray-400{background-color:var(--color-gray-400)}.bg-indigo-50{background-color:var(--color-indigo-50)}.bg-purple-50{background-color:var(--color-purple-50)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-400{background-color:var(--color-red-400)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-violet-50{background-color:var(--color-violet-50)}.bg-violet-500{background-color:var(--color-violet-500)}.bg-yellow-400{background-color:var(--color-yellow-400)}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:calc(var(--spacing) * 1)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-16{padding-block:calc(var(--spacing) * 16)}.py-20{padding-block:calc(var(--spacing) * 20)}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-\[26px\]{padding-top:26px}.pr-3{padding-right:calc(var(--spacing) * 3)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pl-8{padding-left:calc(var(--spacing) * 8)}.pl-9{padding-left:calc(var(--spacing) * 9)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.text-\[var\(--color-brand-500\)\]{color:var(--color-brand-500)}.text-\[var\(--color-brand-600\)\]{color:var(--color-brand-600)}.text-\[var\(--color-brand-700\)\]{color:var(--color-brand-700)}.text-\[var\(--color-danger\)\]{color:var(--color-danger)}.text-\[var\(--text-link\)\]{color:var(--text-link)}.text-\[var\(--text-primary\)\]{color:var(--text-primary)}.text-\[var\(--text-secondary\)\]{color:var(--text-secondary)}.text-\[var\(--text-tertiary\)\]{color:var(--text-tertiary)}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-emerald-600{color:var(--color-emerald-600)}.text-emerald-700{color:var(--color-emerald-700)}.text-gray-400{color:var(--color-gray-400)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-indigo-700{color:var(--color-indigo-700)}.text-purple-700{color:var(--color-purple-700)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-violet-700{color:var(--color-violet-700)}.text-white{color:var(--color-white)}.text-white\/70{color:#ffffffb3}@supports (color:color-mix(in lab,red,red)){.text-white\/70{color:color-mix(in oklab,var(--color-white) 70%,transparent)}}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.line-through{text-decoration-line:line-through}.underline{text-decoration-line:underline}.decoration-1{text-decoration-thickness:1px}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.shadow-\[var\(--shadow-lg\)\]{--tw-shadow:var(--shadow-lg);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[var\(--shadow-sm\)\]{--tw-shadow:var(--shadow-sm);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring,.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-\[var\(--border-primary\)\]{--tw-ring-color:var(--border-primary)}.ring-amber-300{--tw-ring-color:var(--color-amber-300)}.ring-blue-300{--tw-ring-color:var(--color-blue-300)}.ring-red-300{--tw-ring-color:var(--color-red-300)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.select-none{-webkit-user-select:none;user-select:none}@media(hover:hover){.group-hover\:bg-\[var\(--color-brand-100\)\]:is(:where(.group):hover *){background-color:var(--color-brand-100)}.group-hover\:text-\[var\(--text-secondary\)\]:is(:where(.group):hover *){color:var(--text-secondary)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.placeholder\:text-\[var\(--text-tertiary\)\]::placeholder{color:var(--text-tertiary)}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media(hover:hover){.hover\:-translate-y-0\.5:hover{--tw-translate-y:calc(var(--spacing) * -.5);translate:var(--tw-translate-x) var(--tw-translate-y)}.hover\:border-\[var\(--color-brand-300\)\]:hover{border-color:var(--color-brand-300)}.hover\:bg-\[var\(--color-brand-700\)\]:hover{background-color:var(--color-brand-700)}.hover\:bg-\[var\(--color-danger-dark\)\]:hover{background-color:var(--color-danger-dark)}.hover\:bg-\[var\(--color-danger-light\)\]:hover{background-color:var(--color-danger-light)}.hover\:bg-\[var\(--color-info-dark\)\]:hover{background-color:var(--color-info-dark)}.hover\:bg-\[var\(--color-success-dark\)\]:hover{background-color:var(--color-success-dark)}.hover\:bg-\[var\(--surface-card\)\]:hover{background-color:var(--surface-card)}.hover\:bg-\[var\(--surface-card-hover\)\]:hover{background-color:var(--surface-card-hover)}.hover\:bg-amber-50:hover{background-color:var(--color-amber-50)}.hover\:bg-blue-50:hover{background-color:var(--color-blue-50)}.hover\:bg-emerald-50:hover{background-color:var(--color-emerald-50)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-red-100:hover{background-color:var(--color-red-100)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:text-\[var\(--color-brand-600\)\]:hover{color:var(--color-brand-600)}.hover\:text-\[var\(--color-brand-700\)\]:hover{color:var(--color-brand-700)}.hover\:text-\[var\(--color-danger\)\]:hover{color:var(--color-danger)}.hover\:text-\[var\(--text-link\)\]:hover{color:var(--text-link)}.hover\:text-\[var\(--text-link-hover\)\]:hover{color:var(--text-link-hover)}.hover\:text-\[var\(--text-primary\)\]:hover{color:var(--text-primary)}.hover\:text-\[var\(--text-secondary\)\]:hover{color:var(--text-secondary)}.hover\:text-amber-600:hover{color:var(--color-amber-600)}.hover\:text-blue-600:hover{color:var(--color-blue-600)}.hover\:text-emerald-600:hover{color:var(--color-emerald-600)}.hover\:text-red-600:hover{color:var(--color-red-600)}.hover\:text-white:hover{color:var(--color-white)}.hover\:no-underline:hover{text-decoration-line:none}.hover\:opacity-90:hover{opacity:.9}.hover\:shadow-\[var\(--shadow-md\)\]:hover{--tw-shadow:var(--shadow-md);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\:border-\[var\(--color-brand-400\)\]:focus{border-color:var(--color-brand-400)}.focus\:border-\[var\(--color-brand-500\)\]:focus{border-color:var(--color-brand-500)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-\[var\(--color-brand-400\)\]:focus{--tw-ring-color:var(--color-brand-400)}.focus\:ring-\[var\(--color-brand-500\)\]:focus{--tw-ring-color:var(--color-brand-500)}.focus\:ring-\[var\(--color-danger\)\]:focus{--tw-ring-color:var(--color-danger)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:outline:focus-visible{outline-style:var(--tw-outline-style);outline-width:1px}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\:outline-\[var\(--color-brand-600\)\]:focus-visible{outline-color:var(--color-brand-600)}.focus-visible\:outline-\[var\(--color-danger\)\]:focus-visible{outline-color:var(--color-danger)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:40rem){.sm\:block{display:block}.sm\:w-48{width:calc(var(--spacing) * 48)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.sm\:flex-col{flex-direction:column}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}:where(.sm\:space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}.sm\:py-8{padding-block:calc(var(--spacing) * 8)}}@media(min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(min-width:64rem){.lg\:static{position:static}.lg\:hidden{display:none}.lg\:translate-x-0{--tw-translate-x:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media(prefers-color-scheme:dark){.dark\:border-red-700{border-color:var(--color-red-700)}.dark\:border-red-900{border-color:var(--color-red-900)}.dark\:bg-\[var\(--color-brand-900\)\]\/10{background-color:var(--color-brand-900)}@supports (color:color-mix(in lab,red,red)){.dark\:bg-\[var\(--color-brand-900\)\]\/10{background-color:color-mix(in oklab,var(--color-brand-900) 10%,transparent)}}.dark\:bg-amber-500{background-color:var(--color-amber-500)}.dark\:bg-amber-900\/30{background-color:#7b33064d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-amber-900\/30{background-color:color-mix(in oklab,var(--color-amber-900) 30%,transparent)}}.dark\:bg-amber-900\/40{background-color:#7b330666}@supports (color:color-mix(in lab,red,red)){.dark\:bg-amber-900\/40{background-color:color-mix(in oklab,var(--color-amber-900) 40%,transparent)}}.dark\:bg-amber-950{background-color:var(--color-amber-950)}.dark\:bg-blue-500{background-color:var(--color-blue-500)}.dark\:bg-blue-900\/30{background-color:#1c398e4d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-900\/30{background-color:color-mix(in oklab,var(--color-blue-900) 30%,transparent)}}.dark\:bg-blue-900\/40{background-color:#1c398e66}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-900\/40{background-color:color-mix(in oklab,var(--color-blue-900) 40%,transparent)}}.dark\:bg-blue-950{background-color:var(--color-blue-950)}.dark\:bg-emerald-900\/30{background-color:#004e3b4d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-emerald-900\/30{background-color:color-mix(in oklab,var(--color-emerald-900) 30%,transparent)}}.dark\:bg-emerald-950{background-color:var(--color-emerald-950)}.dark\:bg-gray-800{background-color:var(--color-gray-800)}.dark\:bg-indigo-950{background-color:var(--color-indigo-950)}.dark\:bg-purple-900\/30{background-color:#59168b4d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-purple-900\/30{background-color:color-mix(in oklab,var(--color-purple-900) 30%,transparent)}}.dark\:bg-purple-950{background-color:var(--color-purple-950)}.dark\:bg-red-500{background-color:var(--color-red-500)}.dark\:bg-red-900\/30{background-color:#82181a4d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-red-900\/30{background-color:color-mix(in oklab,var(--color-red-900) 30%,transparent)}}.dark\:bg-red-900\/40{background-color:#82181a66}@supports (color:color-mix(in lab,red,red)){.dark\:bg-red-900\/40{background-color:color-mix(in oklab,var(--color-red-900) 40%,transparent)}}.dark\:bg-red-950{background-color:var(--color-red-950)}.dark\:bg-red-950\/30{background-color:#4608094d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-red-950\/30{background-color:color-mix(in oklab,var(--color-red-950) 30%,transparent)}}.dark\:bg-violet-900\/30{background-color:#4d179a4d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-violet-900\/30{background-color:color-mix(in oklab,var(--color-violet-900) 30%,transparent)}}.dark\:bg-violet-950{background-color:var(--color-violet-950)}.dark\:text-amber-300{color:var(--color-amber-300)}.dark\:text-amber-400{color:var(--color-amber-400)}.dark\:text-blue-300{color:var(--color-blue-300)}.dark\:text-blue-400{color:var(--color-blue-400)}.dark\:text-emerald-300{color:var(--color-emerald-300)}.dark\:text-emerald-400{color:var(--color-emerald-400)}.dark\:text-gray-300{color:var(--color-gray-300)}.dark\:text-gray-400{color:var(--color-gray-400)}.dark\:text-indigo-300{color:var(--color-indigo-300)}.dark\:text-purple-300{color:var(--color-purple-300)}.dark\:text-purple-400{color:var(--color-purple-400)}.dark\:text-red-300{color:var(--color-red-300)}.dark\:text-red-400{color:var(--color-red-400)}.dark\:text-violet-300{color:var(--color-violet-300)}.dark\:text-violet-400{color:var(--color-violet-400)}.dark\:ring-amber-700{--tw-ring-color:var(--color-amber-700)}.dark\:ring-blue-700{--tw-ring-color:var(--color-blue-700)}.dark\:ring-red-700{--tw-ring-color:var(--color-red-700)}@media(hover:hover){.dark\:hover\:bg-red-900\/30:hover{background-color:#82181a4d}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-red-900\/30:hover{background-color:color-mix(in oklab,var(--color-red-900) 30%,transparent)}}.dark\:hover\:bg-red-950:hover{background-color:var(--color-red-950)}}}}:root{--color-brand-50:#eef2ff;--color-brand-100:#e0e7ff;--color-brand-200:#c7d2fe;--color-brand-300:#a5b4fc;--color-brand-400:#818cf8;--color-brand-500:#6366f1;--color-brand-600:#4f46e5;--color-brand-700:#4338ca;--color-brand-800:#3730a3;--color-brand-900:#312e81;--color-success:#16a34a;--color-success-light:#dcfce7;--color-success-dark:#15803d;--color-warning:#d97706;--color-warning-light:#fef3c7;--color-warning-dark:#b45309;--color-danger:#dc2626;--color-danger-light:#fee2e2;--color-danger-dark:#b91c1c;--color-info:#2563eb;--color-info-light:#dbeafe;--color-info-dark:#1d4ed8;--surface-page:#f8fafc;--surface-card:#fff;--surface-card-hover:#f8fafc;--surface-sidebar:#fff;--surface-overlay:#0000004d;--surface-input:#fff;--border-primary:#e2e8f0;--border-secondary:#f1f5f9;--border-focus:var(--color-brand-500);--border-input:#cbd5e1;--text-primary:#0f172a;--text-secondary:#475569;--text-tertiary:#94a3b8;--text-inverse:#fff;--text-link:var(--color-brand-600);--text-link-hover:var(--color-brand-700);--space-0:0;--space-1:.25rem;--space-2:.5rem;--space-3:.75rem;--space-4:1rem;--space-5:1.25rem;--space-6:1.5rem;--space-8:2rem;--space-10:2.5rem;--space-12:3rem;--space-16:4rem;--font-family-sans:"Inter", ui-sans-serif, system-ui, -apple-system, sans-serif;--font-family-mono:"JetBrains Mono", ui-monospace, "Cascadia Code", monospace;--text-xs:.75rem;--text-sm:.875rem;--text-base:1rem;--text-lg:1.125rem;--text-xl:1.25rem;--text-2xl:1.5rem;--text-3xl:1.875rem;--leading-tight:1.25;--leading-normal:1.5;--leading-relaxed:1.625;--weight-normal:400;--weight-medium:500;--weight-semibold:600;--weight-bold:700;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--radius-full:9999px;--shadow-sm:0 1px 2px 0 #0000000d;--shadow-md:0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;--shadow-lg:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--shadow-xl:0 20px 25px -5px #0000001a, 0 8px 10px -6px #0000001a;--transition-fast:.15s cubic-bezier(.4, 0, .2, 1);--transition-normal:.2s cubic-bezier(.4, 0, .2, 1);--transition-slow:.3s cubic-bezier(.4, 0, .2, 1);--sidebar-width:16rem;--sidebar-collapsed-width:0;--topbar-height:4rem}[data-theme=dark]{--surface-page:#0f172a;--surface-card:#1e293b;--surface-card-hover:#334155;--surface-sidebar:#1e293b;--surface-overlay:#0009;--surface-input:#1e293b;--border-primary:#334155;--border-secondary:#1e293b;--border-focus:var(--color-brand-400);--border-input:#475569;--text-primary:#f1f5f9;--text-secondary:#94a3b8;--text-tertiary:#64748b;--text-inverse:#0f172a;--text-link:var(--color-brand-400);--text-link-hover:var(--color-brand-300);--color-success:#22c55e;--color-success-light:#14532d;--color-warning:#f59e0b;--color-warning-light:#451a03;--color-danger:#ef4444;--color-danger-light:#450a0a;--color-info:#3b82f6;--color-info-light:#172554;--shadow-sm:0 1px 2px 0 #0000004d;--shadow-md:0 4px 6px -1px #0006, 0 2px 4px -2px #0000004d;--shadow-lg:0 10px 15px -3px #0006, 0 4px 6px -4px #0000004d;--shadow-xl:0 20px 25px -5px #0006, 0 8px 10px -6px #0000004d}@keyframes pulse-status{0%,to{opacity:1}50%{opacity:.5}}@keyframes slide-in-right{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}@keyframes slide-out-right{0%{opacity:1;transform:translate(0)}to{opacity:0;transform:translate(100%)}}@keyframes skeleton-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes scale-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes button-press{0%,to{transform:scale(1)}50%{transform:scale(.97)}}.animate-pulse-status{animation:2s cubic-bezier(.4,0,.6,1) infinite pulse-status}.animate-slide-in{animation:slide-in-right var(--transition-slow) forwards}.animate-slide-out{animation:slide-out-right var(--transition-slow) forwards}.animate-fade-in{animation:fade-in var(--transition-normal) forwards}.animate-scale-in{animation:scale-in var(--transition-normal) forwards}.active\:animate-press:active{animation:.15s ease-in-out button-press}.skeleton{background:linear-gradient(90deg,var(--border-secondary) 25%,var(--border-primary) 50%,var(--border-secondary) 75%);border-radius:var(--radius-md);background-size:200% 100%;animation:1.5s ease-in-out infinite skeleton-shimmer}.toggle-switch{background-color:var(--border-primary);border-radius:var(--radius-full);cursor:pointer;width:2.75rem;height:1.5rem;transition:background-color var(--transition-fast);position:relative}.toggle-switch[aria-checked=true]{background-color:var(--color-brand-600)}.toggle-switch:after{content:"";border-radius:var(--radius-full);width:1.25rem;height:1.25rem;box-shadow:var(--shadow-sm);transition:transform var(--transition-fast);background-color:#fff;position:absolute;top:.125rem;left:.125rem}.toggle-switch[aria-checked=true]:after{transform:translate(1.25rem)}html,body{height:100%;font-family:var(--font-family-sans);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:var(--surface-page);color:var(--text-primary);margin:0;padding:0;overflow:hidden}input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.focus-ring:focus-visible{outline:2px solid var(--border-focus);outline-offset:2px}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--border-primary);border-radius:var(--radius-full)}::-webkit-scrollbar-thumb:hover{background:var(--text-tertiary)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}} diff --git a/web/.svelte-kit/output/client/_app/immutable/assets/EntityPicker.D4Qf6tQ2.css b/web/.svelte-kit/output/client/_app/immutable/assets/EntityPicker.D4Qf6tQ2.css new file mode 100644 index 0000000..a003d75 --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/assets/EntityPicker.D4Qf6tQ2.css @@ -0,0 +1 @@ +.entity-picker-backdrop.svelte-1bxz98v{position:fixed;top:0;right:0;bottom:0;left:0;z-index:60;background:var(--surface-overlay);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);animation:fade-in var(--transition-normal) forwards}.entity-picker-container.svelte-1bxz98v{position:fixed;top:0;right:0;bottom:0;left:0;z-index:61;display:flex;align-items:flex-start;justify-content:center;padding-top:12vh;pointer-events:none}.entity-picker-modal.svelte-1bxz98v{pointer-events:auto;width:90vw;max-width:500px;background:var(--surface-card);border:1px solid var(--border-primary);border-radius:var(--radius-xl);box-shadow:var(--shadow-xl);overflow:hidden;animation:scale-in var(--transition-normal) forwards;display:flex;flex-direction:column}.entity-picker-header.svelte-1bxz98v{display:flex;align-items:center;justify-content:space-between;padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border-secondary)}.entity-picker-title.svelte-1bxz98v{font-size:var(--text-sm);font-weight:var(--weight-semibold);color:var(--text-primary);margin:0}.entity-picker-close.svelte-1bxz98v{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;border-radius:var(--radius-md);background:transparent;color:var(--text-tertiary);cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.entity-picker-close.svelte-1bxz98v:hover{background:var(--surface-card-hover);color:var(--text-primary)}.entity-picker-search.svelte-1bxz98v{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border-secondary)}.entity-picker-search-icon{flex-shrink:0;color:var(--text-tertiary)}.entity-picker-search-input.svelte-1bxz98v{flex:1;border:none;outline:none;background:transparent;font-size:var(--text-sm);color:var(--text-primary);font-family:var(--font-family-sans)}.entity-picker-search-input.svelte-1bxz98v::placeholder{color:var(--text-tertiary)}.entity-picker-close-inline.svelte-1bxz98v{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--text-tertiary);cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.entity-picker-close-inline.svelte-1bxz98v:hover{background:var(--surface-card-hover);color:var(--text-primary)}.entity-picker-list.svelte-1bxz98v{overflow-y:auto;max-height:60vh;padding:var(--space-1) 0}.entity-picker-empty.svelte-1bxz98v{padding:var(--space-8) var(--space-4);text-align:center;font-size:var(--text-sm);color:var(--text-tertiary)}.entity-picker-group-header.svelte-1bxz98v{padding:var(--space-2) var(--space-4) var(--space-1);font-size:var(--text-xs);font-weight:var(--weight-semibold);color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.05em}.entity-picker-item.svelte-1bxz98v{display:flex;align-items:center;gap:var(--space-3);width:100%;padding:var(--space-2) var(--space-4);border:none;background:transparent;cursor:pointer;text-align:left;font-family:var(--font-family-sans);transition:background var(--transition-fast);border-left:3px solid transparent}.entity-picker-item--highlighted.svelte-1bxz98v{background:var(--surface-card-hover)}.entity-picker-item--current.svelte-1bxz98v{border-left-color:var(--color-brand-500)}.entity-picker-item-icon.svelte-1bxz98v{flex-shrink:0;width:20px;height:20px;display:flex;align-items:center;justify-content:center;color:var(--text-tertiary)}.entity-picker-item-content.svelte-1bxz98v{display:flex;flex-direction:column;gap:1px;min-width:0}.entity-picker-item-label.svelte-1bxz98v{font-size:var(--text-sm);font-weight:var(--weight-medium);color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.entity-picker-item-description.svelte-1bxz98v{font-size:var(--text-xs);color:var(--text-tertiary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.entity-picker-item--disabled.svelte-1bxz98v{opacity:.45;cursor:default;pointer-events:none}.entity-picker-item-hint.svelte-1bxz98v{font-size:var(--text-xs);color:var(--text-tertiary);font-style:italic;white-space:nowrap} diff --git a/web/.svelte-kit/output/client/_app/immutable/chunks/BE_zO38m.js b/web/.svelte-kit/output/client/_app/immutable/chunks/BE_zO38m.js new file mode 100644 index 0000000..68523f7 --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/chunks/BE_zO38m.js @@ -0,0 +1 @@ +import{a as d,b as h}from"./BJdXET8u.js";import{Q as f,t as n}from"./DKemW7Dm.js";import{b as m,a as c}from"./kfynmD3Z.js";import{p as r}from"./BSXRhUWv.js";function p(t,e,l,i){var a=t.__style;if(f||a!==e){var s=m(e);(!f||s!==t.getAttribute("style"))&&(s==null?t.removeAttribute("style"):t.style.cssText=s),t.__style=e}return i}var u=h('');function g(t,e){const l=r(e,"class",3,""),i=r(e,"width",3,"100%"),a=r(e,"height",3,"1rem"),s=r(e,"rounded",3,!1);var o=u();n(()=>{c(o,1,`skeleton ${l()??""}`),p(o,`width: ${i()??""}; height: ${a()??""}; ${s()?"border-radius: 9999px;":""}`)}),d(t,o)}export{g as S,p as s}; diff --git a/web/.svelte-kit/output/client/_app/immutable/chunks/BFW91e3Y.js b/web/.svelte-kit/output/client/_app/immutable/chunks/BFW91e3Y.js new file mode 100644 index 0000000..bc64f73 --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/chunks/BFW91e3Y.js @@ -0,0 +1 @@ +import{a as n,f as p}from"./BJdXET8u.js";import{t as m}from"./DKemW7Dm.js";import{s,a as f}from"./kfynmD3Z.js";import{p as a}from"./BSXRhUWv.js";var c=p('');function g(e,o){const r=a(o,"size",3,20),i=a(o,"class",3,"");var t=c();m(()=>{s(t,"width",r()),s(t,"height",r()),f(t,0,`animate-spin ${i()??""}`)}),n(e,t)}export{g as I}; diff --git a/web/.svelte-kit/output/client/_app/immutable/chunks/BJdXET8u.js b/web/.svelte-kit/output/client/_app/immutable/chunks/BJdXET8u.js new file mode 100644 index 0000000..a9a308b --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/chunks/BJdXET8u.js @@ -0,0 +1,2 @@ +var ke=Object.defineProperty;var ve=t=>{throw TypeError(t)};var We=(t,e,r)=>e in t?ke(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var Z=(t,e,r)=>We(t,typeof e!="symbol"?e+"":e,r),ae=(t,e,r)=>e.has(t)||ve("Cannot "+r);var s=(t,e,r)=>(ae(t,e,"read from private field"),r?r.call(t):e.get(t)),h=(t,e,r)=>e.has(t)?ve("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,r),o=(t,e,r,a)=>(ae(t,e,"write to private field"),a?a.call(t,r):e.set(t,r),r),v=(t,e,r)=>(ae(t,e,"access private method"),r);import{aS as xe,g as Re,B as Ve,o as $e,aT as ge,Z as B,af as Se,W as _,Q as w,C as F,aU as be,l as Be,a0 as Ae,a2 as Ye,aV as me,a7 as P,N as Y,aj as ie,H as ye,ao as Ue,aW as je,aX as te,aY as re,aZ as Te,a_ as qe,a$ as Xe,b0 as Oe,m as De,a5 as ze,ap as fe,V as U,F as Ze,a3 as Ge,b1 as G,E as Je,P as Ke,b2 as Qe,b3 as et,I as tt,b4 as rt,aA as st,au as nt,X as j,b5 as at,b6 as it,b7 as ft,b8 as ot,b9 as lt,ba as ut,bb as le,R as Me,aK as dt,T as ht,at as ue,U as J,bc as ct,an as _t,bd as pt,ab as vt,p as gt,a4 as bt,as as mt,e as yt}from"./DKemW7Dm.js";function Tt(t){let e=0,r=Se(0),a;return()=>{xe()&&(Re(r),Ve(()=>(e===0&&(a=$e(()=>t(()=>ge(r)))),e+=1,()=>{B(()=>{e-=1,e===0&&(a==null||a(),a=void 0,ge(r))})})))}}var Et=Je|Ke;function wt(t,e,r,a){new Nt(t,e,r,a)}var T,q,R,k,g,S,E,N,O,W,L,V,X,z,D,se,u,Le,Fe,Ie,de,Q,ee,he;class Nt{constructor(e,r,a,f){h(this,u);Z(this,"parent");Z(this,"is_pending",!1);Z(this,"transform_error");h(this,T);h(this,q,w?_:null);h(this,R);h(this,k);h(this,g);h(this,S,null);h(this,E,null);h(this,N,null);h(this,O,null);h(this,W,0);h(this,L,0);h(this,V,!1);h(this,X,new Set);h(this,z,new Set);h(this,D,null);h(this,se,Tt(()=>(o(this,D,Se(s(this,W))),()=>{o(this,D,null)})));var n;o(this,T,e),o(this,R,r),o(this,k,i=>{var d=F;d.b=this,d.f|=be,a(i)}),this.parent=F.b,this.transform_error=f??((n=this.parent)==null?void 0:n.transform_error)??(i=>i),o(this,g,Be(()=>{if(w){const i=s(this,q);Ae();const d=i.data===Ye;if(i.data.startsWith(me)){const c=JSON.parse(i.data.slice(me.length));v(this,u,Fe).call(this,c)}else d?v(this,u,Ie).call(this):v(this,u,Le).call(this)}else v(this,u,de).call(this)},Et)),w&&o(this,T,_)}defer_effect(e){je(e,s(this,X),s(this,z))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!s(this,R).pending}update_pending_count(e,r){v(this,u,he).call(this,e,r),o(this,W,s(this,W)+e),!(!s(this,D)||s(this,V))&&(o(this,V,!0),B(()=>{o(this,V,!1),s(this,D)&&ze(s(this,D),s(this,W))}))}get_effect_pending(){return s(this,se).call(this),Re(s(this,D))}error(e){var r=s(this,R).onerror;let a=s(this,R).failed;if(!r&&!a)throw e;s(this,S)&&(fe(s(this,S)),o(this,S,null)),s(this,E)&&(fe(s(this,E)),o(this,E,null)),s(this,N)&&(fe(s(this,N)),o(this,N,null)),w&&(U(s(this,q)),Ze(),U(Ge()));var f=!1,n=!1;const i=()=>{if(f){et();return}f=!0,n&&Qe(),s(this,N)!==null&&ie(s(this,N),()=>{o(this,N,null)}),v(this,u,ee).call(this,()=>{v(this,u,de).call(this)})},d=l=>{try{n=!0,r==null||r(l,i),n=!1}catch(c){G(c,s(this,g)&&s(this,g).parent)}a&&o(this,N,v(this,u,ee).call(this,()=>{try{return P(()=>{var c=F;c.b=this,c.f|=be,a(s(this,T),()=>l,()=>i)})}catch(c){return G(c,s(this,g).parent),null}}))};B(()=>{var l;try{l=this.transform_error(e)}catch(c){G(c,s(this,g)&&s(this,g).parent);return}l!==null&&typeof l=="object"&&typeof l.then=="function"?l.then(d,c=>G(c,s(this,g)&&s(this,g).parent)):d(l)})}}T=new WeakMap,q=new WeakMap,R=new WeakMap,k=new WeakMap,g=new WeakMap,S=new WeakMap,E=new WeakMap,N=new WeakMap,O=new WeakMap,W=new WeakMap,L=new WeakMap,V=new WeakMap,X=new WeakMap,z=new WeakMap,D=new WeakMap,se=new WeakMap,u=new WeakSet,Le=function(){try{o(this,S,P(()=>s(this,k).call(this,s(this,T))))}catch(e){this.error(e)}},Fe=function(e){const r=s(this,R).failed;r&&o(this,N,P(()=>{r(s(this,T),()=>e,()=>()=>{})}))},Ie=function(){const e=s(this,R).pending;e&&(this.is_pending=!0,o(this,E,P(()=>e(s(this,T)))),B(()=>{var r=o(this,O,document.createDocumentFragment()),a=Y();r.append(a),o(this,S,v(this,u,ee).call(this,()=>P(()=>s(this,k).call(this,a)))),s(this,L)===0&&(s(this,T).before(r),o(this,O,null),ie(s(this,E),()=>{o(this,E,null)}),v(this,u,Q).call(this,ye))}))},de=function(){try{if(this.is_pending=this.has_pending_snippet(),o(this,L,0),o(this,W,0),o(this,S,P(()=>{s(this,k).call(this,s(this,T))})),s(this,L)>0){var e=o(this,O,document.createDocumentFragment());Ue(s(this,S),e);const r=s(this,R).pending;o(this,E,P(()=>r(s(this,T))))}else v(this,u,Q).call(this,ye)}catch(r){this.error(r)}},Q=function(e){this.is_pending=!1,e.transfer_effects(s(this,X),s(this,z))},ee=function(e){var r=F,a=Oe,f=De;te(s(this,g)),re(s(this,g)),Te(s(this,g).ctx);try{return qe.ensure(),e()}catch(n){return Xe(n),null}finally{te(r),re(a),Te(f)}},he=function(e,r){var a;if(!this.has_pending_snippet()){this.parent&&v(a=this.parent,u,he).call(a,e,r);return}o(this,L,s(this,L)+e),s(this,L)===0&&(v(this,u,Q).call(this,r),s(this,E)&&ie(s(this,E),()=>{o(this,E,null)}),s(this,O)&&(s(this,T).before(s(this,O)),o(this,O,null)))};const Rt=["touchstart","touchmove"];function St(t){return Rt.includes(t)}const H=Symbol("events"),Ce=new Set,ce=new Set;function At(t,e,r,a={}){function f(n){if(a.capture||_e.call(e,n),!n.cancelBubble)return rt(()=>r==null?void 0:r.call(this,n))}return t.startsWith("pointer")||t.startsWith("touch")||t==="wheel"?B(()=>{e.addEventListener(t,f,a)}):e.addEventListener(t,f,a),f}function Ct(t,e,r,a,f){var n={capture:a,passive:f},i=At(t,e,r,n);(e===document.body||e===window||e===document||e instanceof HTMLMediaElement)&&tt(()=>{e.removeEventListener(t,i,n)})}function Pt(t,e,r){(e[H]??(e[H]={}))[t]=r}function Ht(t){for(var e=0;e{throw C});throw M}}finally{t[H]=e,delete t.currentTarget,re(x),te($)}}}var we;const oe=((we=globalThis==null?void 0:globalThis.window)==null?void 0:we.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:t=>t});function Ot(t){return(oe==null?void 0:oe.createHTML(t))??t}function Pe(t){var e=nt("template");return e.innerHTML=Ot(t.replaceAll("","")),e.content}function A(t,e){var r=F;r.nodes===null&&(r.nodes={start:t,end:e,a:null,t:null})}function kt(t,e){var r=(e&it)!==0,a=(e&ft)!==0,f,n=!t.startsWith("");return()=>{if(w)return A(_,null),_;f===void 0&&(f=Pe(n?t:""+t),r||(f=j(f)));var i=a||at?document.importNode(f,!0):f.cloneNode(!0);if(r){var d=j(i),l=i.lastChild;A(d,l)}else A(i,i);return i}}function Dt(t,e,r="svg"){var a=!t.startsWith(""),f=`<${r}>${a?t:""+t}`,n;return()=>{if(w)return A(_,null),_;if(!n){var i=Pe(f),d=j(i);n=j(d)}var l=n.cloneNode(!0);return A(l,l),l}}function Wt(t,e){return Dt(t,e,"svg")}function xt(t=""){if(!w){var e=Y(t+"");return A(e,e),e}var r=_;return r.nodeType!==lt?(r.before(r=Y()),U(r)):ut(r),A(r,r),r}function Vt(){if(w)return A(_,null),_;var t=document.createDocumentFragment(),e=document.createComment(""),r=Y();return t.append(e,r),A(e,r),t}function $t(t,e){if(w){var r=F;((r.f&ot)===0||r.nodes.end===null)&&(r.nodes.end=_),Ae();return}t!==null&&t.before(e)}function Bt(t,e){var r=e==null?"":typeof e=="object"?`${e}`:e;r!==(t.__t??(t.__t=t.nodeValue))&&(t.__t=r,t.nodeValue=`${r}`)}function Mt(t,e){return He(t,e)}function Yt(t,e){le(),e.intro=e.intro??!1;const r=e.target,a=w,f=_;try{for(var n=j(r);n&&(n.nodeType!==Me||n.data!==dt);)n=ht(n);if(!n)throw ue;J(!0),U(n);const i=He(t,{...e,anchor:n});return J(!1),i}catch(i){if(i instanceof Error&&i.message.split(` +`).some(d=>d.startsWith("https://svelte.dev/e/")))throw i;return i!==ue&&console.warn("Failed to hydrate: ",i),e.recover===!1&&ct(),le(),_t(r),J(!1),Mt(t,e)}finally{J(a),U(f)}}const K=new Map;function He(t,{target:e,anchor:r,props:a={},events:f,context:n,intro:i=!0,transformError:d}){le();var l=void 0,c=pt(()=>{var x=r??e.appendChild(Y());wt(x,{pending:()=>{}},b=>{gt({});var p=De;if(n&&(p.c=n),f&&(a.$$events=f),w&&A(b,null),l=t(b,a)||{},w&&(F.nodes.end=_,_===null||_.nodeType!==Me||_.data!==bt))throw mt(),ue;yt()},d);var $=new Set,M=b=>{for(var p=0;p{var I;for(var b of $)for(const y of[e,document]){var p=K.get(y),m=p.get(b);--m==0?(y.removeEventListener(b,_e),p.delete(b),p.size===0&&K.delete(y)):p.set(b,m)}ce.delete(M),x!==r&&((I=x.parentNode)==null||I.removeChild(x))}});return pe.set(l,c),l}let pe=new WeakMap;function Ut(t,e){const r=pe.get(t);return r?(pe.delete(t),r(e)):Promise.resolve()}const Lt="5";var Ne;typeof window<"u"&&((Ne=window.__svelte??(window.__svelte={})).v??(Ne.v=new Set)).add(Lt);export{$t as a,kt as b,Pt as c,Ht as d,Ct as e,Wt as f,Vt as g,A as h,Yt as i,Mt as m,Bt as s,xt as t,Ut as u}; diff --git a/web/.svelte-kit/output/client/_app/immutable/chunks/BPqRr2-s.js b/web/.svelte-kit/output/client/_app/immutable/chunks/BPqRr2-s.js new file mode 100644 index 0000000..cbacaf2 --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/chunks/BPqRr2-s.js @@ -0,0 +1 @@ +import{s as B,a as i,b as p}from"./BJdXET8u.js";import{p as C,c as m,g as t,s as u,r as k,t as c,e as M,u as a}from"./DKemW7Dm.js";import{p as j,i as q}from"./BSXRhUWv.js";import{a as g}from"./kfynmD3Z.js";var D=p(""),E=p(" ");function J(f,e){C(e,!0);const l=j(e,"size",3,"md"),v={running:{bg:"bg-emerald-50 dark:bg-emerald-950",text:"text-emerald-700 dark:text-emerald-300",dot:"bg-emerald-500"},success:{bg:"bg-emerald-50 dark:bg-emerald-950",text:"text-emerald-700 dark:text-emerald-300",dot:"bg-emerald-500"},stopped:{bg:"bg-gray-100 dark:bg-gray-800",text:"text-gray-700 dark:text-gray-300",dot:"bg-gray-400"},failed:{bg:"bg-red-50 dark:bg-red-950",text:"text-red-700 dark:text-red-300",dot:"bg-red-500"},rolled_back:{bg:"bg-red-50 dark:bg-red-950",text:"text-red-700 dark:text-red-300",dot:"bg-red-500"},removing:{bg:"bg-amber-50 dark:bg-amber-950",text:"text-amber-700 dark:text-amber-300",dot:"bg-amber-500"},pending:{bg:"bg-blue-50 dark:bg-blue-950",text:"text-blue-700 dark:text-blue-300",dot:"bg-blue-500"},pulling:{bg:"bg-blue-50 dark:bg-blue-950",text:"text-blue-700 dark:text-blue-300",dot:"bg-blue-500"},starting:{bg:"bg-amber-50 dark:bg-amber-950",text:"text-amber-700 dark:text-amber-300",dot:"bg-amber-500"},configuring_proxy:{bg:"bg-amber-50 dark:bg-amber-950",text:"text-amber-700 dark:text-amber-300",dot:"bg-amber-500"},health_checking:{bg:"bg-violet-50 dark:bg-violet-950",text:"text-violet-700 dark:text-violet-300",dot:"bg-violet-500"}},_={bg:"bg-gray-100 dark:bg-gray-800",text:"text-gray-700 dark:text-gray-300",dot:"bg-gray-400"},r=a(()=>v[e.status]??_),y=a(()=>l()==="sm"?"text-xs px-2 py-0.5":"text-sm px-2.5 py-0.5"),n=a(()=>l()==="sm"?"h-1.5 w-1.5":"h-2 w-2"),h=a(()=>e.status.replace(/_/g," ")),z=a(()=>e.status==="running"||e.status==="pulling"||e.status==="starting"||e.status==="health_checking");var b=E(),d=m(b),o=m(d);{var w=s=>{var x=D();c(()=>g(x,1,`absolute inline-flex h-full w-full animate-ping rounded-full ${t(r).dot??""} opacity-50`)),i(s,x)};q(o,s=>{t(z)&&s(w)})}var S=u(o,2);k(d);var A=u(d);k(b),c(()=>{g(b,1,`inline-flex items-center gap-1.5 rounded-full font-medium ${t(r).bg??""} ${t(r).text??""} ${t(y)??""}`),g(d,1,`relative flex ${t(n)??""}`),g(S,1,`relative inline-flex rounded-full ${t(n)??""} ${t(r).dot??""}`),B(A,` ${t(h)??""}`)}),i(f,b),M()}export{J as S}; diff --git a/web/.svelte-kit/output/client/_app/immutable/chunks/BSEsuAwr.js b/web/.svelte-kit/output/client/_app/immutable/chunks/BSEsuAwr.js new file mode 100644 index 0000000..f826270 --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/chunks/BSEsuAwr.js @@ -0,0 +1 @@ +import{z as a}from"./DKemW7Dm.js";a(); diff --git a/web/.svelte-kit/output/client/_app/immutable/chunks/BSXRhUWv.js b/web/.svelte-kit/output/client/_app/immutable/chunks/BSXRhUWv.js new file mode 100644 index 0000000..7315aed --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/chunks/BSXRhUWv.js @@ -0,0 +1 @@ +var J=Object.defineProperty;var L=t=>{throw TypeError(t)};var Q=(t,e,a)=>e in t?J(t,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):t[e]=a;var U=(t,e,a)=>Q(t,typeof e!="symbol"?e+"":e,a),x=(t,e,a)=>e.has(t)||L("Cannot "+a);var r=(t,e,a)=>(x(t,e,"read from private field"),a?a.call(t):e.get(t)),b=(t,e,a)=>e.has(t)?L("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,a),C=(t,e,a,s)=>(x(t,e,"write to private field"),s?s.call(t,a):e.set(t,a),a);import{ax as F,ae as V,ay as W,d as q,az as Z,g as A,I as K,aA as X,ai as ee,ap as D,aj as te,N as k,a7 as Y,H as ae,Q as O,W as z,ao as se,a9 as re,l as ie,a0 as ne,E as fe,a1 as ue,a3 as ce,V as de,U as $,aB as oe,aC as le,aD as he,b as _e,aE as ve,C as be,ah as ge,aF as Se,o as me,aq as pe,aG as Ee,aH as Ie,y as Pe,aa as ye,aI as Ae,S as Re,aJ as Te}from"./DKemW7Dm.js";let y=!1,M=Symbol();function we(t,e,a){const s=a[e]??(a[e]={store:null,source:V(void 0),unsubscribe:F});if(s.store!==t&&!(M in a))if(s.unsubscribe(),s.store=t??null,t==null)s.source.v=void 0,s.unsubscribe=F;else{var i=!0;s.unsubscribe=W(t,n=>{i?s.source.v=n:q(s.source,n)}),i=!1}return t&&M in a?Z(t):A(s.source)}function Be(){const t={};function e(){K(()=>{for(var a in t)t[a].unsubscribe();X(t,M,{enumerable:!1,value:!0})})}return[t,e]}function De(t){var e=y;try{return y=!1,[t(),y]}finally{y=e}}var l,_,o,g,E,I,R;class Oe{constructor(e,a=!0){U(this,"anchor");b(this,l,new Map);b(this,_,new Map);b(this,o,new Map);b(this,g,new Set);b(this,E,!0);b(this,I,e=>{if(r(this,l).has(e)){var a=r(this,l).get(e),s=r(this,_).get(a);if(s)ee(s),r(this,g).delete(a);else{var i=r(this,o).get(a);i&&(r(this,_).set(a,i.effect),r(this,o).delete(a),i.fragment.lastChild.remove(),this.anchor.before(i.fragment),s=i.effect)}for(const[n,u]of r(this,l)){if(r(this,l).delete(n),n===e)break;const f=r(this,o).get(u);f&&(D(f.effect),r(this,o).delete(u))}for(const[n,u]of r(this,_)){if(n===a||r(this,g).has(n))continue;const f=()=>{if(Array.from(r(this,l).values()).includes(n)){var h=document.createDocumentFragment();se(u,h),h.append(k()),r(this,o).set(n,{effect:u,fragment:h})}else D(u);r(this,g).delete(n),r(this,_).delete(n)};r(this,E)||!s?(r(this,g).add(n),te(u,f,!1)):f()}}});b(this,R,e=>{r(this,l).delete(e);const a=Array.from(r(this,l).values());for(const[s,i]of r(this,o))a.includes(s)||(D(i.effect),r(this,o).delete(s))});this.anchor=e,C(this,E,a)}ensure(e,a){var s=ae,i=re();if(a&&!r(this,_).has(e)&&!r(this,o).has(e))if(i){var n=document.createDocumentFragment(),u=k();n.append(u),r(this,o).set(e,{effect:Y(()=>a(u)),fragment:n})}else r(this,_).set(e,Y(()=>a(this.anchor)));if(r(this,l).set(s,e),i){for(const[f,c]of r(this,_))f===e?s.unskip_effect(c):s.skip_effect(c);for(const[f,c]of r(this,o))f===e?s.unskip_effect(c.effect):s.skip_effect(c.effect);s.oncommit(r(this,I)),s.ondiscard(r(this,R))}else O&&(this.anchor=z),r(this,I).call(this,s)}}l=new WeakMap,_=new WeakMap,o=new WeakMap,g=new WeakMap,E=new WeakMap,I=new WeakMap,R=new WeakMap;function Le(t,e,a=!1){var s;O&&(s=z,ne());var i=new Oe(t),n=a?fe:0;function u(f,c){if(O){var h=ue(s);if(f!==parseInt(h.substring(1))){var v=ce();de(v),i.anchor=v,$(!1),i.ensure(f,c),$(!0);return}}i.ensure(f,c)}ie(()=>{var f=!1;e((c,h=0)=>{f=!0,u(h,c)}),f||u(-1,null)},n)}function Ue(t,e,a,s){var w;var i=!pe||(a&Ee)!==0,n=(a&Se)!==0,u=(a&Ae)!==0,f=s,c=!0,h=()=>(c&&(c=!1,f=u?me(s):s),f);let v;if(n){var G=Re in t||Te in t;v=((w=oe(t,e))==null?void 0:w.set)??(G&&e in t?d=>t[e]=d:void 0)}var m,N=!1;n?[m,N]=De(()=>t[e]):m=t[e],m===void 0&&s!==void 0&&(m=h(),v&&(i&&le(),v(m)));var S;if(i?S=()=>{var d=t[e];return d===void 0?h():(c=!0,d)}:S=()=>{var d=t[e];return d!==void 0&&(f=void 0),d===void 0?f:d},i&&(a&he)===0)return S;if(v){var H=t.$$legacy;return(function(d,P){return arguments.length>0?((!i||!P||H||N)&&v(P?S():d),d):S()})}var T=!1,p=((a&Ie)!==0?Pe:ye)(()=>(T=!1,S()));n&&A(p);var j=be;return(function(d,P){if(arguments.length>0){const B=P?A(p):i&&n?_e(d):d;return q(p,B),T=!0,f!==void 0&&(f=B),d}return ve&&T||(j.f&ge)!==0?p.v:A(p)})}export{Oe as B,we as a,Le as i,Ue as p,Be as s}; diff --git a/web/.svelte-kit/output/client/_app/immutable/chunks/BberSjRt.js b/web/.svelte-kit/output/client/_app/immutable/chunks/BberSjRt.js new file mode 100644 index 0000000..456b65d --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/chunks/BberSjRt.js @@ -0,0 +1 @@ +import{d as b,s as m,c as h,a as g,b as k}from"./BJdXET8u.js";import{p as _,c as r,r as i,t as p,e as v}from"./DKemW7Dm.js";import{s as w,a as x}from"./kfynmD3Z.js";import{p as l}from"./BSXRhUWv.js";var y=k('');function z(n,t){_(t,!0);let a=l(t,"checked",15,!1),d=l(t,"label",3,""),s=l(t,"disabled",3,!1);function f(){var o;s()||(a(!a()),(o=t.onchange)==null||o.call(t,a()))}var e=y(),c=r(e),u=r(c,!0);i(c),i(e),p(()=>{w(e,"aria-checked",a()),x(e,1,`toggle-switch ${s()?"opacity-50 cursor-not-allowed":""}`),e.disabled=s(),m(u,d())}),h("click",e,f),g(n,e),v()}b(["click"]);export{z as T}; diff --git a/web/.svelte-kit/output/client/_app/immutable/chunks/BlV-f-zB.js b/web/.svelte-kit/output/client/_app/immutable/chunks/BlV-f-zB.js new file mode 100644 index 0000000..affc347 --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/chunks/BlV-f-zB.js @@ -0,0 +1 @@ +import{m as d,n as g,i as c,o as m,q as v,v as l,g as p,x as b,y as h}from"./DKemW7Dm.js";function x(n=!1){const s=d,e=s.l.u;if(!e)return;let r=()=>b(s.s);if(n){let o=0,t={};const _=h(()=>{let i=!1;const a=s.s;for(const f in a)a[f]!==t[f]&&(t[f]=a[f],i=!0);return i&&o++,o});r=()=>p(_)}e.b.length&&g(()=>{u(s,r),l(e.b)}),c(()=>{const o=m(()=>e.m.map(v));return()=>{for(const t of o)typeof t=="function"&&t()}}),e.a.length&&c(()=>{u(s,r),l(e.a)})}function u(n,s){if(n.l.s)for(const e of n.l.s)p(e);s()}export{x as i}; diff --git a/web/.svelte-kit/output/client/_app/immutable/chunks/BoGS7hWi.js b/web/.svelte-kit/output/client/_app/immutable/chunks/BoGS7hWi.js new file mode 100644 index 0000000..4abce98 --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/chunks/BoGS7hWi.js @@ -0,0 +1 @@ +import{m as w,A as T,B as x,o as A,C as B,D,S as E}from"./DKemW7Dm.js";function n(r,f){return r===f||(r==null?void 0:r[E])===f}function k(r={},f,i,O){var p=w.r,S=B;return T(()=>{var a,t;return x(()=>{a=t,t=[],A(()=>{r!==i(...t)&&(f(r,...t),a&&n(i(...a),r)&&f(null,...a))})}),()=>{let s=S;for(;s!==p&&s.parent!==null&&s.parent.f&D;)s=s.parent;const h=()=>{t&&n(i(...t),r)&&f(null,...t)},c=s.teardown;s.teardown=()=>{h(),c==null||c()}}}),r}export{k as b}; diff --git a/web/.svelte-kit/output/client/_app/immutable/chunks/Bpb8V1MF.js b/web/.svelte-kit/output/client/_app/immutable/chunks/Bpb8V1MF.js new file mode 100644 index 0000000..1043a33 --- /dev/null +++ b/web/.svelte-kit/output/client/_app/immutable/chunks/Bpb8V1MF.js @@ -0,0 +1 @@ +import{g as y,c as S}from"./DTyrBG6r.js";class $ extends Error{constructor(e,n){super(e),this.status=n,this.name="ApiError"}}async function f(t,e){const n=y(),o={"Content-Type":"application/json",...e==null?void 0:e.headers};n&&(o.Authorization=`Bearer ${n}`);const r=await fetch(t,{...e,headers:o});if(r.status===401&&typeof window<"u"&&!t.includes("/auth/"))throw S(),window.location.href="/login",new $("Authentication required",401);let u;try{u=await r.json()}catch{throw new $(`Server returned non-JSON response (HTTP ${r.status})`,r.status)}if(!u.success)throw new $(u.error??"Unknown API error",r.status);return u.data}function s(t){return f(t)}function i(t,e){return f(t,{method:"POST",body:e!==void 0?JSON.stringify(e):void 0})}function a(t,e){return f(t,{method:"PUT",body:JSON.stringify(e)})}function c(t){return f(t,{method:"DELETE"})}function w(){return s("/api/projects")}function P(t){return s(`/api/projects/${t}`)}function k(t){return i("/api/projects",t)}function x(t,e){return a(`/api/projects/${t}`,e)}function E(t){return c(`/api/projects/${t}`)}function q(t,e){return i(`/api/projects/${t}/stages`,e)}function I(t,e){return c(`/api/projects/${t}/stages/${e}`)}function R(t,e){return s(`/api/projects/${t}/stages/${e}/instances`)}function U(t,e,n){return i(`/api/projects/${t}/stages/${e}/instances`,{image_tag:n})}function T(t,e,n){return c(`/api/projects/${t}/stages/${e}/instances/${n}`)}function b(t,e,n){return i(`/api/projects/${t}/stages/${e}/instances/${n}/stop`)}function A(t,e,n){return i(`/api/projects/${t}/stages/${e}/instances/${n}/start`)}function C(t,e,n){return i(`/api/projects/${t}/stages/${e}/instances/${n}/restart`)}function L(t=50){return s(`/api/deploys?limit=${t}`)}function V(t){return i("/api/deploy/inspect",{image:t})}function D(t){return i("/api/deploy/quick",t)}function O(){return s("/api/registries")}function N(t){return i("/api/registries",t)}function J(t,e){return a(`/api/registries/${t}`,e)}function _(t){return c(`/api/registries/${t}`)}function z(t){return i(`/api/registries/${t}/test`)}function B(t,e){return s(`/api/registries/${t}/tags/${encodeURIComponent(e)}`)}function H(t){return s(`/api/registries/${t}/images`)}function W(){return s("/api/settings")}function F(t){return a("/api/settings",t)}function G(){return s("/api/settings/webhook-url")}function K(){return i("/api/settings/webhook-url/regenerate")}function M(){return s("/api/settings/npm-certificates")}function Q(){return s("/api/health")}function X(t,e){return s(`/api/projects/${t}/stages/${e}/env`)}function Y(t,e,n){return i(`/api/projects/${t}/stages/${e}/env`,n)}function Z(t,e,n,o){return a(`/api/projects/${t}/stages/${e}/env/${n}`,o)}function m(t,e,n){return c(`/api/projects/${t}/stages/${e}/env/${n}`)}function tt(t){return s(`/api/projects/${t}/volumes`)}function et(t,e){return i(`/api/projects/${t}/volumes`,e)}function nt(t,e,n){return a(`/api/projects/${t}/volumes/${e}`,n)}function ot(){return s("/api/volumes/scopes")}function st(t,e){return c(`/api/projects/${t}/volumes/${e}`)}function it(t,e,n){const o=new URLSearchParams;n!=null&&n.path&&o.set("path",n.path),n!=null&&n.stage&&o.set("stage",n.stage),n!=null&&n.tag&&o.set("tag",n.tag);const r=o.toString();return s(`/api/projects/${t}/volumes/${e}/browse${r?`?${r}`:""}`)}function rt(t,e,n){const o=new URLSearchParams;n!=null&&n.path&&o.set("path",n.path),n!=null&&n.stage&&o.set("stage",n.stage),n!=null&&n.tag&&o.set("tag",n.tag);const r=typeof localStorage<"u"?localStorage.getItem("auth_token"):null;r&&o.set("token",r);const u=o.toString();return`/api/projects/${t}/volumes/${e}/download${u?`?${u}`:""}`}async function ut(t,e,n,o){const r=new URLSearchParams;o!=null&&o.path&&r.set("path",o.path),o!=null&&o.stage&&r.set("stage",o.stage),o!=null&&o.tag&&r.set("tag",o.tag);const u=r.toString(),p=new FormData;for(let g=0;g