From a56bc06cc162d21689553f533e901c3d5442adf8 Mon Sep 17 00:00:00 2001 From: Wha1eChai Date: Sun, 11 Jan 2026 02:11:35 +0800 Subject: [PATCH 1/2] feat(webui): add Tailwind build system and refactor frontend architecture - Replace Tailwind CDN with local build (PostCSS + autoprefixer + daisyui) - Add CSS build scripts with automatic prepare hook on npm install - Create account-actions.js service layer with unified response format - Extend ErrorHandler.withLoading() for automatic loading state management - Add skeleton screens for initial load, silent refresh for subsequent updates - Implement loading animations for async operations (buttons, modals) - Improve empty states and add ARIA labels for accessibility - Abstract component styles using @apply (buttons, badges, inputs) - Add JSDoc documentation for Dashboard modules - Update README and CLAUDE.md with development guidelines --- CLAUDE.md | 139 +- README.md | 57 + package-lock.json | 1552 +++++++++++++++++++++ package.json | 12 + postcss.config.js | 6 + public/css/src/input.css | 486 +++++++ public/css/style.css | 373 +---- public/index.html | 50 +- public/js/components/account-manager.js | 59 +- public/js/components/dashboard/charts.js | 28 +- public/js/components/dashboard/filters.js | 17 +- public/js/components/dashboard/stats.js | 31 +- public/js/data-store.js | 7 +- public/js/store.js | 2 + public/js/utils/account-actions.js | 199 +++ public/js/utils/error-handler.js | 38 + public/views/accounts.html | 39 +- public/views/dashboard.html | 24 +- public/views/logs.html | 4 +- public/views/models.html | 36 +- public/views/settings.html | 18 +- tailwind.config.js | 52 + 22 files changed, 2730 insertions(+), 499 deletions(-) create mode 100644 postcss.config.js create mode 100644 public/css/src/input.css create mode 100644 public/js/utils/account-actions.js create mode 100644 tailwind.config.js diff --git a/CLAUDE.md b/CLAUDE.md index a3b8a44..4c3e6c4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,7 +11,7 @@ The proxy translates requests from Anthropic Messages API format → Google Gene ## Commands ```bash -# Install dependencies +# Install dependencies (automatically builds CSS via prepare hook) npm install # Start server (runs on port 8080) @@ -23,8 +23,13 @@ npm start -- --fallback # Start with debug logging npm start -- --debug -# Start with file watching for development -npm run dev +# Development mode (file watching) +npm run dev # Watch server files only +npm run dev:full # Watch both CSS and server files (recommended for frontend dev) + +# CSS build commands +npm run build:css # Build CSS once (minified) +npm run watch:css # Watch CSS files for changes # Account management npm run accounts # Interactive account management @@ -113,18 +118,35 @@ src/ ``` public/ ├── index.html # Main entry point +├── css/ +│ ├── style.css # Compiled Tailwind CSS (generated, do not edit) +│ └── src/ +│ └── input.css # Tailwind source with @apply directives ├── js/ │ ├── app.js # Main application logic (Alpine.js) │ ├── store.js # Global state management +│ ├── data-store.js # Shared data store (accounts, models, quotas) +│ ├── settings-store.js # Settings management store │ ├── components/ # UI Components -│ │ ├── dashboard.js # Real-time stats & charts +│ │ ├── dashboard.js # Main dashboard orchestrator │ │ ├── account-manager.js # Account list & OAuth handling │ │ ├── logs-viewer.js # Live log streaming -│ │ └── claude-config.js # CLI settings editor +│ │ ├── claude-config.js # CLI settings editor +│ │ ├── model-manager.js # Model configuration UI +│ │ ├── server-config.js # Server settings UI +│ │ └── dashboard/ # Dashboard sub-modules +│ │ ├── stats.js # Account statistics calculation +│ │ ├── charts.js # Chart.js visualizations +│ │ └── filters.js # Chart filter state management │ └── utils/ # Frontend utilities +│ ├── error-handler.js # Centralized error handling with ErrorHandler.withLoading +│ ├── account-actions.js # Account operations service layer (NEW) +│ ├── validators.js # Input validation +│ └── model-config.js # Model configuration helpers └── views/ # HTML partials (loaded dynamically) ├── dashboard.html ├── accounts.html + ├── models.html ├── settings.html └── logs.html ``` @@ -191,15 +213,29 @@ Each account object in `accounts.json` contains: **Web Management UI:** -- **Stack**: Vanilla JS + Alpine.js + Tailwind CSS (via CDN) +- **Stack**: Vanilla JS + Alpine.js + Tailwind CSS (local build with PostCSS) +- **Build System**: + - Tailwind CLI with JIT compilation + - PostCSS + Autoprefixer + - DaisyUI component library + - Custom `@apply` directives in `public/css/src/input.css` + - Compiled output: `public/css/style.css` (auto-generated on `npm install`) - **Architecture**: Single Page Application (SPA) with dynamic view loading -- **State Management**: Alpine.store for global state (accounts, settings, logs) +- **State Management**: + - Alpine.store for global state (accounts, settings, logs) + - Layered architecture: Service Layer (`account-actions.js`) → Component Layer → UI - **Features**: - Real-time dashboard with Chart.js visualization and subscription tier distribution - Account list with tier badges (Ultra/Pro/Free) and quota progress bars - OAuth flow handling via popup window - Live log streaming via Server-Sent Events (SSE) - Config editor for both Proxy and Claude CLI (`~/.claude/settings.json`) + - Skeleton loading screens for improved perceived performance + - Empty state UX with actionable prompts + - Loading states for all async operations +- **Accessibility**: + - ARIA labels on search inputs and icon buttons + - Keyboard navigation support (Escape to clear search) - **Security**: Optional password protection via `WEBUI_PASSWORD` env var - **Smart Refresh**: Client-side polling with ±20% jitter and tab visibility detection (3x slower when hidden) @@ -263,6 +299,95 @@ Each account object in `accounts.json` contains: - Returns: `{ accounts: [{ email, subscription: { tier, projectId }, limits: {...} }], models: [...] }` - Query params: `?format=table` (ASCII table) or `?includeHistory=true` (adds usage stats) +## Frontend Development + +### CSS Build System + +**Workflow:** +1. Edit styles in `public/css/src/input.css` (Tailwind source with `@apply` directives) +2. Run `npm run build:css` to compile (or `npm run watch:css` for auto-rebuild) +3. Compiled CSS output: `public/css/style.css` (minified, committed to git) + +**Component Styles:** +- Use `@apply` to abstract common Tailwind patterns into reusable classes +- Example: `.btn-action-ghost`, `.status-pill-success`, `.input-search` +- Skeleton loading: `.skeleton`, `.skeleton-stat-card`, `.skeleton-chart` + +**When to rebuild:** +- After modifying `public/css/src/input.css` +- After pulling changes that updated CSS source +- Automatically on `npm install` (via `prepare` hook) + +### Error Handling Pattern + +Use `window.ErrorHandler.withLoading()` for async operations: + +```javascript +async myOperation() { + return await window.ErrorHandler.withLoading(async () => { + // Your async code here + const result = await someApiCall(); + if (!result.ok) { + throw new Error('Operation failed'); + } + return result; + }, this, 'loading', { errorMessage: 'Failed to complete operation' }); +} +``` + +- Automatically manages `this.loading` state +- Shows error toast on failure +- Always resets loading state in `finally` block + +### Account Operations Service Layer + +Use `window.AccountActions` for account operations instead of direct API calls: + +```javascript +// ✅ Good: Use service layer +const result = await window.AccountActions.refreshAccount(email); +if (result.success) { + this.$store.global.showToast('Account refreshed', 'success'); +} else { + this.$store.global.showToast(result.error, 'error'); +} + +// ❌ Bad: Direct API call in component +const response = await fetch(`/api/accounts/${email}/refresh`); +``` + +**Available methods:** +- `refreshAccount(email)` - Refresh token and quota +- `toggleAccount(email, enabled)` - Enable/disable account (with optimistic update) +- `deleteAccount(email)` - Delete account +- `getFixAccountUrl(email)` - Get OAuth re-auth URL +- `reloadAccounts()` - Reload from disk +- `canDelete(account)` - Check if account is deletable + +All methods return `{success: boolean, data?: object, error?: string}` + +### Dashboard Modules + +Dashboard is split into three modules for maintainability: + +1. **stats.js** - Account statistics calculation + - `updateStats(component)` - Computes active/limited/total counts + - Updates subscription tier distribution + +2. **charts.js** - Chart.js visualizations + - `initQuotaChart(component)` - Initialize quota distribution pie chart + - `initTrendChart(component)` - Initialize usage trend line chart + - `updateQuotaChart(component)` - Update quota chart data + - `updateTrendChart(component)` - Update trend chart (with concurrency lock) + +3. **filters.js** - Filter state management + - `getInitialState()` - Default filter values + - `loadPreferences(component)` - Load from localStorage + - `savePreferences(component)` - Save to localStorage + - Filter types: time range, display mode, family/model selection + +Each module is well-documented with JSDoc comments. + ## Maintenance When making significant changes to the codebase (new modules, refactoring, architectural changes), update this CLAUDE.md and the README.md file to keep documentation in sync. diff --git a/README.md b/README.md index 0207373..b310562 100644 --- a/README.md +++ b/README.md @@ -458,6 +458,63 @@ By using this software, you acknowledge and accept the following: --- +## Development + +### For Developers & Contributors + +This project uses a local Tailwind CSS build system. CSS is pre-compiled and included in the repository, so you can run the project immediately after cloning. + +#### Quick Start + +```bash +git clone https://github.com/badri-s2001/antigravity-claude-proxy.git +cd antigravity-claude-proxy +npm install # Automatically builds CSS via prepare hook +npm start # Start server (no rebuild needed) +``` + +#### Frontend Development + +If you need to modify styles in `public/css/src/input.css`: + +```bash +# Option 1: Build once +npm run build:css + +# Option 2: Watch for changes (auto-rebuild) +npm run watch:css + +# Option 3: Watch both CSS and server (recommended) +npm run dev:full +``` + +**File Structure:** +- `public/css/src/input.css` - Source CSS with Tailwind `@apply` directives (edit this) +- `public/css/style.css` - Compiled & minified CSS (auto-generated, don't edit) +- `tailwind.config.js` - Tailwind configuration +- `postcss.config.js` - PostCSS configuration + +#### Backend-Only Development + +If you're only working on backend code and don't need frontend dev tools: + +```bash +npm install --production # Skip devDependencies (saves ~20MB) +npm start +``` + +**Note:** Pre-compiled CSS is committed to the repository, so you don't need to rebuild unless modifying styles. + +#### Project Structure + +See [CLAUDE.md](./CLAUDE.md) for detailed architecture documentation, including: +- Request flow and module organization +- Frontend architecture (Alpine.js + Tailwind) +- Service layer patterns (`ErrorHandler.withLoading`, `AccountActions`) +- Dashboard module documentation + +--- + ## Credits This project is based on insights and code from: diff --git a/package-lock.json b/package-lock.json index 2a68883..a062183 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,10 +17,131 @@ "bin": { "antigravity-claude-proxy": "bin/cli.js" }, + "devDependencies": { + "@tailwindcss/forms": "^0.5.7", + "autoprefixer": "^10.4.16", + "concurrently": "^8.2.2", + "daisyui": "^4.12.14", + "postcss": "^8.4.32", + "tailwindcss": "^3.4.0" + }, "engines": { "node": ">=18.0.0" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.11.tgz", + "integrity": "sha512-h9wegbZDPurxG22xZSoWtdzc41/OlNEUQERNqI/0fOwa2aVlWGu7C35E/x6LDyD3lgtztFSSjKZyuVM0hxhbgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -34,6 +155,60 @@ "node": ">= 0.6" } }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -49,6 +224,43 @@ "tslib": "^2.4.0" } }, + "node_modules/autoprefixer": { + "version": "10.4.23", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.23.tgz", + "integrity": "sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001760", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -69,6 +281,16 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.14", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", + "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/better-sqlite3": { "version": "12.5.0", "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.5.0.tgz", @@ -83,6 +305,19 @@ "node": "20.x || 22.x || 23.x || 24.x || 25.x" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -127,6 +362,53 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -189,12 +471,184 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001763", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001763.tgz", + "integrity": "sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "license": "ISC" }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concurrently": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", + "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "date-fns": "^2.30.0", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -244,6 +698,77 @@ "node": ">= 0.10" } }, + "node_modules/css-selector-tokenizer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz", + "integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/culori": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz", + "integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/daisyui": { + "version": "4.12.24", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.12.24.tgz", + "integrity": "sha512-JYg9fhQHOfXyLadrBrEqCDM6D5dWCSSiM6eTNCRrBRzx/VlOCrLS8eDfIw9RVvs64v2mJdLooKXY8EwQzoszAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-selector-tokenizer": "^0.8", + "culori": "^3", + "picocolors": "^1", + "postcss-js": "^4" + }, + "engines": { + "node": ">=16.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/daisyui" + } + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -305,6 +830,20 @@ "node": ">=8" } }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -325,6 +864,20 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -373,6 +926,16 @@ "node": ">= 0.4" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -443,12 +1006,72 @@ "url": "https://opencollective.com/express" } }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "license": "MIT" }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", @@ -476,6 +1099,20 @@ "node": ">= 0.6" } }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -491,6 +1128,21 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "license": "MIT" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -500,6 +1152,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -543,6 +1205,19 @@ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "license": "MIT" }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -555,6 +1230,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -652,6 +1337,115 @@ "node": ">= 0.10" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -679,6 +1473,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -688,6 +1492,20 @@ "node": ">= 0.6" } }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -733,6 +1551,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "license": "MIT", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -754,6 +1582,37 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/napi-build-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", @@ -781,6 +1640,23 @@ "node": ">=10" } }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -790,6 +1666,16 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -832,12 +1718,222 @@ "node": ">= 0.8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -902,6 +1998,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -941,6 +2058,16 @@ "rc": "cli.js" } }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -955,6 +2082,95 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1133,6 +2349,19 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -1250,6 +2479,22 @@ "simple-concat": "^1.0.0" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawn-command": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", + "dev": true + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -1268,6 +2513,34 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -1277,6 +2550,96 @@ "node": ">=0.10.0" } }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tar-fs": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", @@ -1305,6 +2668,90 @@ "node": ">=6" } }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -1314,6 +2761,23 @@ "node": ">=0.6" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -1354,6 +2818,37 @@ "node": ">= 0.8" } }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -1378,11 +2873,68 @@ "node": ">= 0.8" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } } } } diff --git a/package.json b/package.json index 21ddf33..dec5b4f 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,12 @@ "public" ], "scripts": { + "build:css": "tailwindcss -i ./public/css/src/input.css -o ./public/css/style.css --minify", + "watch:css": "tailwindcss -i ./public/css/src/input.css -o ./public/css/style.css --watch", + "prepare": "npm run build:css", "start": "node src/index.js", "dev": "node --watch src/index.js", + "dev:full": "concurrently \"npm run watch:css\" \"npm run dev\"", "accounts": "node src/cli/accounts.js", "accounts:add": "node src/cli/accounts.js add", "accounts:list": "node src/cli/accounts.js list", @@ -57,5 +61,13 @@ "better-sqlite3": "^12.5.0", "cors": "^2.8.5", "express": "^4.18.2" + }, + "devDependencies": { + "@tailwindcss/forms": "^0.5.7", + "autoprefixer": "^10.4.16", + "concurrently": "^8.2.2", + "daisyui": "^4.12.14", + "postcss": "^8.4.32", + "tailwindcss": "^3.4.0" } } \ No newline at end of file diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2b75bd8 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +} diff --git a/public/css/src/input.css b/public/css/src/input.css new file mode 100644 index 0000000..d2a764b --- /dev/null +++ b/public/css/src/input.css @@ -0,0 +1,486 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + /* === Background Layers === */ + --color-space-950: #09090b; + --color-space-900: #0f0f11; + --color-space-850: #121214; + --color-space-800: #18181b; + --color-space-border: #27272a; + + /* === Neon Accents (Full Saturation) === */ + --color-neon-purple: #a855f7; + --color-neon-green: #22c55e; + --color-neon-cyan: #06b6d4; + --color-neon-yellow: #eab308; + --color-neon-red: #ef4444; + + /* === Soft Neon (Reduced Saturation for Fills) === */ + --color-neon-purple-soft: #9333ea; + --color-neon-green-soft: #16a34a; + --color-neon-cyan-soft: #0891b2; + + /* === Text Hierarchy (WCAG AA Compliant) === */ + --color-text-primary: #ffffff; /* Emphasis: Titles, Key Numbers */ + --color-text-secondary: #d4d4d8; /* Content: Body Text (zinc-300) */ + --color-text-tertiary: #a1a1aa; /* Metadata: Timestamps, Labels (zinc-400) */ + --color-text-quaternary: #71717a; /* Subtle: Decorative (zinc-500) */ + + /* === Legacy Aliases (Backward Compatibility) === */ + --color-text-main: var(--color-text-secondary); + --color-text-dim: var(--color-text-tertiary); + --color-text-muted: var(--color-text-tertiary); + --color-text-bright: var(--color-text-primary); + + /* Gradient Accents */ + --color-green-400: #4ade80; + --color-yellow-400: #facc15; + --color-red-400: #f87171; + + /* Chart Colors */ + --color-chart-1: #a855f7; + --color-chart-2: #c084fc; + --color-chart-3: #e879f9; + --color-chart-4: #d946ef; + --color-chart-5: #22c55e; + --color-chart-6: #4ade80; + --color-chart-7: #86efac; + --color-chart-8: #10b981; + --color-chart-9: #06b6d4; + --color-chart-10: #f59e0b; + --color-chart-11: #ef4444; + --color-chart-12: #ec4899; + --color-chart-13: #8b5cf6; + --color-chart-14: #14b8a6; + --color-chart-15: #f97316; + --color-chart-16: #6366f1; +} + +[x-cloak] { + display: none !important; +} + +/* Custom Scrollbar */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: rgba(9, 9, 11, 0.3); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb { + background: linear-gradient(180deg, #27272a 0%, #18181b 100%); + border-radius: 4px; + border: 1px solid rgba(255, 255, 255, 0.05); + transition: background 0.2s ease; +} + +::-webkit-scrollbar-thumb:hover { + background: linear-gradient(180deg, #3f3f46 0%, #27272a 100%); + border-color: rgba(168, 85, 247, 0.3); +} + +/* Animations */ +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.2s ease; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(5px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in { + animation: fadeIn 0.4s ease-out forwards; +} + +/* Note: .glass-panel has been deprecated. Use .view-card instead for consistency. */ + +.nav-item.active { + background: linear-gradient( + 90deg, + theme("colors.neon.purple / 15%") 0%, + transparent 100% + ); + @apply border-l-4 border-neon-purple text-white; +} + +.nav-item { + @apply border-l-4 border-transparent transition-all duration-200; +} + +.progress-gradient-success::-webkit-progress-value { + background-image: linear-gradient( + to right, + var(--color-neon-green), + var(--color-green-400) + ); +} + +.progress-gradient-warning::-webkit-progress-value { + background-image: linear-gradient( + to right, + var(--color-neon-yellow), + var(--color-yellow-400) + ); +} + +.progress-gradient-error::-webkit-progress-value { + background-image: linear-gradient( + to right, + var(--color-neon-red), + var(--color-red-400) + ); +} + +/* Dashboard Grid */ +.stats-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 1.5rem; +} + +/* Tooltip Customization */ +.tooltip:before { + @apply bg-space-800 border border-space-border text-gray-200 font-mono text-xs; +} + +.tooltip-left:before { + margin-right: 0.5rem; +} + +/* -------------------------------------------------------------------------- */ +/* Refactored Global Utilities */ +/* -------------------------------------------------------------------------- */ + +/* Standard Layout Constants */ +:root { + --view-padding: 2rem; /* 32px - Standard Padding */ + --view-gap: 2rem; /* 32px - Standard component gap */ + --card-radius: 0.75rem; /* 12px */ +} + +@media (max-width: 768px) { + :root { + --view-padding: 1rem; + --view-gap: 1.25rem; + } +} + +/* Base View Container */ +.view-container { + display: flex; + flex-direction: column; + margin-left: auto; + margin-right: auto; + width: 100%; + padding: var(--view-padding); + gap: var(--view-gap); + min-height: calc(100vh - 56px); /* Align with navbar height */ + max-width: 1400px; + scrollbar-gutter: stable; +} + +/* Specialized container for data-heavy pages (Logs) */ +.view-container-full { + @apply w-full animate-fade-in flex flex-col; + padding: var(--view-padding); + gap: var(--view-gap); + min-height: calc(100vh - 56px); + max-width: 100%; +} + +/* Centered container for form-heavy pages (Settings/Accounts) */ +.view-container-centered { + @apply mx-auto w-full animate-fade-in flex flex-col; + padding: var(--view-padding); + gap: var(--view-gap); + min-height: calc(100vh - 56px); + max-width: 900px; /* Comfortable reading width for forms */ +} + +/* Standard Section Header */ +.view-header { + display: flex; + flex-direction: column; + justify-content: space-between; + margin-bottom: 0.5rem; + gap: 1rem; +} + +@media (min-width: 768px) { + .view-header { + flex-direction: row; + align-items: flex-end; + } +} + +.view-header-title { + @apply flex flex-col; +} + +.view-header-title h2 { + @apply text-2xl font-bold text-white tracking-tight; +} + +.view-header-title p { + @apply text-sm text-gray-500 mt-1; +} + +.view-header-actions { + @apply flex items-center gap-3; +} + +/* Standard Card Panel */ +.view-card { + position: relative; + overflow: hidden; + border-radius: var(--card-radius); + padding: 1.5rem; + border: 1px solid rgba(255, 255, 255, 0.08); + background: linear-gradient(135deg, + rgba(15, 15, 17, 0.75) 0%, + rgba(18, 18, 20, 0.70) 100% + ); + backdrop-filter: blur(12px); + box-shadow: + 0 0 0 1px rgba(255, 255, 255, 0.02) inset, + 0 4px 24px rgba(0, 0, 0, 0.4); + transition: border-color 0.3s ease, box-shadow 0.3s ease; +} + +.view-card:hover { + border-color: rgba(255, 255, 255, 0.12); + box-shadow: + 0 0 0 1px rgba(255, 255, 255, 0.04) inset, + 0 8px 32px rgba(0, 0, 0, 0.5); +} + +.view-card-header { + @apply flex items-center justify-between mb-4 pb-4 border-b border-[rgba(39,39,42,0.3)]; +} + +/* Component Unification */ +.standard-table { + @apply table w-full border-separate border-spacing-0; +} +.standard-table thead { + @apply bg-space-900/50 text-gray-500 font-mono text-xs uppercase border-b border-space-border; +} +.standard-table tbody tr { + @apply transition-all duration-200 border-b border-[rgba(39,39,42,0.3)] last:border-0; +} + +.standard-table tbody tr:hover { + background: linear-gradient( + 90deg, + rgba(255, 255, 255, 0.03) 0%, + rgba(255, 255, 255, 0.05) 50%, + rgba(255, 255, 255, 0.03) 100% + ); + border-color: rgba(255, 255, 255, 0.08); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); +} + +/* Custom Range Slider - Simplified */ +.custom-range { + -webkit-appearance: none; + appearance: none; + width: 100%; + height: 4px; + background: var(--color-space-800); + border-radius: 999px; + outline: none; + cursor: pointer; +} + +.custom-range::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 14px; + height: 14px; + border-radius: 50%; + background: var(--range-color, var(--color-neon-purple)); + cursor: pointer; + transition: transform 0.1s ease; +} + +.custom-range::-webkit-slider-thumb:hover { + transform: scale(1.15); +} + +.custom-range::-moz-range-thumb { + width: 14px; + height: 14px; + border: none; + border-radius: 50%; + background: var(--range-color, var(--color-neon-purple)); + cursor: pointer; + transition: transform 0.1s ease; +} + +.custom-range::-moz-range-thumb:hover { + transform: scale(1.15); +} + +/* Color Variants */ +.custom-range-purple { + --range-color: var(--color-neon-purple); +} +.custom-range-green { + --range-color: var(--color-neon-green); +} +.custom-range-cyan { + --range-color: var(--color-neon-cyan); +} +.custom-range-yellow { + --range-color: var(--color-neon-yellow); +} +.custom-range-accent { + --range-color: var(--color-neon-cyan); +} + +/* -------------------------------------------------------------------------- */ +/* Refactored UI Components (Phase 1.2) */ +/* -------------------------------------------------------------------------- */ + +/* Action Buttons */ +.btn-action-ghost { + @apply btn btn-xs btn-ghost text-gray-400 hover:text-white transition-colors; +} + +.btn-action-ghost-square { + @apply btn btn-xs btn-ghost btn-square text-gray-400 hover:text-white transition-colors; +} + +.btn-action-primary { + @apply btn bg-gradient-to-r from-neon-purple to-indigo-600 + border-none text-white shadow-lg shadow-neon-purple/20 + hover:shadow-neon-purple/40 transition-all; +} + +.btn-action-success { + @apply btn btn-xs btn-ghost btn-square text-green-500 hover:bg-green-500/20; +} + +.btn-action-danger { + @apply btn btn-xs btn-ghost btn-square text-red-400 hover:bg-red-500/20; +} + +.btn-action-neutral { + @apply btn btn-xs btn-ghost btn-square text-gray-500 hover:bg-gray-500/20; +} + +/* Status Pills/Badges */ +.status-pill { + @apply px-2 py-1 text-[10px] font-mono font-bold uppercase rounded border; +} + +.status-pill-purple { + @apply status-pill bg-neon-purple/10 text-neon-purple border-neon-purple/30; +} + +.status-pill-ultra { + @apply status-pill bg-yellow-500/10 text-yellow-400 border-yellow-500/30; +} + +.status-pill-pro { + @apply status-pill bg-blue-500/10 text-blue-400 border-blue-500/30; +} + +.status-pill-free { + @apply status-pill bg-gray-500/10 text-gray-400 border-gray-500/30; +} + +.status-pill-success { + @apply status-pill bg-neon-green/10 text-neon-green border-neon-green/30; +} + +.status-pill-warning { + @apply status-pill bg-yellow-500/10 text-yellow-400 border-yellow-500/30; +} + +.status-pill-error { + @apply status-pill bg-red-500/10 text-red-400 border-red-500/30; +} + +/* Input Components */ +.input-search { + @apply w-full bg-space-900/50 border border-[rgba(39,39,42,0.5)] text-gray-300 + rounded-lg pl-10 pr-4 py-2 + focus:outline-none focus:bg-space-800 focus:border-neon-purple/50 + hover:border-space-border hover:bg-space-800/80 + transition-all placeholder-gray-600/80; +} + +.input-search-sm { + @apply input-search h-8 text-xs font-normal; +} + +/* -------------------------------------------------------------------------- */ +/* Skeleton Loading (Phase 4.1) */ +/* -------------------------------------------------------------------------- */ + +/* Skeleton animation */ +@keyframes skeleton-pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.4; + } +} + +/* Base skeleton element */ +.skeleton { + @apply bg-gradient-to-r from-space-900/60 via-space-800/40 to-space-900/60; + background-size: 200% 100%; + animation: skeleton-pulse 1.5s ease-in-out infinite; + border-radius: 0.375rem; +} + +/* Skeleton variants */ +.skeleton-text { + @apply skeleton h-4 w-full; +} + +.skeleton-text-sm { + @apply skeleton h-3 w-3/4; +} + +.skeleton-title { + @apply skeleton h-6 w-1/2; +} + +.skeleton-circle { + @apply skeleton rounded-full; +} + +.skeleton-stat-card { + @apply skeleton h-32 w-full rounded-xl; +} + +.skeleton-chart { + @apply skeleton h-64 w-full rounded-xl; +} + +.skeleton-table-row { + @apply skeleton h-12 w-full mb-2; +} diff --git a/public/css/style.css b/public/css/style.css index 3b1d734..296f8a0 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -1,372 +1 @@ -:root { - /* === Background Layers === */ - --color-space-950: #09090b; - --color-space-900: #0f0f11; - --color-space-850: #121214; - --color-space-800: #18181b; - --color-space-border: #27272a; - - /* === Neon Accents (Full Saturation) === */ - --color-neon-purple: #a855f7; - --color-neon-green: #22c55e; - --color-neon-cyan: #06b6d4; - --color-neon-yellow: #eab308; - --color-neon-red: #ef4444; - - /* === Soft Neon (Reduced Saturation for Fills) === */ - --color-neon-purple-soft: #9333ea; - --color-neon-green-soft: #16a34a; - --color-neon-cyan-soft: #0891b2; - - /* === Text Hierarchy (WCAG AA Compliant) === */ - --color-text-primary: #ffffff; /* Emphasis: Titles, Key Numbers */ - --color-text-secondary: #d4d4d8; /* Content: Body Text (zinc-300) */ - --color-text-tertiary: #a1a1aa; /* Metadata: Timestamps, Labels (zinc-400) */ - --color-text-quaternary: #71717a; /* Subtle: Decorative (zinc-500) */ - - /* === Legacy Aliases (Backward Compatibility) === */ - --color-text-main: var(--color-text-secondary); - --color-text-dim: var(--color-text-tertiary); - --color-text-muted: var(--color-text-tertiary); - --color-text-bright: var(--color-text-primary); - - /* Gradient Accents */ - --color-green-400: #4ade80; - --color-yellow-400: #facc15; - --color-red-400: #f87171; - - /* Chart Colors */ - --color-chart-1: #a855f7; - --color-chart-2: #c084fc; - --color-chart-3: #e879f9; - --color-chart-4: #d946ef; - --color-chart-5: #22c55e; - --color-chart-6: #4ade80; - --color-chart-7: #86efac; - --color-chart-8: #10b981; - --color-chart-9: #06b6d4; - --color-chart-10: #f59e0b; - --color-chart-11: #ef4444; - --color-chart-12: #ec4899; - --color-chart-13: #8b5cf6; - --color-chart-14: #14b8a6; - --color-chart-15: #f97316; - --color-chart-16: #6366f1; -} - -[x-cloak] { - display: none !important; -} - -/* Custom Scrollbar */ -::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -::-webkit-scrollbar-track { - background: rgba(9, 9, 11, 0.3); - border-radius: 4px; -} - -::-webkit-scrollbar-thumb { - background: linear-gradient(180deg, #27272a 0%, #18181b 100%); - border-radius: 4px; - border: 1px solid rgba(255, 255, 255, 0.05); - transition: background 0.2s ease; -} - -::-webkit-scrollbar-thumb:hover { - background: linear-gradient(180deg, #3f3f46 0%, #27272a 100%); - border-color: rgba(168, 85, 247, 0.3); -} - -/* Animations */ -.fade-enter-active, -.fade-leave-active { - transition: opacity 0.2s ease; -} - -.fade-enter-from, -.fade-leave-to { - opacity: 0; -} - -@keyframes fadeIn { - from { - opacity: 0; - transform: translateY(5px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.animate-fade-in { - animation: fadeIn 0.4s ease-out forwards; -} - -/* Utility */ -.glass-panel { - background: linear-gradient( - 135deg, - rgba(15, 15, 17, 0.75) 0%, - rgba(18, 18, 20, 0.7) 100% - ); - backdrop-filter: blur(12px); - border: 1px solid rgba(255, 255, 255, 0.08); - box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.02) inset, - 0 4px 24px rgba(0, 0, 0, 0.4); - transition: border-color 0.3s ease, box-shadow 0.3s ease; -} - -.glass-panel:hover { - border-color: rgba(255, 255, 255, 0.12); - box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.04) inset, - 0 8px 32px rgba(0, 0, 0, 0.5); -} - -.nav-item.active { - background: linear-gradient( - 90deg, - theme("colors.neon.purple / 15%") 0%, - transparent 100% - ); - @apply border-l-4 border-neon-purple text-white; -} - -.nav-item { - @apply border-l-4 border-transparent transition-all duration-200; -} - -.progress-gradient-success::-webkit-progress-value { - background-image: linear-gradient( - to right, - var(--color-neon-green), - var(--color-green-400) - ); -} - -.progress-gradient-warning::-webkit-progress-value { - background-image: linear-gradient( - to right, - var(--color-neon-yellow), - var(--color-yellow-400) - ); -} - -.progress-gradient-error::-webkit-progress-value { - background-image: linear-gradient( - to right, - var(--color-neon-red), - var(--color-red-400) - ); -} - -/* Dashboard Grid */ -.stats-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); - gap: 1.5rem; -} - -/* Tooltip Customization */ -.tooltip:before { - @apply bg-space-800 border border-space-border text-gray-200 font-mono text-xs; -} - -.tooltip-left:before { - margin-right: 0.5rem; -} - -/* -------------------------------------------------------------------------- */ -/* Refactored Global Utilities */ -/* -------------------------------------------------------------------------- */ - -/* Standard Layout Constants */ -:root { - --view-padding: 2rem; /* 32px - Standard Padding */ - --view-gap: 2rem; /* 32px - Standard component gap */ - --card-radius: 0.75rem; /* 12px */ -} - -@media (max-width: 768px) { - :root { - --view-padding: 1rem; - --view-gap: 1.25rem; - } -} - -/* Base View Container */ -.view-container { - display: flex; - flex-direction: column; - margin-left: auto; - margin-right: auto; - width: 100%; - padding: var(--view-padding); - gap: var(--view-gap); - min-height: calc(100vh - 56px); /* Align with navbar height */ - max-width: 1400px; - scrollbar-gutter: stable; -} - -/* Specialized container for data-heavy pages (Logs) */ -.view-container-full { - @apply w-full animate-fade-in flex flex-col; - padding: var(--view-padding); - gap: var(--view-gap); - min-height: calc(100vh - 56px); - max-width: 100%; -} - -/* Centered container for form-heavy pages (Settings/Accounts) */ -.view-container-centered { - @apply mx-auto w-full animate-fade-in flex flex-col; - padding: var(--view-padding); - gap: var(--view-gap); - min-height: calc(100vh - 56px); - max-width: 900px; /* Comfortable reading width for forms */ -} - -/* Standard Section Header */ -.view-header { - display: flex; - flex-direction: column; - justify-content: space-between; - margin-bottom: 0.5rem; - gap: 1rem; -} - -@media (min-width: 768px) { - .view-header { - flex-direction: row; - align-items: flex-end; - } -} - -.view-header-title { - @apply flex flex-col; -} - -.view-header-title h2 { - @apply text-2xl font-bold text-white tracking-tight; -} - -.view-header-title p { - @apply text-sm text-gray-500 mt-1; -} - -.view-header-actions { - @apply flex items-center gap-3; -} - -/* Standard Card Panel */ -.view-card { - position: relative; - overflow: hidden; - border-radius: var(--card-radius); - padding: 1.5rem; - border: 1px solid rgba(255, 255, 255, 0.08); - background: linear-gradient(135deg, - rgba(15, 15, 17, 0.75) 0%, - rgba(18, 18, 20, 0.70) 100% - ); - backdrop-filter: blur(12px); - box-shadow: - 0 0 0 1px rgba(255, 255, 255, 0.02) inset, - 0 4px 24px rgba(0, 0, 0, 0.4); - transition: border-color 0.3s ease, box-shadow 0.3s ease; -} - -.view-card:hover { - border-color: rgba(255, 255, 255, 0.12); - box-shadow: - 0 0 0 1px rgba(255, 255, 255, 0.04) inset, - 0 8px 32px rgba(0, 0, 0, 0.5); -} - -.view-card-header { - @apply flex items-center justify-between mb-4 pb-4 border-b border-space-border/30; -} - -/* Component Unification */ -.standard-table { - @apply table w-full border-separate border-spacing-0; -} -.standard-table thead { - @apply bg-space-900/50 text-gray-500 font-mono text-xs uppercase border-b border-space-border; -} -.standard-table tbody tr { - @apply transition-all duration-200 border-b border-space-border/30 last:border-0; -} - -.standard-table tbody tr:hover { - background: linear-gradient( - 90deg, - rgba(255, 255, 255, 0.03) 0%, - rgba(255, 255, 255, 0.05) 50%, - rgba(255, 255, 255, 0.03) 100% - ); - border-color: rgba(255, 255, 255, 0.08); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); -} - -/* Custom Range Slider - Simplified */ -.custom-range { - -webkit-appearance: none; - appearance: none; - width: 100%; - height: 4px; - background: var(--color-space-800); - border-radius: 999px; - outline: none; - cursor: pointer; -} - -.custom-range::-webkit-slider-thumb { - -webkit-appearance: none; - appearance: none; - width: 14px; - height: 14px; - border-radius: 50%; - background: var(--range-color, var(--color-neon-purple)); - cursor: pointer; - transition: transform 0.1s ease; -} - -.custom-range::-webkit-slider-thumb:hover { - transform: scale(1.15); -} - -.custom-range::-moz-range-thumb { - width: 14px; - height: 14px; - border: none; - border-radius: 50%; - background: var(--range-color, var(--color-neon-purple)); - cursor: pointer; - transition: transform 0.1s ease; -} - -.custom-range::-moz-range-thumb:hover { - transform: scale(1.15); -} - -/* Color Variants */ -.custom-range-purple { - --range-color: var(--color-neon-purple); -} -.custom-range-green { - --range-color: var(--color-neon-green); -} -.custom-range-cyan { - --range-color: var(--color-neon-cyan); -} -.custom-range-yellow { - --range-color: var(--color-neon-yellow); -} -.custom-range-accent { - --range-color: var(--color-neon-cyan); -} +*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}input:where(:not([type])),input:where([type=date]),input:where([type=datetime-local]),input:where([type=email]),input:where([type=month]),input:where([type=number]),input:where([type=password]),input:where([type=search]),input:where([type=tel]),input:where([type=text]),input:where([type=time]),input:where([type=url]),input:where([type=week]),select,select:where([multiple]),textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}input:where(:not([type])):focus,input:where([type=date]):focus,input:where([type=datetime-local]):focus,input:where([type=email]):focus,input:where([type=month]):focus,input:where([type=number]):focus,input:where([type=password]):focus,input:where([type=search]):focus,input:where([type=tel]):focus,input:where([type=text]):focus,input:where([type=time]):focus,input:where([type=url]):focus,input:where([type=week]):focus,select:focus,select:where([multiple]):focus,textarea:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}select:where([multiple]),select:where([size]:not([size="1"])){background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}input:where([type=checkbox]),input:where([type=radio]){-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}input:where([type=checkbox]){border-radius:0}input:where([type=radio]){border-radius:100%}input:where([type=checkbox]):focus,input:where([type=radio]):focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}input:where([type=checkbox]):checked,input:where([type=radio]):checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}input:where([type=checkbox]):checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0'/%3E%3C/svg%3E")}@media (forced-colors:active) {input:where([type=checkbox]):checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}input:where([type=radio]):checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}@media (forced-colors:active) {input:where([type=radio]):checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}input:where([type=checkbox]):checked:focus,input:where([type=checkbox]):checked:hover,input:where([type=radio]):checked:focus,input:where([type=radio]):checked:hover{border-color:transparent;background-color:currentColor}input:where([type=checkbox]):indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media (forced-colors:active) {input:where([type=checkbox]):indeterminate{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}input:where([type=checkbox]):indeterminate:focus,input:where([type=checkbox]):indeterminate:hover{border-color:transparent;background-color:currentColor}input:where([type=file]){background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}input:where([type=file]):focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}:root,[data-theme]{background-color:var(--fallback-b1,oklch(var(--b1)/1));color:var(--fallback-bc,oklch(var(--bc)/1))}@supports not (color:oklch(0% 0 0)){:root{color-scheme:light;--fallback-p:#491eff;--fallback-pc:#d4dbff;--fallback-s:#ff41c7;--fallback-sc:#fff9fc;--fallback-a:#00cfbd;--fallback-ac:#00100d;--fallback-n:#2b3440;--fallback-nc:#d7dde4;--fallback-b1:#fff;--fallback-b2:#e5e6e6;--fallback-b3:#e5e6e6;--fallback-bc:#1f2937;--fallback-in:#00b3f0;--fallback-inc:#000;--fallback-su:#00ca92;--fallback-suc:#000;--fallback-wa:#ffc22d;--fallback-wac:#000;--fallback-er:#ff6f70;--fallback-erc:#000}@media (prefers-color-scheme:dark){:root{color-scheme:dark;--fallback-p:#7582ff;--fallback-pc:#050617;--fallback-s:#ff71cf;--fallback-sc:#190211;--fallback-a:#00c7b5;--fallback-ac:#000e0c;--fallback-n:#2a323c;--fallback-nc:#a6adbb;--fallback-b1:#1d232a;--fallback-b2:#191e24;--fallback-b3:#15191e;--fallback-bc:#a6adbb;--fallback-in:#00b3f0;--fallback-inc:#000;--fallback-su:#00ca92;--fallback-suc:#000;--fallback-wa:#ffc22d;--fallback-wac:#000;--fallback-er:#ff6f70;--fallback-erc:#000}}}html{-webkit-tap-highlight-color:transparent}*{scrollbar-color:color-mix(in oklch,currentColor 35%,transparent) transparent}:hover{scrollbar-color:color-mix(in oklch,currentColor 60%,transparent) transparent}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.alert{display:grid;width:100%;grid-auto-flow:row;align-content:flex-start;align-items:center;justify-items:center;gap:1rem;text-align:center;border-radius:var(--rounded-box,1rem);border-width:1px;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));padding:1rem;--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--alert-bg:var(--fallback-b2,oklch(var(--b2)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1));background-color:var(--alert-bg)}@media (min-width:640px){.alert{grid-auto-flow:column;grid-template-columns:auto minmax(auto,1fr);justify-items:start;text-align:start}}.avatar.placeholder>div{display:flex;align-items:center;justify-content:center}@media (hover:hover){.checkbox-primary:hover{--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)))}.checkbox-success:hover{--tw-border-opacity:1;border-color:var(--fallback-su,oklch(var(--su)/var(--tw-border-opacity)))}.checkbox-warning:hover{--tw-border-opacity:1;border-color:var(--fallback-wa,oklch(var(--wa)/var(--tw-border-opacity)))}.checkbox-info:hover{--tw-border-opacity:1;border-color:var(--fallback-in,oklch(var(--in)/var(--tw-border-opacity)))}.checkbox-error:hover{--tw-border-opacity:1;border-color:var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity)))}.label a:hover{--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}.menu li>:not(ul,.menu-title,details,.btn).active,.menu li>:not(ul,.menu-title,details,.btn):active,.menu li>details>summary:active{--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.tab:hover{--tw-text-opacity:1}.table tr.hover:hover,.table tr.hover:nth-child(2n):hover{--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}}.btn{display:inline-flex;height:3rem;min-height:3rem;flex-shrink:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-wrap:wrap;align-items:center;justify-content:center;border-radius:var(--rounded-btn,.5rem);border-color:transparent;border-color:oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;text-align:center;font-size:.875rem;line-height:1em;gap:.5rem;font-weight:600;text-decoration-line:none;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);border-width:var(--border-btn,1px);transition-property:color,background-color,border-color,opacity,box-shadow,transform;--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:var(--fallback-bc,oklch(var(--bc)/1));background-color:oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity));--tw-bg-opacity:1;--tw-border-opacity:1}.btn-disabled,.btn:disabled,.btn[disabled]{pointer-events:none}.btn-circle,.btn-square{height:3rem;width:3rem;padding:0}.btn-circle{border-radius:9999px}:where(.btn:is(input[type=checkbox])),:where(.btn:is(input[type=radio])){width:auto;-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn:is(input[type=checkbox]):after,.btn:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}.card{position:relative;display:flex;flex-direction:column;border-radius:var(--rounded-box,1rem)}.card:focus{outline:2px solid transparent;outline-offset:2px}.card figure{display:flex;align-items:center;justify-content:center}.card.image-full{display:grid}.card.image-full:before{position:relative;content:"";z-index:10;border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));opacity:.75}.card.image-full:before,.card.image-full>*{grid-column-start:1;grid-row-start:1}.card.image-full>figure img{height:100%;-o-object-fit:cover;object-fit:cover}.card.image-full>.card-body{position:relative;z-index:20;--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.checkbox{flex-shrink:0;--chkbg:var(--fallback-bc,oklch(var(--bc)/1));--chkfg:var(--fallback-b1,oklch(var(--b1)/1));height:1.5rem;width:1.5rem;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--rounded-btn,.5rem);border-width:1px;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));--tw-border-opacity:0.2}.diff{position:relative;display:grid;width:100%;overflow:hidden;direction:ltr;container-type:inline-size;grid-template-columns:auto 1fr}.divider{display:flex;flex-direction:row;align-items:center;align-self:stretch;margin-top:1rem;margin-bottom:1rem;height:1rem;white-space:nowrap}.divider:after,.divider:before{height:.125rem;width:100%;flex-grow:1;--tw-content:"";content:var(--tw-content);background-color:var(--fallback-bc,oklch(var(--bc)/.1))}.dropdown{position:relative;display:inline-block}.dropdown>:not(summary):focus{outline:2px solid transparent;outline-offset:2px}.dropdown .dropdown-content{position:absolute}.dropdown:is(:not(details)) .dropdown-content{visibility:hidden;opacity:0;transform-origin:top;--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);transition-duration:.2s}.dropdown.dropdown-open .dropdown-content,.dropdown:focus-within .dropdown-content,.dropdown:not(.dropdown-hover):focus .dropdown-content{visibility:visible;opacity:1}@media (hover:hover){.dropdown.dropdown-hover:hover .dropdown-content{visibility:visible;opacity:1}.btm-nav>.disabled:hover,.btm-nav>[disabled]:hover{pointer-events:none;--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn:hover{--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn:hover{background-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity,1)) 90%,#000);border-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity,1)) 90%,#000)}}@supports not (color:oklch(0% 0 0)){.btn:hover{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn.glass:hover{--glass-opacity:25%;--glass-border-opacity:15%}.btn-ghost:hover{border-color:transparent}@supports (color:oklch(0% 0 0)){.btn-ghost:hover{background-color:var(--fallback-bc,oklch(var(--bc)/.2))}}.btn-outline:hover{--tw-border-opacity:1;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-b1,oklch(var(--b1)/var(--tw-text-opacity)))}.btn-outline.btn-primary:hover{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-primary:hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}.btn-outline.btn-secondary:hover{--tw-text-opacity:1;color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-secondary:hover{background-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000)}}.btn-outline.btn-accent:hover{--tw-text-opacity:1;color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-accent:hover{background-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000)}}.btn-outline.btn-success:hover{--tw-text-opacity:1;color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-success:hover{background-color:color-mix(in oklab,var(--fallback-su,oklch(var(--su)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-su,oklch(var(--su)/1)) 90%,#000)}}.btn-outline.btn-info:hover{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-info:hover{background-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000)}}.btn-outline.btn-warning:hover{--tw-text-opacity:1;color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-warning:hover{background-color:color-mix(in oklab,var(--fallback-wa,oklch(var(--wa)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-wa,oklch(var(--wa)/1)) 90%,#000)}}.btn-outline.btn-error:hover{--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-error:hover{background-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000)}}.btn-disabled:hover,.btn:disabled:hover,.btn[disabled]:hover{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}@supports (color:color-mix(in oklab,black,black)){.btn:is(input[type=checkbox]:checked):hover,.btn:is(input[type=radio]:checked):hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}.dropdown.dropdown-hover:hover .dropdown-content{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:where(.menu li:not(.menu-title,.disabled)>:not(ul,details,.menu-title)):not(.active,.btn):hover,:where(.menu li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.active,.btn):hover{cursor:pointer;outline:2px solid transparent;outline-offset:2px}@supports (color:oklch(0% 0 0)){:where(.menu li:not(.menu-title,.disabled)>:not(ul,details,.menu-title)):not(.active,.btn):hover,:where(.menu li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.active,.btn):hover{background-color:var(--fallback-bc,oklch(var(--bc)/.1))}}.tab[disabled],.tab[disabled]:hover{cursor:not-allowed;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}}.dropdown:is(details) summary::-webkit-details-marker{display:none}.form-control{flex-direction:column}.form-control,.label{display:flex}.label{-webkit-user-select:none;-moz-user-select:none;user-select:none;align-items:center;justify-content:space-between;padding:.5rem .25rem}.indicator{position:relative;display:inline-flex;width:-moz-max-content;width:max-content}.indicator :where(.indicator-item){z-index:1;position:absolute;white-space:nowrap}.input{flex-shrink:1;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:3rem;padding-left:1rem;padding-right:1rem;font-size:1rem;line-height:2;line-height:1.5rem;border-radius:var(--rounded-btn,.5rem);border-width:1px;border-color:transparent;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.input-md[type=number]::-webkit-inner-spin-button,.input[type=number]::-webkit-inner-spin-button{margin-top:-1rem;margin-bottom:-1rem;margin-inline-end:-1rem}.input-xs[type=number]::-webkit-inner-spin-button{margin-top:-.25rem;margin-bottom:-.25rem;margin-inline-end:0}.input-sm[type=number]::-webkit-inner-spin-button{margin-top:0;margin-bottom:0;margin-inline-end:0}.join{display:inline-flex;align-items:stretch;border-radius:var(--rounded-btn,.5rem)}.join :where(.join-item){border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:0;border-start-start-radius:0}.join .join-item:not(:first-child):not(:last-child),.join :not(:first-child):not(:last-child) .join-item{border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:0;border-start-start-radius:0}.join .join-item:first-child:not(:last-child),.join :first-child:not(:last-child) .join-item{border-start-end-radius:0;border-end-end-radius:0}.join .dropdown .join-item:first-child:not(:last-child),.join :first-child:not(:last-child) .dropdown .join-item{border-start-end-radius:inherit;border-end-end-radius:inherit}.join :where(.join-item:first-child:not(:last-child)),.join :where(:first-child:not(:last-child) .join-item){border-end-start-radius:inherit;border-start-start-radius:inherit}.join .join-item:last-child:not(:first-child),.join :last-child:not(:first-child) .join-item{border-end-start-radius:0;border-start-start-radius:0}.join :where(.join-item:last-child:not(:first-child)),.join :where(:last-child:not(:first-child) .join-item){border-start-end-radius:inherit;border-end-end-radius:inherit}@supports not selector(:has(*)){:where(.join *){border-radius:inherit}}@supports selector(:has(*)){:where(.join :has(.join-item)){border-radius:inherit}}.link{cursor:pointer;text-decoration-line:underline}.menu{display:flex;flex-direction:column;flex-wrap:wrap;font-size:.875rem;line-height:1.25rem;padding:.5rem}.menu :where(li ul){position:relative;white-space:nowrap;margin-inline-start:1rem;padding-inline-start:.5rem}.menu :where(li:not(.menu-title)>:not(ul,details,.menu-title,.btn)),.menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){display:grid;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;grid-auto-columns:minmax(auto,max-content) auto max-content;-webkit-user-select:none;-moz-user-select:none;user-select:none}.menu li.disabled{cursor:not-allowed;-webkit-user-select:none;-moz-user-select:none;user-select:none;color:var(--fallback-bc,oklch(var(--bc)/.3))}.menu :where(li>.menu-dropdown:not(.menu-dropdown-show)){display:none}:where(.menu li){position:relative;display:flex;flex-shrink:0;flex-direction:column;flex-wrap:wrap;align-items:stretch}:where(.menu li) .badge{justify-self:end}.modal{pointer-events:none;position:fixed;inset:0;margin:0;display:grid;height:100%;max-height:none;width:100%;max-width:none;justify-items:center;padding:0;opacity:0;overscroll-behavior:contain;z-index:999;background-color:transparent;color:inherit;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);transition-property:transform,opacity,visibility;overflow-y:hidden}:where(.modal){align-items:center}.modal-box{max-height:calc(100vh - 5em);grid-column-start:1;grid-row-start:1;width:91.666667%;max-width:32rem;--tw-scale-x:.9;--tw-scale-y:.9;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-bottom-right-radius:var(--rounded-box,1rem);border-bottom-left-radius:var(--rounded-box,1rem);border-top-left-radius:var(--rounded-box,1rem);border-top-right-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));padding:1.5rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);transition-duration:.2s;box-shadow:0 25px 50px -12px rgba(0,0,0,.25);overflow-y:auto;overscroll-behavior:contain}.modal-open,.modal-toggle:checked+.modal,.modal:target,.modal[open]{pointer-events:auto;visibility:visible;opacity:1}.modal-action{display:flex;margin-top:1.5rem;justify-content:flex-end}:root:has(:is(.modal-open,.modal:target,.modal-toggle:checked+.modal,.modal[open])){overflow:hidden;scrollbar-gutter:stable}.navbar{display:flex;align-items:center;padding:var(--navbar-padding,.5rem);min-height:4rem;width:100%}:where(.navbar>:not(script,style)){display:inline-flex;align-items:center}.progress{position:relative;-webkit-appearance:none;height:.5rem;background-color:var(--fallback-bc,oklch(var(--bc)/.2))}.progress,.range{width:100%;-moz-appearance:none;appearance:none;overflow:hidden;border-radius:var(--rounded-box,1rem)}.range{height:1.5rem;cursor:pointer;-webkit-appearance:none;--range-shdw:var(--fallback-bc,oklch(var(--bc)/1));background-color:transparent}.range:focus{outline:none}.select{display:inline-flex;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:3rem;min-height:3rem;padding-inline-start:1rem;padding-inline-end:2.5rem;font-size:.875rem;line-height:1.25rem;line-height:2;border-radius:var(--rounded-btn,.5rem);border-width:1px;border-color:transparent;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));background-image:linear-gradient(45deg,transparent 50%,currentColor 0),linear-gradient(135deg,currentColor 50%,transparent 0);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16.1px) calc(1px + 50%);background-size:4px 4px,4px 4px;background-repeat:no-repeat}.select[multiple]{height:auto}.\!stats{display:inline-grid!important;border-radius:var(--rounded-box,1rem)!important;--tw-bg-opacity:1!important;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))!important;--tw-text-opacity:1!important;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))!important}.stats{display:inline-grid;border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}:where(.\!stats){grid-auto-flow:column!important;overflow-x:auto!important}:where(.stats){grid-auto-flow:column;overflow-x:auto}.stat{display:inline-grid;width:100%;grid-template-columns:repeat(1,1fr);-moz-column-gap:1rem;column-gap:1rem;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));--tw-border-opacity:0.1;padding:1rem 1.5rem}.stat-title{color:var(--fallback-bc,oklch(var(--bc)/.6))}.stat-title,.stat-value{grid-column-start:1;white-space:nowrap}.stat-value{font-size:2.25rem;line-height:2.5rem;font-weight:800}.stat-desc{grid-column-start:1;white-space:nowrap;font-size:.75rem;line-height:1rem;color:var(--fallback-bc,oklch(var(--bc)/.6))}.steps .step{display:grid;grid-template-columns:repeat(1,minmax(0,1fr));grid-template-columns:auto;grid-template-rows:repeat(2,minmax(0,1fr));grid-template-rows:40px 1fr;place-items:center;text-align:center;min-width:4rem}.tabs-lifted:has(.tab-content[class*=" rounded-"]) .tab:first-child:not(:is(.tab-active,[aria-selected=true])),.tabs-lifted:has(.tab-content[class^=rounded-]) .tab:first-child:not(:is(.tab-active,[aria-selected=true])){border-bottom-color:transparent}.tab{position:relative;grid-row-start:1;display:inline-flex;height:2rem;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;flex-wrap:wrap;align-items:center;justify-content:center;text-align:center;font-size:.875rem;line-height:1.25rem;line-height:2;--tab-padding:1rem;--tw-text-opacity:0.5;--tab-color:var(--fallback-bc,oklch(var(--bc)/1));--tab-bg:var(--fallback-b1,oklch(var(--b1)/1));--tab-border-color:var(--fallback-b3,oklch(var(--b3)/1));color:var(--tab-color);padding-inline-start:var(--tab-padding,1rem);padding-inline-end:var(--tab-padding,1rem)}.tab:is(input[type=radio]){width:auto;border-bottom-right-radius:0;border-bottom-left-radius:0}.tab:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}.tab:not(input):empty{cursor:default;grid-column-start:span 9999}:is(.tab-active,[aria-selected=true])+.tab-content,input.tab:checked+.tab-content{display:block}.table{position:relative;width:100%;border-radius:var(--rounded-box,1rem);text-align:left;font-size:.875rem;line-height:1.25rem}.table :where(.table-pin-rows thead tr){position:sticky;top:0;z-index:1;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.table :where(.table-pin-rows tfoot tr){position:sticky;bottom:0;z-index:1;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.table :where(.table-pin-cols tr th){position:sticky;left:0;right:0;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.toast{position:fixed;display:flex;min-width:-moz-fit-content;min-width:fit-content;flex-direction:column;white-space:nowrap;gap:.5rem;padding:1rem}.toggle{flex-shrink:0;--tglbg:var(--fallback-b1,oklch(var(--b1)/1));--handleoffset:1.5rem;--handleoffsetcalculator:calc(var(--handleoffset)*-1);--togglehandleborder:0 0;height:1.5rem;width:3rem;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--rounded-badge,1.9rem);border-width:1px;border-color:currentColor;background-color:currentColor;color:var(--fallback-bc,oklch(var(--bc)/.5));transition:background,box-shadow var(--animation-input,.2s) ease-out;box-shadow:var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset,0 0 0 2px var(--tglbg) inset,var(--togglehandleborder)}.alert-info{border-color:var(--fallback-in,oklch(var(--in)/.2));--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)));--alert-bg:var(--fallback-in,oklch(var(--in)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1))}.alert-success{border-color:var(--fallback-su,oklch(var(--su)/.2));--tw-text-opacity:1;color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)));--alert-bg:var(--fallback-su,oklch(var(--su)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1))}.alert-error{border-color:var(--fallback-er,oklch(var(--er)/.2));--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)));--alert-bg:var(--fallback-er,oklch(var(--er)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1))}.btm-nav>:where(.active){border-top-width:2px;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.btm-nav>.disabled,.btm-nav>[disabled]{pointer-events:none;--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btm-nav>* .label{font-size:1rem;line-height:1.5rem}@media (prefers-reduced-motion:no-preference){.btn{animation:button-pop var(--animation-btn,.25s) ease-out}}.btn:active:focus,.btn:active:hover{animation:button-pop 0s ease-out;transform:scale(var(--btn-focus-scale,.97))}@supports not (color:oklch(0% 0 0)){.btn{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}.btn-primary{--btn-color:var(--fallback-p)}}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-primary.btn-active{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}.btn-outline.btn-secondary.btn-active{background-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000)}.btn-outline.btn-accent.btn-active{background-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000)}.btn-outline.btn-success.btn-active{background-color:color-mix(in oklab,var(--fallback-su,oklch(var(--su)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-su,oklch(var(--su)/1)) 90%,#000)}.btn-outline.btn-info.btn-active{background-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000)}.btn-outline.btn-warning.btn-active{background-color:color-mix(in oklab,var(--fallback-wa,oklch(var(--wa)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-wa,oklch(var(--wa)/1)) 90%,#000)}.btn-outline.btn-error.btn-active{background-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000)}}.btn:focus-visible{outline-style:solid;outline-width:2px;outline-offset:2px}.btn-primary{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));outline-color:var(--fallback-p,oklch(var(--p)/1))}@supports (color:oklch(0% 0 0)){.btn-primary{--btn-color:var(--p)}}.btn.glass{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn.glass.btn-active{--glass-opacity:25%;--glass-border-opacity:15%}.btn-ghost{border-width:1px;border-color:transparent;background-color:transparent;color:currentColor;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-ghost.btn-active{border-color:transparent;background-color:var(--fallback-bc,oklch(var(--bc)/.2))}.btn-outline{border-color:currentColor;background-color:transparent;--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.btn-outline.btn-active{--tw-border-opacity:1;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-b1,oklch(var(--b1)/var(--tw-text-opacity)))}.btn-outline.btn-primary{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)))}.btn-outline.btn-primary.btn-active{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn-outline.btn-secondary{--tw-text-opacity:1;color:var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity)))}.btn-outline.btn-secondary.btn-active{--tw-text-opacity:1;color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)))}.btn-outline.btn-accent{--tw-text-opacity:1;color:var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity)))}.btn-outline.btn-accent.btn-active{--tw-text-opacity:1;color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)))}.btn-outline.btn-success{--tw-text-opacity:1;color:var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity)))}.btn-outline.btn-success.btn-active{--tw-text-opacity:1;color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)))}.btn-outline.btn-info{--tw-text-opacity:1;color:var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity)))}.btn-outline.btn-info.btn-active{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}.btn-outline.btn-warning{--tw-text-opacity:1;color:var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity)))}.btn-outline.btn-warning.btn-active{--tw-text-opacity:1;color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)))}.btn-outline.btn-error{--tw-text-opacity:1;color:var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity)))}.btn-outline.btn-error.btn-active{--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)))}.btn.btn-disabled,.btn:disabled,.btn[disabled]{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn:is(input[type=checkbox]:checked),.btn:is(input[type=radio]:checked){--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn:is(input[type=checkbox]:checked):focus-visible,.btn:is(input[type=radio]:checked):focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}@keyframes button-pop{0%{transform:scale(var(--btn-focus-scale,.98))}40%{transform:scale(1.02)}to{transform:scale(1)}}.card :where(figure:first-child){overflow:hidden;border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-start-radius:unset;border-end-end-radius:unset}.card :where(figure:last-child){overflow:hidden;border-start-start-radius:unset;border-start-end-radius:unset;border-end-start-radius:inherit;border-end-end-radius:inherit}.card:focus-visible{outline:2px solid currentColor;outline-offset:2px}.card.bordered{border-width:1px;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)))}.card.compact .card-body{padding:1rem;font-size:.875rem;line-height:1.25rem}.card.image-full :where(figure){overflow:hidden;border-radius:inherit}.checkbox:focus{box-shadow:none}.checkbox:focus-visible{outline-style:solid;outline-width:2px;outline-offset:2px;outline-color:var(--fallback-bc,oklch(var(--bc)/1))}.checkbox:disabled{border-width:0;cursor:not-allowed;border-color:transparent;--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));opacity:.2}.checkbox:checked,.checkbox[aria-checked=true]{background-repeat:no-repeat;animation:checkmark var(--animation-input,.2s) ease-out;background-color:var(--chkbg);background-image:linear-gradient(-45deg,transparent 65%,var(--chkbg) 65.99%),linear-gradient(45deg,transparent 75%,var(--chkbg) 75.99%),linear-gradient(-45deg,var(--chkbg) 40%,transparent 40.99%),linear-gradient(45deg,var(--chkbg) 30%,var(--chkfg) 30.99%,var(--chkfg) 40%,transparent 40.99%),linear-gradient(-45deg,var(--chkfg) 50%,var(--chkbg) 50.99%)}.checkbox:indeterminate{--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));background-repeat:no-repeat;animation:checkmark var(--animation-input,.2s) ease-out;background-image:linear-gradient(90deg,transparent 80%,var(--chkbg) 80%),linear-gradient(-90deg,transparent 80%,var(--chkbg) 80%),linear-gradient(0deg,var(--chkbg) 43%,var(--chkfg) 43%,var(--chkfg) 57%,var(--chkbg) 57%)}.checkbox-primary{--chkbg:var(--fallback-p,oklch(var(--p)/1));--chkfg:var(--fallback-pc,oklch(var(--pc)/1));--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)))}.checkbox-primary:focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}.checkbox-primary:checked,.checkbox-primary[aria-checked=true]{--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.checkbox-success{--chkbg:var(--fallback-su,oklch(var(--su)/1));--chkfg:var(--fallback-suc,oklch(var(--suc)/1));--tw-border-opacity:1;border-color:var(--fallback-su,oklch(var(--su)/var(--tw-border-opacity)))}.checkbox-success:focus-visible{outline-color:var(--fallback-su,oklch(var(--su)/1))}.checkbox-success:checked,.checkbox-success[aria-checked=true]{--tw-border-opacity:1;border-color:var(--fallback-su,oklch(var(--su)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-su,oklch(var(--su)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)))}.checkbox-warning{--chkbg:var(--fallback-wa,oklch(var(--wa)/1));--chkfg:var(--fallback-wac,oklch(var(--wac)/1));--tw-border-opacity:1;border-color:var(--fallback-wa,oklch(var(--wa)/var(--tw-border-opacity)))}.checkbox-warning:focus-visible{outline-color:var(--fallback-wa,oklch(var(--wa)/1))}.checkbox-warning:checked,.checkbox-warning[aria-checked=true]{--tw-border-opacity:1;border-color:var(--fallback-wa,oklch(var(--wa)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-wa,oklch(var(--wa)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)))}.checkbox-info{--chkbg:var(--fallback-in,oklch(var(--in)/1));--chkfg:var(--fallback-inc,oklch(var(--inc)/1));--tw-border-opacity:1;border-color:var(--fallback-in,oklch(var(--in)/var(--tw-border-opacity)))}.checkbox-info:focus-visible{outline-color:var(--fallback-in,oklch(var(--in)/1))}.checkbox-info:checked,.checkbox-info[aria-checked=true]{--tw-border-opacity:1;border-color:var(--fallback-in,oklch(var(--in)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-in,oklch(var(--in)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}.checkbox-error{--chkbg:var(--fallback-er,oklch(var(--er)/1));--chkfg:var(--fallback-erc,oklch(var(--erc)/1));--tw-border-opacity:1;border-color:var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity)))}.checkbox-error:focus-visible{outline-color:var(--fallback-er,oklch(var(--er)/1))}.checkbox-error:checked,.checkbox-error[aria-checked=true]{--tw-border-opacity:1;border-color:var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-er,oklch(var(--er)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)))}@keyframes checkmark{0%{background-position-y:5px}50%{background-position-y:-2px}to{background-position-y:0}}.divider:not(:empty){gap:1rem}.dropdown.dropdown-open .dropdown-content,.dropdown:focus .dropdown-content,.dropdown:focus-within .dropdown-content{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.label-text{font-size:.875rem;line-height:1.25rem}.label-text,.label-text-alt{--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}.label-text-alt{font-size:.75rem;line-height:1rem}.input input{--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));background-color:transparent}.input input:focus{outline:2px solid transparent;outline-offset:2px}.input[list]::-webkit-calendar-picker-indicator{line-height:1em}.input-bordered{border-color:var(--fallback-bc,oklch(var(--bc)/.2))}.input:focus,.input:focus-within{box-shadow:none;border-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-style:solid;outline-width:2px;outline-offset:2px;outline-color:var(--fallback-bc,oklch(var(--bc)/.2))}.input-disabled,.input:disabled,.input:has(>input[disabled]),.input[disabled]{cursor:not-allowed;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));color:var(--fallback-bc,oklch(var(--bc)/.4))}.input-disabled::-moz-placeholder,.input:disabled::-moz-placeholder,.input:has(>input[disabled])::-moz-placeholder,.input[disabled]::-moz-placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.input-disabled::placeholder,.input:disabled::placeholder,.input:has(>input[disabled])::placeholder,.input[disabled]::placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.input::-webkit-date-and-time-value{text-align:inherit}.join>:where(:not(:first-child)){margin-top:0;margin-bottom:0;margin-inline-start:-1px}.join>:where(:not(:first-child)):is(.btn){margin-inline-start:calc(var(--border-btn)*-1)}.join-item:focus{isolation:isolate}.link:focus{outline:2px solid transparent;outline-offset:2px}.link:focus-visible{outline:2px solid currentColor;outline-offset:2px}.\!loading{pointer-events:none!important;display:inline-block!important;aspect-ratio:1/1!important;width:1.5rem!important;background-color:currentColor!important;-webkit-mask-size:100%!important;mask-size:100%!important;-webkit-mask-repeat:no-repeat!important;mask-repeat:no-repeat!important;-webkit-mask-position:center!important;mask-position:center!important;-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23000'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-linecap='round' stroke-width='3'%3E%3CanimateTransform attributeName='transform' dur='2s' from='0 12 12' repeatCount='indefinite' to='360 12 12' type='rotate'/%3E%3Canimate attributeName='stroke-dasharray' dur='1.5s' keyTimes='0;0.475;1' repeatCount='indefinite' values='0,150;42,150;42,150'/%3E%3Canimate attributeName='stroke-dashoffset' dur='1.5s' keyTimes='0;0.475;1' repeatCount='indefinite' values='0;-16;-59'/%3E%3C/circle%3E%3C/svg%3E")!important;mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23000'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-linecap='round' stroke-width='3'%3E%3CanimateTransform attributeName='transform' dur='2s' from='0 12 12' repeatCount='indefinite' to='360 12 12' type='rotate'/%3E%3Canimate attributeName='stroke-dasharray' dur='1.5s' keyTimes='0;0.475;1' repeatCount='indefinite' values='0,150;42,150;42,150'/%3E%3Canimate attributeName='stroke-dashoffset' dur='1.5s' keyTimes='0;0.475;1' repeatCount='indefinite' values='0;-16;-59'/%3E%3C/circle%3E%3C/svg%3E")!important}.loading{pointer-events:none;display:inline-block;aspect-ratio:1/1;width:1.5rem;background-color:currentColor;-webkit-mask-size:100%;mask-size:100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center}.loading,.loading-spinner{-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23000'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-linecap='round' stroke-width='3'%3E%3CanimateTransform attributeName='transform' dur='2s' from='0 12 12' repeatCount='indefinite' to='360 12 12' type='rotate'/%3E%3Canimate attributeName='stroke-dasharray' dur='1.5s' keyTimes='0;0.475;1' repeatCount='indefinite' values='0,150;42,150;42,150'/%3E%3Canimate attributeName='stroke-dashoffset' dur='1.5s' keyTimes='0;0.475;1' repeatCount='indefinite' values='0;-16;-59'/%3E%3C/circle%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23000'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-linecap='round' stroke-width='3'%3E%3CanimateTransform attributeName='transform' dur='2s' from='0 12 12' repeatCount='indefinite' to='360 12 12' type='rotate'/%3E%3Canimate attributeName='stroke-dasharray' dur='1.5s' keyTimes='0;0.475;1' repeatCount='indefinite' values='0,150;42,150;42,150'/%3E%3Canimate attributeName='stroke-dashoffset' dur='1.5s' keyTimes='0;0.475;1' repeatCount='indefinite' values='0;-16;-59'/%3E%3C/circle%3E%3C/svg%3E")}.loading-bars{-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M1 1h6v22H1z'%3E%3Canimate attributeName='y' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;5;1'/%3E%3Canimate attributeName='height' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='22;14;22'/%3E%3Canimate attributeName='opacity' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;0.2;1'/%3E%3C/path%3E%3Cpath d='M9 1h6v22H9z'%3E%3Canimate attributeName='y' begin='-0.65s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;5;1'/%3E%3Canimate attributeName='height' begin='-0.65s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='22;14;22'/%3E%3Canimate attributeName='opacity' begin='-0.65s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;0.2;1'/%3E%3C/path%3E%3Cpath d='M17 1h6v22h-6z'%3E%3Canimate attributeName='y' begin='-0.5s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;5;1'/%3E%3Canimate attributeName='height' begin='-0.5s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='22;14;22'/%3E%3Canimate attributeName='opacity' begin='-0.5s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;0.2;1'/%3E%3C/path%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M1 1h6v22H1z'%3E%3Canimate attributeName='y' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;5;1'/%3E%3Canimate attributeName='height' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='22;14;22'/%3E%3Canimate attributeName='opacity' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;0.2;1'/%3E%3C/path%3E%3Cpath d='M9 1h6v22H9z'%3E%3Canimate attributeName='y' begin='-0.65s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;5;1'/%3E%3Canimate attributeName='height' begin='-0.65s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='22;14;22'/%3E%3Canimate attributeName='opacity' begin='-0.65s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;0.2;1'/%3E%3C/path%3E%3Cpath d='M17 1h6v22h-6z'%3E%3Canimate attributeName='y' begin='-0.5s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;5;1'/%3E%3Canimate attributeName='height' begin='-0.5s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='22;14;22'/%3E%3Canimate attributeName='opacity' begin='-0.5s' dur='.8s' keyTimes='0;0.938;1' repeatCount='indefinite' values='1;0.2;1'/%3E%3C/path%3E%3C/svg%3E")}.loading-xs{width:1rem}.loading-md{width:1.5rem}:where(.menu li:empty){--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));opacity:.1;margin:.5rem 1rem;height:1px}.menu :where(li ul):before{position:absolute;bottom:.75rem;inset-inline-start:0;top:.75rem;width:1px;--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));opacity:.1;content:""}.menu :where(li:not(.menu-title)>:not(ul,details,.menu-title,.btn)),.menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--rounded-btn,.5rem);padding:.5rem 1rem;text-align:start;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);transition-duration:.2s;text-wrap:balance}:where(.menu li:not(.menu-title,.disabled)>:not(ul,details,.menu-title)):is(summary):not(.active,.btn):focus-visible,:where(.menu li:not(.menu-title,.disabled)>:not(ul,details,.menu-title)):not(summary,.active,.btn).focus,:where(.menu li:not(.menu-title,.disabled)>:not(ul,details,.menu-title)):not(summary,.active,.btn):focus,:where(.menu li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):is(summary):not(.active,.btn):focus-visible,:where(.menu li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(summary,.active,.btn).focus,:where(.menu li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(summary,.active,.btn):focus{cursor:pointer;background-color:var(--fallback-bc,oklch(var(--bc)/.1));--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));outline:2px solid transparent;outline-offset:2px}.menu li>:not(ul,.menu-title,details,.btn).active,.menu li>:not(ul,.menu-title,details,.btn):active,.menu li>details>summary:active{--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.menu :where(li>details>summary)::-webkit-details-marker{display:none}.menu :where(li>.menu-dropdown-toggle):after,.menu :where(li>details>summary):after{justify-self:end;display:block;margin-top:-.5rem;height:.5rem;width:.5rem;transform:rotate(45deg);transition-property:transform,margin-top;transition-duration:.3s;transition-timing-function:cubic-bezier(.4,0,.2,1);content:"";transform-origin:75% 75%;box-shadow:2px 2px;pointer-events:none}.menu :where(li>.menu-dropdown-toggle.menu-dropdown-show):after,.menu :where(li>details[open]>summary):after{transform:rotate(225deg);margin-top:0}.mockup-phone .display{overflow:hidden;border-radius:40px;margin-top:-25px}.mockup-browser .mockup-browser-toolbar .input{position:relative;margin-left:auto;margin-right:auto;display:block;height:1.75rem;width:24rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));padding-left:2rem;direction:ltr}.mockup-browser .mockup-browser-toolbar .input:before{left:.5rem;aspect-ratio:1/1;height:.75rem;--tw-translate-y:-50%;border-radius:9999px;border-width:2px;border-color:currentColor}.mockup-browser .mockup-browser-toolbar .input:after,.mockup-browser .mockup-browser-toolbar .input:before{content:"";position:absolute;top:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));opacity:.6}.mockup-browser .mockup-browser-toolbar .input:after{left:1.25rem;height:.5rem;--tw-translate-y:25%;--tw-rotate:-45deg;border-radius:9999px;border-width:1px;border-color:currentColor}.modal::backdrop,.modal:not(dialog:not(.modal-open)){background-color:#0006;animation:modal-pop .2s ease-out}.modal-backdrop{z-index:-1;grid-column-start:1;grid-row-start:1;display:grid;align-self:stretch;justify-self:stretch;color:transparent}.modal-open .modal-box,.modal-toggle:checked+.modal .modal-box,.modal:target .modal-box,.modal[open] .modal-box{--tw-translate-y:0px;--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.modal-action>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.modal-action:where([dir=rtl],[dir=rtl] *)>:not([hidden])~:not([hidden]){--tw-space-x-reverse:1}@keyframes modal-pop{0%{opacity:0}}.progress::-moz-progress-bar{border-radius:var(--rounded-box,1rem);background-color:currentColor}.progress:indeterminate{--progress-color:var(--fallback-bc,oklch(var(--bc)/1));background-image:repeating-linear-gradient(90deg,var(--progress-color) -1%,var(--progress-color) 10%,transparent 10%,transparent 90%);background-size:200%;background-position-x:15%;animation:progress-loading 5s ease-in-out infinite}.progress::-webkit-progress-bar{border-radius:var(--rounded-box,1rem);background-color:transparent}.progress::-webkit-progress-value{border-radius:var(--rounded-box,1rem);background-color:currentColor}.progress:indeterminate::-moz-progress-bar{background-color:transparent;background-image:repeating-linear-gradient(90deg,var(--progress-color) -1%,var(--progress-color) 10%,transparent 10%,transparent 90%);background-size:200%;background-position-x:15%;animation:progress-loading 5s ease-in-out infinite}@keyframes progress-loading{50%{background-position-x:-115%}}@keyframes radiomark{0%{box-shadow:0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset}50%{box-shadow:0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset}to{box-shadow:0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset}}.range:focus-visible::-webkit-slider-thumb{--focus-shadow:0 0 0 6px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 2rem var(--range-shdw) inset}.range:focus-visible::-moz-range-thumb{--focus-shadow:0 0 0 6px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 2rem var(--range-shdw) inset}.range::-webkit-slider-runnable-track{height:.5rem;width:100%;border-radius:var(--rounded-box,1rem);background-color:var(--fallback-bc,oklch(var(--bc)/.1))}.range::-moz-range-track{height:.5rem;width:100%;border-radius:var(--rounded-box,1rem);background-color:var(--fallback-bc,oklch(var(--bc)/.1))}.range::-webkit-slider-thumb{position:relative;height:1.5rem;width:1.5rem;border-radius:var(--rounded-box,1rem);border-style:none;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));appearance:none;-webkit-appearance:none;top:50%;color:var(--range-shdw);transform:translateY(-50%);--filler-size:100rem;--filler-offset:0.6rem;box-shadow:0 0 0 3px var(--range-shdw) inset,var(--focus-shadow,0 0),calc(var(--filler-size)*-1 - var(--filler-offset)) 0 0 var(--filler-size)}.range::-moz-range-thumb{position:relative;height:1.5rem;width:1.5rem;border-radius:var(--rounded-box,1rem);border-style:none;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));top:50%;color:var(--range-shdw);--filler-size:100rem;--filler-offset:0.5rem;box-shadow:0 0 0 3px var(--range-shdw) inset,var(--focus-shadow,0 0),calc(var(--filler-size)*-1 - var(--filler-offset)) 0 0 var(--filler-size)}@keyframes rating-pop{0%{transform:translateY(-.125em)}40%{transform:translateY(-.125em)}to{transform:translateY(0)}}.select:focus{box-shadow:none;border-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-style:solid;outline-width:2px;outline-offset:2px;outline-color:var(--fallback-bc,oklch(var(--bc)/.2))}.select-disabled,.select:disabled,.select[disabled]{cursor:not-allowed;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));color:var(--fallback-bc,oklch(var(--bc)/.4))}.select-disabled::-moz-placeholder,.select:disabled::-moz-placeholder,.select[disabled]::-moz-placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.select-disabled::placeholder,.select:disabled::placeholder,.select[disabled]::placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.select-multiple,.select[multiple],.select[size].select:not([size="1"]){background-image:none;padding-right:1rem}[dir=rtl] .select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}@keyframes skeleton{0%{background-position:150%}to{background-position:-50%}}:where(.\!stats)>:not([hidden])~:not([hidden]){--tw-divide-x-reverse:0!important;--tw-divide-y-reverse:0!important;border-width:calc(0px*(1 - var(--tw-divide-y-reverse))) calc(1px*var(--tw-divide-x-reverse)) calc(0px*var(--tw-divide-y-reverse)) calc(1px*(1 - var(--tw-divide-x-reverse)))!important}:where(.stats)>:not([hidden])~:not([hidden]){--tw-divide-x-reverse:0;--tw-divide-y-reverse:0;border-width:calc(0px*(1 - var(--tw-divide-y-reverse))) calc(1px*var(--tw-divide-x-reverse)) calc(0px*var(--tw-divide-y-reverse)) calc(1px*(1 - var(--tw-divide-x-reverse)))}[dir=rtl] .\!stats>:not([hidden])~:not([hidden]){--tw-divide-x-reverse:1!important}[dir=rtl] .stats>:not([hidden])~:not([hidden]){--tw-divide-x-reverse:1}.steps .step:before{top:0;height:.5rem;width:100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));content:"";margin-inline-start:-100%}.steps .step:after,.steps .step:before{grid-column-start:1;grid-row-start:1;--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));--tw-text-opacity:1}.steps .step:after{content:counter(step);counter-increment:step;z-index:1;position:relative;display:grid;height:2rem;width:2rem;place-items:center;place-self:center;border-radius:9999px;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}.steps .step:first-child:before{content:none}.steps .step[data-content]:after{content:attr(data-content)}.tabs-lifted>.tab:focus-visible{border-end-end-radius:0;border-end-start-radius:0}.tab:is(.tab-active,[aria-selected=true]):not(.tab-disabled):not([disabled]),.tab:is(input:checked){border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));--tw-border-opacity:1;--tw-text-opacity:1}.tab:focus{outline:2px solid transparent;outline-offset:2px}.tab:focus-visible{outline:2px solid currentColor;outline-offset:-5px}.tab-disabled,.tab[disabled]{cursor:not-allowed;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.tabs-bordered>.tab{border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));--tw-border-opacity:0.2;border-style:solid;border-bottom-width:calc(var(--tab-border, 1px) + 1px)}.tabs-lifted>.tab{border:var(--tab-border,1px) solid transparent;border-width:0 0 var(--tab-border,1px) 0;border-start-start-radius:var(--tab-radius,.5rem);border-start-end-radius:var(--tab-radius,.5rem);border-bottom-color:var(--tab-border-color);padding-inline-start:var(--tab-padding,1rem);padding-inline-end:var(--tab-padding,1rem);padding-top:var(--tab-border,1px)}.tabs-lifted>.tab:is(.tab-active,[aria-selected=true]):not(.tab-disabled):not([disabled]),.tabs-lifted>.tab:is(input:checked){background-color:var(--tab-bg);border-width:var(--tab-border,1px) var(--tab-border,1px) 0 var(--tab-border,1px);border-inline-start-color:var(--tab-border-color);border-inline-end-color:var(--tab-border-color);border-top-color:var(--tab-border-color);padding-inline-start:calc(var(--tab-padding, 1rem) - var(--tab-border, 1px));padding-inline-end:calc(var(--tab-padding, 1rem) - var(--tab-border, 1px));padding-bottom:var(--tab-border,1px);padding-top:0}.tabs-lifted>.tab:is(.tab-active,[aria-selected=true]):not(.tab-disabled):not([disabled]):before,.tabs-lifted>.tab:is(input:checked):before{z-index:1;content:"";display:block;position:absolute;width:calc(100% + var(--tab-radius, .5rem)*2);height:var(--tab-radius,.5rem);bottom:0;background-size:var(--tab-radius,.5rem);background-position:0 0,100% 0;background-repeat:no-repeat;--tab-grad:calc(69% - var(--tab-border, 1px));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color) calc(var(--tab-grad) + 0.25px),var(--tab-border-color) calc(var(--tab-grad) + var(--tab-border, 1px)),var(--tab-bg) calc(var(--tab-grad) + var(--tab-border, 1px) + 0.25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color) calc(var(--tab-grad) + 0.25px),var(--tab-border-color) calc(var(--tab-grad) + var(--tab-border, 1px)),var(--tab-bg) calc(var(--tab-grad) + var(--tab-border, 1px) + 0.25px));background-image:var(--radius-start),var(--radius-end)}.tabs-lifted>.tab:is(.tab-active,[aria-selected=true]):not(.tab-disabled):not([disabled]):first-child:before,.tabs-lifted>.tab:is(input:checked):first-child:before{background-image:var(--radius-end);background-position:100% 0}[dir=rtl] .tabs-lifted>.tab:is(.tab-active,[aria-selected=true]):not(.tab-disabled):not([disabled]):first-child:before,[dir=rtl] .tabs-lifted>.tab:is(input:checked):first-child:before{background-image:var(--radius-start);background-position:0 0}.tabs-lifted>.tab:is(.tab-active,[aria-selected=true]):not(.tab-disabled):not([disabled]):last-child:before,.tabs-lifted>.tab:is(input:checked):last-child:before{background-image:var(--radius-start);background-position:0 0}[dir=rtl] .tabs-lifted>.tab:is(.tab-active,[aria-selected=true]):not(.tab-disabled):not([disabled]):last-child:before,[dir=rtl] .tabs-lifted>.tab:is(input:checked):last-child:before{background-image:var(--radius-end);background-position:100% 0}.tabs-lifted>.tab:is(input:checked)+.tabs-lifted .tab:is(input:checked):before,.tabs-lifted>:is(.tab-active,[aria-selected=true]):not(.tab-disabled):not([disabled])+.tabs-lifted :is(.tab-active,[aria-selected=true]):not(.tab-disabled):not([disabled]):before{background-image:var(--radius-end);background-position:100% 0}.tabs-boxed .tab{border-radius:var(--rounded-btn,.5rem)}.table:where([dir=rtl],[dir=rtl] *){text-align:right}.table :where(th,td){padding:.75rem 1rem;vertical-align:middle}.table tr.active,.table tr.active:nth-child(2n),.table-zebra tbody tr:nth-child(2n){--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}.table-zebra tr.active,.table-zebra tr.active:nth-child(2n),.table-zebra-zebra tbody tr:nth-child(2n){--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}.table :where(thead tr,tbody tr:not(:last-child),tbody tr:first-child:last-child){border-bottom-width:1px;--tw-border-opacity:1;border-bottom-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)))}.table :where(thead,tfoot){white-space:nowrap;font-size:.75rem;line-height:1rem;font-weight:700;color:var(--fallback-bc,oklch(var(--bc)/.6))}.table :where(tfoot){border-top-width:1px;--tw-border-opacity:1;border-top-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)))}.toast>*{animation:toast-pop .25s ease-out}@keyframes toast-pop{0%{transform:scale(.9);opacity:0}to{transform:scale(1);opacity:1}}[dir=rtl] .toggle{--handleoffsetcalculator:calc(var(--handleoffset)*1)}.toggle:focus-visible{outline-style:solid;outline-width:2px;outline-offset:2px;outline-color:var(--fallback-bc,oklch(var(--bc)/.2))}.toggle:hover{background-color:currentColor}.toggle:checked,.toggle[aria-checked=true]{background-image:none;--handleoffsetcalculator:var(--handleoffset);--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}[dir=rtl] .toggle:checked,[dir=rtl] .toggle[aria-checked=true]{--handleoffsetcalculator:calc(var(--handleoffset)*-1)}.toggle:indeterminate{--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));box-shadow:calc(var(--handleoffset)/2) 0 0 2px var(--tglbg) inset,calc(var(--handleoffset)/-2) 0 0 2px var(--tglbg) inset,0 0 0 2px var(--tglbg) inset}[dir=rtl] .toggle:indeterminate{box-shadow:calc(var(--handleoffset)/2) 0 0 2px var(--tglbg) inset,calc(var(--handleoffset)/-2) 0 0 2px var(--tglbg) inset,0 0 0 2px var(--tglbg) inset}.toggle-success:focus-visible{outline-color:var(--fallback-su,oklch(var(--su)/1))}.toggle-success:checked,.toggle-success[aria-checked=true]{border-color:var(--fallback-su,oklch(var(--su)/var(--tw-border-opacity)));--tw-border-opacity:0.1;--tw-bg-opacity:1;background-color:var(--fallback-su,oklch(var(--su)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)))}.toggle:disabled{cursor:not-allowed;--tw-border-opacity:1;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));background-color:transparent;opacity:.3;--togglehandleborder:0 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset,var(--handleoffsetcalculator) 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset}.btm-nav-xs>:where(.active){border-top-width:1px}.btm-nav-sm>:where(.active){border-top-width:2px}.btm-nav-md>:where(.active){border-top-width:2px}.btm-nav-lg>:where(.active){border-top-width:4px}.btn-xs{height:1.5rem;min-height:1.5rem;padding-left:.5rem;padding-right:.5rem;font-size:.75rem}.btn-sm{height:2rem;min-height:2rem;padding-left:.75rem;padding-right:.75rem;font-size:.875rem}.btn-square:where(.btn-xs){height:1.5rem;width:1.5rem;padding:0}.btn-square:where(.btn-sm){height:2rem;width:2rem;padding:0}.btn-square:where(.btn-md){height:3rem;width:3rem;padding:0}.btn-square:where(.btn-lg){height:4rem;width:4rem;padding:0}.btn-circle:where(.btn-xs){height:1.5rem;width:1.5rem;border-radius:9999px;padding:0}.btn-circle:where(.btn-sm){height:2rem;width:2rem;border-radius:9999px;padding:0}.btn-circle:where(.btn-md){height:3rem;width:3rem;border-radius:9999px;padding:0}.btn-circle:where(.btn-lg){height:4rem;width:4rem;border-radius:9999px;padding:0}[type=checkbox].checkbox-xs{height:1rem;width:1rem}.indicator :where(.indicator-item){bottom:auto;inset-inline-end:0;inset-inline-start:auto;top:0;--tw-translate-y:-50%;--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item):where([dir=rtl],[dir=rtl] *){--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-start){inset-inline-end:auto;inset-inline-start:0;--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-start):where([dir=rtl],[dir=rtl] *){--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-center){inset-inline-end:50%;inset-inline-start:50%;--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-center):where([dir=rtl],[dir=rtl] *){--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-end){inset-inline-end:0;inset-inline-start:auto;--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-end):where([dir=rtl],[dir=rtl] *){--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-bottom){bottom:0;top:auto;--tw-translate-y:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-middle){bottom:50%;top:50%;--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-top){bottom:auto;top:0;--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.input-xs{height:1.5rem;padding-left:.5rem;padding-right:.5rem;font-size:.75rem;line-height:1rem;line-height:1.625}.input-sm{height:2rem;padding-left:.75rem;padding-right:.75rem;font-size:.875rem;line-height:2rem}.join.join-vertical{flex-direction:column}.join.join-vertical .join-item:first-child:not(:last-child),.join.join-vertical :first-child:not(:last-child) .join-item{border-end-start-radius:0;border-end-end-radius:0;border-start-start-radius:inherit;border-start-end-radius:inherit}.join.join-vertical .join-item:last-child:not(:first-child),.join.join-vertical :last-child:not(:first-child) .join-item{border-start-start-radius:0;border-start-end-radius:0;border-end-start-radius:inherit;border-end-end-radius:inherit}.join.join-horizontal{flex-direction:row}.join.join-horizontal .join-item:first-child:not(:last-child),.join.join-horizontal :first-child:not(:last-child) .join-item{border-end-end-radius:0;border-start-end-radius:0;border-end-start-radius:inherit;border-start-start-radius:inherit}.join.join-horizontal .join-item:last-child:not(:first-child),.join.join-horizontal :last-child:not(:first-child) .join-item{border-end-start-radius:0;border-start-start-radius:0;border-end-end-radius:inherit;border-start-end-radius:inherit}.steps-horizontal .step{display:grid;grid-template-columns:repeat(1,minmax(0,1fr));grid-template-rows:repeat(2,minmax(0,1fr));place-items:center;text-align:center}.steps-vertical .step{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:repeat(1,minmax(0,1fr))}.tabs-md :where(.tab){height:2rem;font-size:.875rem;line-height:1.25rem;line-height:2;--tab-padding:1rem}.tabs-lg :where(.tab){height:3rem;font-size:1.125rem;line-height:1.75rem;line-height:2;--tab-padding:1.25rem}.tabs-sm :where(.tab){height:1.5rem;font-size:.875rem;line-height:.75rem;--tab-padding:0.75rem}.tabs-xs :where(.tab){height:1.25rem;font-size:.75rem;line-height:.75rem;--tab-padding:0.5rem}:where(.toast){bottom:0;inset-inline-end:0;inset-inline-start:auto;top:auto;--tw-translate-x:0px;--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-start){inset-inline-end:auto;inset-inline-start:0;--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-center){inset-inline-end:50%;inset-inline-start:50%;--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-center):where([dir=rtl],[dir=rtl] *){--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-end){inset-inline-end:0;inset-inline-start:auto;--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-bottom){bottom:0;top:auto;--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-middle){bottom:auto;top:50%;--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.toast:where(.toast-top){bottom:auto;top:0;--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}[type=checkbox].toggle-xs{--handleoffset:0.5rem;height:1rem;width:1.5rem}.tooltip{--tooltip-offset:calc(100% + 1px + var(--tooltip-tail, 0px))}.tooltip:before{position:absolute;pointer-events:none;z-index:1;content:var(--tw-content);--tw-content:attr(data-tip)}.tooltip-top:before,.tooltip:before{transform:translateX(-50%);top:auto;left:50%;right:auto;bottom:var(--tooltip-offset)}.tooltip-left:before{left:auto;right:var(--tooltip-offset)}.tooltip-left:before,.tooltip-right:before{transform:translateY(-50%);top:50%;bottom:auto}.tooltip-right:before{left:var(--tooltip-offset);right:auto}.avatar.online:before{background-color:var(--fallback-su,oklch(var(--su)/var(--tw-bg-opacity)))}.avatar.offline:before,.avatar.online:before{content:"";position:absolute;z-index:10;display:block;border-radius:9999px;--tw-bg-opacity:1;outline-style:solid;outline-width:2px;outline-color:var(--fallback-b1,oklch(var(--b1)/1));width:15%;height:15%;top:7%;right:7%}.avatar.offline:before{background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}.join.join-vertical>:where(:not(:first-child)){margin-left:0;margin-right:0;margin-top:-1px}.join.join-vertical>:where(:not(:first-child)):is(.btn){margin-top:calc(var(--border-btn)*-1)}.join.join-horizontal>:where(:not(:first-child)){margin-top:0;margin-bottom:0;margin-inline-start:-1px}.join.join-horizontal>:where(:not(:first-child)):is(.btn){margin-inline-start:calc(var(--border-btn)*-1);margin-top:0}.modal-top :where(.modal-box){width:100%;max-width:none;--tw-translate-y:-2.5rem;--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-bottom-right-radius:var(--rounded-box,1rem);border-bottom-left-radius:var(--rounded-box,1rem);border-top-left-radius:0;border-top-right-radius:0}.modal-middle :where(.modal-box){width:91.666667%;max-width:32rem;--tw-translate-y:0px;--tw-scale-x:.9;--tw-scale-y:.9;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-top-left-radius:var(--rounded-box,1rem);border-top-right-radius:var(--rounded-box,1rem);border-bottom-right-radius:var(--rounded-box,1rem);border-bottom-left-radius:var(--rounded-box,1rem)}.modal-bottom :where(.modal-box){width:100%;max-width:none;--tw-translate-y:2.5rem;--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-top-left-radius:var(--rounded-box,1rem);border-top-right-radius:var(--rounded-box,1rem);border-bottom-right-radius:0;border-bottom-left-radius:0}.steps-horizontal .step{grid-template-rows:40px 1fr;grid-template-columns:auto;min-width:4rem}.steps-horizontal .step:before{height:.5rem;width:100%;--tw-translate-x:0px;--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));content:"";margin-inline-start:-100%}.steps-horizontal .step:where([dir=rtl],[dir=rtl] *):before{--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.steps-vertical .step{gap:.5rem;grid-template-columns:40px 1fr;grid-template-rows:auto;min-height:4rem;justify-items:start}.steps-vertical .step:before{height:100%;width:.5rem;--tw-translate-x:-50%;--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));margin-inline-start:50%}.steps-vertical .step:where([dir=rtl],[dir=rtl] *):before{--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.table-xs :not(thead):not(tfoot) tr{font-size:.75rem;line-height:1rem}.table-xs :where(th,td){padding:.25rem .5rem}.table-sm :not(thead):not(tfoot) tr{font-size:.875rem;line-height:1.25rem}.table-sm :where(th,td){padding:.5rem .75rem}.tooltip{position:relative;display:inline-block;text-align:center;--tooltip-tail:0.1875rem;--tooltip-color:var(--fallback-n,oklch(var(--n)/1));--tooltip-text-color:var(--fallback-nc,oklch(var(--nc)/1));--tooltip-tail-offset:calc(100% + 0.0625rem - var(--tooltip-tail))}.tooltip:after,.tooltip:before{opacity:0;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-delay:.1s;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.tooltip:after{position:absolute;content:"";border-style:solid;border-width:var(--tooltip-tail,0);width:0;height:0;display:block}.tooltip:before{max-width:20rem;white-space:normal;border-radius:.25rem;padding:.25rem .5rem;font-size:.875rem;line-height:1.25rem;background-color:var(--tooltip-color);color:var(--tooltip-text-color);width:-moz-max-content;width:max-content}.tooltip.tooltip-open:after,.tooltip.tooltip-open:before,.tooltip:hover:after,.tooltip:hover:before{opacity:1;transition-delay:75ms}.tooltip:has(:focus-visible):after,.tooltip:has(:focus-visible):before{opacity:1;transition-delay:75ms}.tooltip:not([data-tip]):hover:after,.tooltip:not([data-tip]):hover:before{visibility:hidden;opacity:0}.tooltip-top:after,.tooltip:after{transform:translateX(-50%);border-color:var(--tooltip-color) transparent transparent transparent;top:auto;left:50%;right:auto;bottom:var(--tooltip-tail-offset)}.tooltip-left:after{border-color:transparent transparent transparent var(--tooltip-color);left:auto;right:calc(var(--tooltip-tail-offset) + .0625rem)}.tooltip-left:after,.tooltip-right:after{transform:translateY(-50%);top:50%;bottom:auto}.tooltip-right:after{border-color:transparent var(--tooltip-color) transparent transparent;left:calc(var(--tooltip-tail-offset) + .0625rem);right:auto}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-3{left:.75rem}.right-0{right:0}.right-2{right:.5rem}.right-3{right:.75rem}.right-4{right:1rem}.top-1\.5{top:.375rem}.top-2{top:.5rem}.top-3{top:.75rem}.top-4{top:1rem}.top-full{top:100%}.z-10{z-index:10}.z-50{z-index:50}.z-\[100\]{z-index:100}.z-\[9999\]{z-index:9999}.col-span-1{grid-column:span 1/span 1}.col-span-full{grid-column:1/-1}.-mx-2{margin-left:-.5rem;margin-right:-.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-2{margin-top:.5rem;margin-bottom:.5rem}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-4{margin-left:1rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-auto{margin-top:auto}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-20{height:5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[18px\]{height:18px}.h-\[calc\(100vh-56px\)\]{height:calc(100vh - 56px)}.h-full{height:100%}.h-px{height:1px}.max-h-60{max-height:15rem}.max-h-64{max-height:16rem}.min-h-0{min-height:0}.min-h-\[400px\]{min-height:400px}.min-h-\[48px\]{min-height:48px}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-2\/12{width:16.666667%}.w-20{width:5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-5\/12{width:41.666667%}.w-6{width:1.5rem}.w-64{width:16rem}.w-72{width:18rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0}.min-w-\[12rem\]{min-width:12rem}.min-w-\[200px\]{min-width:200px}.min-w-\[300px\]{min-width:300px}.min-w-\[8rem\]{min-width:8rem}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-\[200px\]{max-width:200px}.max-w-\[320px\]{max-width:320px}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-4{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-4{--tw-translate-x:1rem}.translate-x-8{--tw-translate-x:2rem}.rotate-180,.translate-x-8{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.scale-100{--tw-scale-x:1;--tw-scale-y:1}.scale-100,.scale-75{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-75{--tw-scale-x:.75;--tw-scale-y:.75}.scale-95{--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes ping{75%,to{transform:scale(2);opacity:0}}.animate-ping{animation:ping 1s cubic-bezier(0,0,.2,1) infinite}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-y-2{row-gap:.5rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem*var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-\[2px\]{border-radius:2px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-none{border-style:none}.\!border-space-border{--tw-border-opacity:1!important;border-color:rgb(39 39 42/var(--tw-border-opacity,1))!important}.border-blue-400\/50{border-color:rgba(96,165,250,.5)}.border-blue-500\/20{border-color:rgba(59,130,246,.2)}.border-blue-500\/30{border-color:rgba(59,130,246,.3)}.border-emerald-500\/20{border-color:rgba(16,185,129,.2)}.border-gray-500\/30{border-color:hsla(220,9%,46%,.3)}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.border-green-500\/50{border-color:rgba(34,197,94,.5)}.border-neon-cyan\/20{border-color:rgba(6,182,212,.2)}.border-neon-green\/20{border-color:rgba(34,197,94,.2)}.border-neon-green\/50{border-color:rgba(34,197,94,.5)}.border-neon-green\/60{border-color:rgba(34,197,94,.6)}.border-neon-purple{--tw-border-opacity:1;border-color:rgb(168 85 247/var(--tw-border-opacity,1))}.border-neon-purple\/50{border-color:rgba(168,85,247,.5)}.border-neon-purple\/60{border-color:rgba(168,85,247,.6)}.border-neon-yellow\/20{border-color:rgba(234,179,8,.2)}.border-neon-yellow\/30{border-color:rgba(234,179,8,.3)}.border-purple-500\/20{border-color:rgba(168,85,247,.2)}.border-red-500\/20{border-color:rgba(239,68,68,.2)}.border-red-500\/30{border-color:rgba(239,68,68,.3)}.border-red-500\/50{border-color:rgba(239,68,68,.5)}.border-space-border{--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.border-space-border\/10{border-color:rgba(39,39,42,.1)}.border-space-border\/20{border-color:rgba(39,39,42,.2)}.border-space-border\/30{border-color:rgba(39,39,42,.3)}.border-space-border\/40{border-color:rgba(39,39,42,.4)}.border-space-border\/50{border-color:rgba(39,39,42,.5)}.border-space-border\/60{border-color:rgba(39,39,42,.6)}.border-transparent{border-color:transparent}.border-yellow-400\/50{border-color:rgba(250,204,21,.5)}.border-yellow-500\/20{border-color:rgba(234,179,8,.2)}.border-yellow-500\/30{border-color:rgba(234,179,8,.3)}.border-yellow-500\/50{border-color:rgba(234,179,8,.5)}.\!bg-space-800{--tw-bg-opacity:1!important;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))!important}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-emerald-500\/10{background-color:rgba(16,185,129,.1)}.bg-gray-500\/10{background-color:hsla(220,9%,46%,.1)}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.bg-gray-700\/50{background-color:rgba(55,65,81,.5)}.bg-green-500\/20{background-color:rgba(34,197,94,.2)}.bg-neon-green{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-neon-green\/10{background-color:rgba(34,197,94,.1)}.bg-neon-green\/20{background-color:rgba(34,197,94,.2)}.bg-neon-green\/5{background-color:rgba(34,197,94,.05)}.bg-neon-purple{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.bg-neon-purple\/20{background-color:rgba(168,85,247,.2)}.bg-neon-purple\/5{background-color:rgba(168,85,247,.05)}.bg-neon-yellow\/10{background-color:rgba(234,179,8,.1)}.bg-neon-yellow\/5{background-color:rgba(234,179,8,.05)}.bg-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-red-500\/10{background-color:rgba(239,68,68,.1)}.bg-red-500\/20{background-color:rgba(239,68,68,.2)}.bg-red-900{--tw-bg-opacity:1;background-color:rgb(127 29 29/var(--tw-bg-opacity,1))}.bg-space-800{--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.bg-space-800\/50{background-color:rgba(24,24,27,.5)}.bg-space-850{--tw-bg-opacity:1;background-color:rgb(18 18 20/var(--tw-bg-opacity,1))}.bg-space-900{--tw-bg-opacity:1;background-color:rgb(15 15 17/var(--tw-bg-opacity,1))}.bg-space-900\/20{background-color:rgba(15,15,17,.2)}.bg-space-900\/30{background-color:rgba(15,15,17,.3)}.bg-space-900\/40{background-color:rgba(15,15,17,.4)}.bg-space-900\/50{background-color:rgba(15,15,17,.5)}.bg-space-900\/60{background-color:rgba(15,15,17,.6)}.bg-space-900\/90{background-color:rgba(15,15,17,.9)}.bg-space-950{--tw-bg-opacity:1;background-color:rgb(9 9 11/var(--tw-bg-opacity,1))}.bg-space-border{--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1))}.bg-space-border\/20{background-color:rgba(39,39,42,.2)}.bg-space-border\/30{background-color:rgba(39,39,42,.3)}.bg-transparent{background-color:transparent}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.bg-yellow-500\/10{background-color:rgba(234,179,8,.1)}.bg-yellow-500\/20{background-color:rgba(234,179,8,.2)}.bg-zinc-600{--tw-bg-opacity:1;background-color:rgb(82 82 91/var(--tw-bg-opacity,1))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-neon-purple{--tw-gradient-from:#a855f7 var(--tw-gradient-from-position);--tw-gradient-to:rgba(168,85,247,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-blue-600{--tw-gradient-to:#2563eb var(--tw-gradient-to-position)}.stroke-current{stroke:currentColor}.stroke-info{stroke:var(--fallback-in,oklch(var(--in)/1))}.\!p-0{padding:0!important}.\!p-4{padding:1rem!important}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-0{padding-bottom:0}.pb-1{padding-bottom:.25rem}.pb-10{padding-bottom:2.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-6{padding-left:1.5rem}.pl-7{padding-left:1.75rem}.pl-9{padding-left:2.25rem}.pr-10{padding-right:2.5rem}.pr-2{padding-right:.5rem}.pr-3{padding-right:.75rem}.pr-4{padding-right:1rem}.pr-6{padding-right:1.5rem}.pr-8{padding-right:2rem}.pt-0{padding-top:0}.pt-2{padding-top:.5rem}.pt-6{padding-top:1.5rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:JetBrains Mono,Fira Code,Consolas,monospace}.font-sans{font-family:Inter,system-ui,sans-serif}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.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)}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-\[0\.15em\]{letter-spacing:.15em}.tracking-tight{letter-spacing:-.025em}.tracking-tighter{letter-spacing:-.05em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.\!text-gray-500{--tw-text-opacity:1!important;color:rgb(107 114 128/var(--tw-text-opacity,1))!important}.\!text-white{--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity,1))!important}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-cyan-400\/60{color:rgba(34,211,238,.6)}.text-emerald-400{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.text-gray-700\/40{color:rgba(55,65,81,.4)}.text-green-400\/60{color:rgba(74,222,128,.6)}.text-neon-cyan{--tw-text-opacity:1;color:rgb(6 182 212/var(--tw-text-opacity,1))}.text-neon-green{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-neon-purple{--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity,1))}.text-neon-yellow{--tw-text-opacity:1;color:rgb(234 179 8/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-red-300{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-red-500\/60{color:rgba(239,68,68,.6)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity,1))}.text-yellow-500{--tw-text-opacity:1;color:rgb(234 179 8/var(--tw-text-opacity,1))}.text-yellow-500\/80{color:rgba(234,179,8,.8)}.text-zinc-300{--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.text-zinc-700{--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.placeholder-gray-700::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(55 65 81/var(--tw-placeholder-opacity,1))}.placeholder-gray-700::placeholder{--tw-placeholder-opacity:1;color:rgb(55 65 81/var(--tw-placeholder-opacity,1))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_15px_rgba\(168\2c 85\2c 247\2c 0\.1\)\]{--tw-shadow:0 0 15px rgba(168,85,247,.1);--tw-shadow-colored:0 0 15px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_15px_rgba\(168\2c 85\2c 247\2c 0\.4\)\]{--tw-shadow:0 0 15px rgba(168,85,247,.4);--tw-shadow-colored:0 0 15px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_15px_rgba\(34\2c 197\2c 94\2c 0\.1\)\]{--tw-shadow:0 0 15px rgba(34,197,94,.1);--tw-shadow-colored:0 0 15px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_50px_rgba\(0\2c 0\2c 0\2c 0\.5\)\]{--tw-shadow:0 0 50px rgba(0,0,0,.5);--tw-shadow-colored:0 0 50px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_5px_rgba\(168\2c 85\2c 247\2c 0\.5\)\]{--tw-shadow:0 0 5px rgba(168,85,247,.5);--tw-shadow-colored:0 0 5px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_5px_rgba\(34\2c 197\2c 94\2c 0\.5\)\]{--tw-shadow:0 0 5px rgba(34,197,94,.5);--tw-shadow-colored:0 0 5px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_8px_rgba\(239\2c 68\2c 68\2c 0\.6\)\]{--tw-shadow:0 0 8px rgba(239,68,68,.6);--tw-shadow-colored:0 0 8px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_8px_rgba\(34\2c 197\2c 94\2c 0\.6\)\]{--tw-shadow:0 0 8px rgba(34,197,94,.6);--tw-shadow-colored:0 0 8px var(--tw-shadow-color)}.shadow-\[0_0_8px_rgba\(34\2c 197\2c 94\2c 0\.6\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-none{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}.shadow-none,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.shadow-neon-green\/10{--tw-shadow-color:rgba(34,197,94,.1);--tw-shadow:var(--tw-shadow-colored)}.shadow-neon-purple\/10{--tw-shadow-color:rgba(168,85,247,.1);--tw-shadow:var(--tw-shadow-colored)}.shadow-neon-purple\/20{--tw-shadow-color:rgba(168,85,247,.2);--tw-shadow:var(--tw-shadow-colored)}.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-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-md,.backdrop-blur-sm{backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}:root{--color-space-950:#09090b;--color-space-900:#0f0f11;--color-space-850:#121214;--color-space-800:#18181b;--color-space-border:#27272a;--color-neon-purple:#a855f7;--color-neon-green:#22c55e;--color-neon-cyan:#06b6d4;--color-neon-yellow:#eab308;--color-neon-red:#ef4444;--color-neon-purple-soft:#9333ea;--color-neon-green-soft:#16a34a;--color-neon-cyan-soft:#0891b2;--color-text-primary:#fff;--color-text-secondary:#d4d4d8;--color-text-tertiary:#a1a1aa;--color-text-quaternary:#71717a;--color-text-main:var(--color-text-secondary);--color-text-dim:var(--color-text-tertiary);--color-text-muted:var(--color-text-tertiary);--color-text-bright:var(--color-text-primary);--color-green-400:#4ade80;--color-yellow-400:#facc15;--color-red-400:#f87171;--color-chart-1:#a855f7;--color-chart-2:#c084fc;--color-chart-3:#e879f9;--color-chart-4:#d946ef;--color-chart-5:#22c55e;--color-chart-6:#4ade80;--color-chart-7:#86efac;--color-chart-8:#10b981;--color-chart-9:#06b6d4;--color-chart-10:#f59e0b;--color-chart-11:#ef4444;--color-chart-12:#ec4899;--color-chart-13:#8b5cf6;--color-chart-14:#14b8a6;--color-chart-15:#f97316;--color-chart-16:#6366f1}[x-cloak]{display:none!important}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:rgba(9,9,11,.3);border-radius:4px}::-webkit-scrollbar-thumb{background:linear-gradient(180deg,#27272a,#18181b);border-radius:4px;border:1px solid hsla(0,0%,100%,.05);-webkit-transition:background .2s ease;transition:background .2s ease}::-webkit-scrollbar-thumb:hover{background:linear-gradient(180deg,#3f3f46,#27272a);border-color:rgba(168,85,247,.3)}.fade-enter-active,.fade-leave-active{transition:opacity .2s ease}.fade-enter-from,.fade-leave-to{opacity:0}@keyframes fadeIn{0%{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}.animate-fade-in{animation:fadeIn .4s ease-out forwards}.nav-item.active{background:linear-gradient(90deg,rgba(168,85,247,.15),transparent);border-left-width:4px;--tw-border-opacity:1;border-color:rgb(168 85 247/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.nav-item{border-left-width:4px;border-color:transparent;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.progress-gradient-success::-webkit-progress-value{background-image:linear-gradient(to right,var(--color-neon-green),var(--color-green-400))}.progress-gradient-warning::-webkit-progress-value{background-image:linear-gradient(to right,var(--color-neon-yellow),var(--color-yellow-400))}.progress-gradient-error::-webkit-progress-value{background-image:linear-gradient(to right,var(--color-neon-red),var(--color-red-400))}.stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:1.5rem}.tooltip:before{border-width:1px;--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1));font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:.75rem;line-height:1rem;--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.tooltip-left:before{margin-right:.5rem}:root{--view-padding:2rem;--view-gap:2rem;--card-radius:0.75rem}@media (max-width:768px){:root{--view-padding:1rem;--view-gap:1.25rem}}.view-container{display:flex;flex-direction:column;margin-left:auto;margin-right:auto;width:100%;padding:var(--view-padding);gap:var(--view-gap);min-height:calc(100vh - 56px);max-width:1400px;scrollbar-gutter:stable}.view-container-full{max-width:100%}.view-container-centered,.view-container-full{display:flex;width:100%;flex-direction:column;animation:fadeIn .4s ease-out forwards;padding:var(--view-padding);gap:var(--view-gap);min-height:calc(100vh - 56px)}.view-container-centered{margin-left:auto;margin-right:auto;max-width:900px}.view-header{display:flex;flex-direction:column;justify-content:space-between;margin-bottom:.5rem;gap:1rem}@media (min-width:768px){.view-header{flex-direction:row;align-items:flex-end}}.view-header-title{display:flex;flex-direction:column}.view-header-title h2{font-size:1.5rem;line-height:2rem;font-weight:700;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.view-header-title p{margin-top:.25rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.view-header-actions{display:flex;align-items:center;gap:.75rem}.view-card{position:relative;overflow:hidden;border-radius:var(--card-radius);padding:1.5rem;border:1px solid hsla(0,0%,100%,.08);background:linear-gradient(135deg,rgba(15,15,17,.75),rgba(18,18,20,.7));backdrop-filter:blur(12px);box-shadow:inset 0 0 0 1px hsla(0,0%,100%,.02),0 4px 24px rgba(0,0,0,.4);transition:border-color .3s ease,box-shadow .3s ease}.view-card:hover{border-color:hsla(0,0%,100%,.12);box-shadow:inset 0 0 0 1px hsla(0,0%,100%,.04),0 8px 32px rgba(0,0,0,.5)}.view-card-header{margin-bottom:1rem;display:flex;align-items:center;justify-content:space-between;border-bottom-width:1px;border-color:rgba(39,39,42,.3);padding-bottom:1rem}@media (hover:hover){.standard-table tr.hover:hover,.standard-table tr.hover:nth-child(2n):hover{--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}}.standard-table{position:relative;border-radius:var(--rounded-box,1rem);text-align:left;font-size:.875rem;line-height:1.25rem}.standard-table :where(.table-pin-rows thead tr){position:sticky;top:0;z-index:1;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.standard-table :where(.table-pin-rows tfoot tr){position:sticky;bottom:0;z-index:1;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.standard-table :where(.table-pin-cols tr th){position:sticky;left:0;right:0;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.standard-table:where([dir=rtl],[dir=rtl] *){text-align:right}.standard-table :where(th,td){padding:.75rem 1rem;vertical-align:middle}.standard-table tr.active,.standard-table tr.active:nth-child(2n){--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}.standard-table :where(thead tr,tbody tr:not(:last-child),tbody tr:first-child:last-child){border-bottom-width:1px;--tw-border-opacity:1;border-bottom-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)))}.standard-table :where(thead,tfoot){white-space:nowrap;font-size:.75rem;line-height:1rem;font-weight:700;color:var(--fallback-bc,oklch(var(--bc)/.6))}.standard-table :where(tfoot){border-top-width:1px;--tw-border-opacity:1;border-top-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)))}.standard-table{display:table;width:100%;border-collapse:separate;--tw-border-spacing-x:0px;--tw-border-spacing-y:0px;border-spacing:var(--tw-border-spacing-x) var(--tw-border-spacing-y)}.standard-table thead{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));background-color:rgba(15,15,17,.5);font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:.75rem;line-height:1rem;text-transform:uppercase;--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.standard-table tbody tr{border-bottom-width:1px;border-color:rgba(39,39,42,.3);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.standard-table tbody tr:last-child{border-width:0}.standard-table tbody tr:hover{background:linear-gradient(90deg,hsla(0,0%,100%,.03),hsla(0,0%,100%,.05) 50%,hsla(0,0%,100%,.03));border-color:hsla(0,0%,100%,.08);box-shadow:0 1px 3px rgba(0,0,0,.3)}.custom-range{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:4px;background:var(--color-space-800);border-radius:999px;outline:none;cursor:pointer}.custom-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:14px;height:14px;border-radius:50%;background:var(--range-color,var(--color-neon-purple));cursor:pointer;-webkit-transition:transform .1s ease;transition:transform .1s ease}.custom-range::-webkit-slider-thumb:hover{transform:scale(1.15)}.custom-range::-moz-range-thumb{width:14px;height:14px;border:none;border-radius:50%;background:var(--range-color,var(--color-neon-purple));cursor:pointer;-moz-transition:transform .1s ease;transition:transform .1s ease}.custom-range::-moz-range-thumb:hover{transform:scale(1.15)}.custom-range-purple{--range-color:var(--color-neon-purple)}.custom-range-green{--range-color:var(--color-neon-green)}.custom-range-cyan{--range-color:var(--color-neon-cyan)}.custom-range-yellow{--range-color:var(--color-neon-yellow)}.custom-range-accent{--range-color:var(--color-neon-cyan)}.btn-action-ghost{display:inline-flex;height:3rem;min-height:3rem;flex-shrink:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-wrap:wrap;align-items:center;justify-content:center;border-radius:var(--rounded-btn,.5rem);border-color:oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;text-align:center;font-size:.875rem;line-height:1em;gap:.5rem;font-weight:600;text-decoration-line:none;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);border-width:var(--border-btn,1px);transition-property:color,background-color,border-color,opacity,box-shadow,transform;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);outline-color:var(--fallback-bc,oklch(var(--bc)/1));background-color:oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity));--tw-bg-opacity:1;--tw-border-opacity:1}.btn-action-ghost:disabled,.btn-action-ghost[disabled]{pointer-events:none}:where(.btn-action-ghost:is(input[type=checkbox])),:where(.btn-action-ghost:is(input[type=radio])){width:auto;-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn-action-ghost:is(input[type=checkbox]):after,.btn-action-ghost:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}@media (hover:hover){.btn-action-ghost:hover{--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-action-ghost:hover{background-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity,1)) 90%,#000);border-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity,1)) 90%,#000)}}@supports not (color:oklch(0% 0 0)){.btn-action-ghost:hover{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-ghost.glass:hover{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-ghost:hover{border-color:transparent}@supports (color:oklch(0% 0 0)){.btn-action-ghost:hover{background-color:var(--fallback-bc,oklch(var(--bc)/.2))}}.btn-action-ghost:disabled:hover,.btn-action-ghost[disabled]:hover{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}@supports (color:color-mix(in oklab,black,black)){.btn-action-ghost:is(input[type=checkbox]:checked):hover,.btn-action-ghost:is(input[type=radio]:checked):hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}}@media (prefers-reduced-motion:no-preference){.btn-action-ghost{animation:button-pop var(--animation-btn,.25s) ease-out}}.btn-action-ghost:active:focus,.btn-action-ghost:active:hover{animation:button-pop 0s ease-out;transform:scale(var(--btn-focus-scale,.97))}@supports not (color:oklch(0% 0 0)){.btn-action-ghost{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-ghost:focus-visible{outline-style:solid;outline-width:2px;outline-offset:2px}.btn-action-ghost.glass{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-ghost.glass.btn-active{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-ghost{border-width:1px;border-color:transparent;background-color:transparent;color:currentColor;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-ghost.btn-active{border-color:transparent;background-color:var(--fallback-bc,oklch(var(--bc)/.2))}.btn-action-ghost.btn-disabled,.btn-action-ghost:disabled,.btn-action-ghost[disabled]{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn-action-ghost:is(input[type=checkbox]:checked),.btn-action-ghost:is(input[type=radio]:checked){--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn-action-ghost:is(input[type=checkbox]:checked):focus-visible,.btn-action-ghost:is(input[type=radio]:checked):focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}.join>:where(:not(:first-child)):is(.btn-action-ghost){margin-inline-start:calc(var(--border-btn)*-1)}.btn-action-ghost{height:1.5rem;min-height:1.5rem;padding-left:.5rem;padding-right:.5rem;font-size:.75rem}.btn-square:where(.btn-action-ghost){height:1.5rem;width:1.5rem;padding:0}.btn-circle:where(.btn-action-ghost){height:1.5rem;width:1.5rem;border-radius:9999px;padding:0}.join.join-vertical>:where(:not(:first-child)):is(.btn-action-ghost){margin-top:calc(var(--border-btn)*-1)}.join.join-horizontal>:where(:not(:first-child)):is(.btn-action-ghost){margin-inline-start:calc(var(--border-btn)*-1);margin-top:0}.btn-action-ghost{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.btn-action-ghost:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.btn-action-ghost-square{display:inline-flex;min-height:3rem;flex-shrink:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-wrap:wrap;align-items:center;justify-content:center;border-radius:var(--rounded-btn,.5rem);border-color:oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;text-align:center;font-size:.875rem;line-height:1em;gap:.5rem;font-weight:600;text-decoration-line:none;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);border-width:var(--border-btn,1px);transition-property:color,background-color,border-color,opacity,box-shadow,transform;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);outline-color:var(--fallback-bc,oklch(var(--bc)/1));background-color:oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity));--tw-bg-opacity:1;--tw-border-opacity:1}.btn-action-ghost-square:disabled,.btn-action-ghost-square[disabled]{pointer-events:none}.btn-action-ghost-square{height:3rem;width:3rem;padding:0}:where(.btn-action-ghost-square:is(input[type=checkbox])),:where(.btn-action-ghost-square:is(input[type=radio])){width:auto;-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn-action-ghost-square:is(input[type=checkbox]):after,.btn-action-ghost-square:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}@media (hover:hover){.btn-action-ghost-square:hover{--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-action-ghost-square:hover{background-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity,1)) 90%,#000);border-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity,1)) 90%,#000)}}@supports not (color:oklch(0% 0 0)){.btn-action-ghost-square:hover{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-ghost-square.glass:hover{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-ghost-square:hover{border-color:transparent}@supports (color:oklch(0% 0 0)){.btn-action-ghost-square:hover{background-color:var(--fallback-bc,oklch(var(--bc)/.2))}}.btn-action-ghost-square:disabled:hover,.btn-action-ghost-square[disabled]:hover{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}@supports (color:color-mix(in oklab,black,black)){.btn-action-ghost-square:is(input[type=checkbox]:checked):hover,.btn-action-ghost-square:is(input[type=radio]:checked):hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}}@media (prefers-reduced-motion:no-preference){.btn-action-ghost-square{animation:button-pop var(--animation-btn,.25s) ease-out}}.btn-action-ghost-square:active:focus,.btn-action-ghost-square:active:hover{animation:button-pop 0s ease-out;transform:scale(var(--btn-focus-scale,.97))}@supports not (color:oklch(0% 0 0)){.btn-action-ghost-square{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-ghost-square:focus-visible{outline-style:solid;outline-width:2px;outline-offset:2px}.btn-action-ghost-square.glass{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-ghost-square.glass.btn-active{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-ghost-square{border-width:1px;border-color:transparent;background-color:transparent;color:currentColor;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-ghost-square.btn-active{border-color:transparent;background-color:var(--fallback-bc,oklch(var(--bc)/.2))}.btn-action-ghost-square.btn-disabled,.btn-action-ghost-square:disabled,.btn-action-ghost-square[disabled]{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn-action-ghost-square:is(input[type=checkbox]:checked),.btn-action-ghost-square:is(input[type=radio]:checked){--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn-action-ghost-square:is(input[type=checkbox]:checked):focus-visible,.btn-action-ghost-square:is(input[type=radio]:checked):focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}.join>:where(:not(:first-child)):is(.btn-action-ghost-square){margin-inline-start:calc(var(--border-btn)*-1)}.btn-action-ghost-square{height:1.5rem;min-height:1.5rem;padding-left:.5rem;padding-right:.5rem;font-size:.75rem}.btn-action-ghost-square:where(.btn-xs){height:1.5rem;width:1.5rem;padding:0}.btn-square:where(.btn-action-ghost-square){height:1.5rem;width:1.5rem;padding:0}.btn-action-ghost-square:where(.btn-sm){height:2rem;width:2rem;padding:0}.btn-action-ghost-square:where(.btn-md){height:3rem;width:3rem;padding:0}.btn-action-ghost-square:where(.btn-lg){height:4rem;width:4rem;padding:0}.btn-circle:where(.btn-action-ghost-square){height:1.5rem;width:1.5rem;border-radius:9999px;padding:0}.join.join-vertical>:where(:not(:first-child)):is(.btn-action-ghost-square){margin-top:calc(var(--border-btn)*-1)}.join.join-horizontal>:where(:not(:first-child)):is(.btn-action-ghost-square){margin-inline-start:calc(var(--border-btn)*-1);margin-top:0}.btn-action-ghost-square{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.btn-action-ghost-square:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.btn-action-primary{display:inline-flex;height:3rem;min-height:3rem;flex-shrink:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-wrap:wrap;align-items:center;justify-content:center;border-radius:var(--rounded-btn,.5rem);border-color:transparent;border-color:oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;text-align:center;font-size:.875rem;line-height:1em;gap:.5rem;font-weight:600;text-decoration-line:none;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);border-width:var(--border-btn,1px);transition-property:color,background-color,border-color,opacity,box-shadow,transform;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);outline-color:var(--fallback-bc,oklch(var(--bc)/1));background-color:oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity));--tw-bg-opacity:1;--tw-border-opacity:1}.btn-action-primary:disabled,.btn-action-primary[disabled]{pointer-events:none}:where(.btn-action-primary:is(input[type=checkbox])),:where(.btn-action-primary:is(input[type=radio])){width:auto;-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn-action-primary:is(input[type=checkbox]):after,.btn-action-primary:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}@media (hover:hover){.btn-action-primary:hover{--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-action-primary:hover{background-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity,1)) 90%,#000);border-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity,1)) 90%,#000)}}@supports not (color:oklch(0% 0 0)){.btn-action-primary:hover{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-primary.glass:hover{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-primary:disabled:hover,.btn-action-primary[disabled]:hover{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}@supports (color:color-mix(in oklab,black,black)){.btn-action-primary:is(input[type=checkbox]:checked):hover,.btn-action-primary:is(input[type=radio]:checked):hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}}@media (prefers-reduced-motion:no-preference){.btn-action-primary{animation:button-pop var(--animation-btn,.25s) ease-out}}.btn-action-primary:active:focus,.btn-action-primary:active:hover{animation:button-pop 0s ease-out;transform:scale(var(--btn-focus-scale,.97))}@supports not (color:oklch(0% 0 0)){.btn-action-primary{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-primary:focus-visible{outline-style:solid;outline-width:2px;outline-offset:2px}.btn-action-primary.glass{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-primary.glass.btn-active{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-primary.btn-disabled,.btn-action-primary:disabled,.btn-action-primary[disabled]{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn-action-primary:is(input[type=checkbox]:checked),.btn-action-primary:is(input[type=radio]:checked){--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn-action-primary:is(input[type=checkbox]:checked):focus-visible,.btn-action-primary:is(input[type=radio]:checked):focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}.join>:where(:not(:first-child)):is(.btn-action-primary){margin-inline-start:calc(var(--border-btn)*-1)}.join.join-vertical>:where(:not(:first-child)):is(.btn-action-primary){margin-top:calc(var(--border-btn)*-1)}.join.join-horizontal>:where(:not(:first-child)):is(.btn-action-primary){margin-inline-start:calc(var(--border-btn)*-1);margin-top:0}.btn-action-primary{border-style:none;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from:#a855f7 var(--tw-gradient-from-position);--tw-gradient-to:rgba(168,85,247,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);--tw-gradient-to:#4f46e5 var(--tw-gradient-to-position);--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1));--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-shadow-color:rgba(168,85,247,.2);--tw-shadow:var(--tw-shadow-colored);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.btn-action-primary:hover{--tw-shadow-color:rgba(168,85,247,.4);--tw-shadow:var(--tw-shadow-colored)}.btn-action-success{display:inline-flex;min-height:3rem;flex-shrink:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-wrap:wrap;align-items:center;justify-content:center;border-radius:var(--rounded-btn,.5rem);border-color:oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;text-align:center;font-size:.875rem;line-height:1em;gap:.5rem;font-weight:600;text-decoration-line:none;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);border-width:var(--border-btn,1px);transition-property:color,background-color,border-color,opacity,box-shadow,transform;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);outline-color:var(--fallback-bc,oklch(var(--bc)/1));background-color:oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity));--tw-bg-opacity:1;--tw-border-opacity:1}.btn-action-success:disabled,.btn-action-success[disabled]{pointer-events:none}.btn-action-success{height:3rem;width:3rem;padding:0}:where(.btn-action-success:is(input[type=checkbox])),:where(.btn-action-success:is(input[type=radio])){width:auto;-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn-action-success:is(input[type=checkbox]):after,.btn-action-success:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}@media (hover:hover){.btn-action-success:hover{--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-action-success:hover{background-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity,1)) 90%,#000);border-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity,1)) 90%,#000)}}@supports not (color:oklch(0% 0 0)){.btn-action-success:hover{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-success.glass:hover{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-success:hover{border-color:transparent}@supports (color:oklch(0% 0 0)){.btn-action-success:hover{background-color:var(--fallback-bc,oklch(var(--bc)/.2))}}.btn-action-success:disabled:hover,.btn-action-success[disabled]:hover{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}@supports (color:color-mix(in oklab,black,black)){.btn-action-success:is(input[type=checkbox]:checked):hover,.btn-action-success:is(input[type=radio]:checked):hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}}@media (prefers-reduced-motion:no-preference){.btn-action-success{animation:button-pop var(--animation-btn,.25s) ease-out}}.btn-action-success:active:focus,.btn-action-success:active:hover{animation:button-pop 0s ease-out;transform:scale(var(--btn-focus-scale,.97))}@supports not (color:oklch(0% 0 0)){.btn-action-success{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-success:focus-visible{outline-style:solid;outline-width:2px;outline-offset:2px}.btn-action-success.glass{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-success.glass.btn-active{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-success{border-width:1px;border-color:transparent;background-color:transparent;color:currentColor;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-success.btn-active{border-color:transparent;background-color:var(--fallback-bc,oklch(var(--bc)/.2))}.btn-action-success.btn-disabled,.btn-action-success:disabled,.btn-action-success[disabled]{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn-action-success:is(input[type=checkbox]:checked),.btn-action-success:is(input[type=radio]:checked){--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn-action-success:is(input[type=checkbox]:checked):focus-visible,.btn-action-success:is(input[type=radio]:checked):focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}.join>:where(:not(:first-child)):is(.btn-action-success){margin-inline-start:calc(var(--border-btn)*-1)}.btn-action-success{height:1.5rem;min-height:1.5rem;padding-left:.5rem;padding-right:.5rem;font-size:.75rem}.btn-action-success:where(.btn-xs){height:1.5rem;width:1.5rem;padding:0}.btn-square:where(.btn-action-success){height:1.5rem;width:1.5rem;padding:0}.btn-action-success:where(.btn-sm){height:2rem;width:2rem;padding:0}.btn-action-success:where(.btn-md){height:3rem;width:3rem;padding:0}.btn-action-success:where(.btn-lg){height:4rem;width:4rem;padding:0}.btn-circle:where(.btn-action-success){height:1.5rem;width:1.5rem;border-radius:9999px;padding:0}.join.join-vertical>:where(:not(:first-child)):is(.btn-action-success){margin-top:calc(var(--border-btn)*-1)}.join.join-horizontal>:where(:not(:first-child)):is(.btn-action-success){margin-inline-start:calc(var(--border-btn)*-1);margin-top:0}.btn-action-success{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.btn-action-success:hover{background-color:rgba(34,197,94,.2)}.btn-action-danger{display:inline-flex;min-height:3rem;flex-shrink:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-wrap:wrap;align-items:center;justify-content:center;border-radius:var(--rounded-btn,.5rem);border-color:oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;text-align:center;font-size:.875rem;line-height:1em;gap:.5rem;font-weight:600;text-decoration-line:none;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);border-width:var(--border-btn,1px);transition-property:color,background-color,border-color,opacity,box-shadow,transform;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);outline-color:var(--fallback-bc,oklch(var(--bc)/1));background-color:oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity));--tw-bg-opacity:1;--tw-border-opacity:1}.btn-action-danger:disabled,.btn-action-danger[disabled]{pointer-events:none}.btn-action-danger{height:3rem;width:3rem;padding:0}:where(.btn-action-danger:is(input[type=checkbox])),:where(.btn-action-danger:is(input[type=radio])){width:auto;-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn-action-danger:is(input[type=checkbox]):after,.btn-action-danger:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}@media (hover:hover){.btn-action-danger:hover{--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-action-danger:hover{background-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity,1)) 90%,#000);border-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity,1)) 90%,#000)}}@supports not (color:oklch(0% 0 0)){.btn-action-danger:hover{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-danger.glass:hover{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-danger:hover{border-color:transparent}@supports (color:oklch(0% 0 0)){.btn-action-danger:hover{background-color:var(--fallback-bc,oklch(var(--bc)/.2))}}.btn-action-danger:disabled:hover,.btn-action-danger[disabled]:hover{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}@supports (color:color-mix(in oklab,black,black)){.btn-action-danger:is(input[type=checkbox]:checked):hover,.btn-action-danger:is(input[type=radio]:checked):hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}}@media (prefers-reduced-motion:no-preference){.btn-action-danger{animation:button-pop var(--animation-btn,.25s) ease-out}}.btn-action-danger:active:focus,.btn-action-danger:active:hover{animation:button-pop 0s ease-out;transform:scale(var(--btn-focus-scale,.97))}@supports not (color:oklch(0% 0 0)){.btn-action-danger{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-danger:focus-visible{outline-style:solid;outline-width:2px;outline-offset:2px}.btn-action-danger.glass{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-danger.glass.btn-active{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-danger{border-width:1px;border-color:transparent;background-color:transparent;color:currentColor;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-danger.btn-active{border-color:transparent;background-color:var(--fallback-bc,oklch(var(--bc)/.2))}.btn-action-danger.btn-disabled,.btn-action-danger:disabled,.btn-action-danger[disabled]{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn-action-danger:is(input[type=checkbox]:checked),.btn-action-danger:is(input[type=radio]:checked){--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn-action-danger:is(input[type=checkbox]:checked):focus-visible,.btn-action-danger:is(input[type=radio]:checked):focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}.join>:where(:not(:first-child)):is(.btn-action-danger){margin-inline-start:calc(var(--border-btn)*-1)}.btn-action-danger{height:1.5rem;min-height:1.5rem;padding-left:.5rem;padding-right:.5rem;font-size:.75rem}.btn-action-danger:where(.btn-xs){height:1.5rem;width:1.5rem;padding:0}.btn-square:where(.btn-action-danger){height:1.5rem;width:1.5rem;padding:0}.btn-action-danger:where(.btn-sm){height:2rem;width:2rem;padding:0}.btn-action-danger:where(.btn-md){height:3rem;width:3rem;padding:0}.btn-action-danger:where(.btn-lg){height:4rem;width:4rem;padding:0}.btn-circle:where(.btn-action-danger){height:1.5rem;width:1.5rem;border-radius:9999px;padding:0}.join.join-vertical>:where(:not(:first-child)):is(.btn-action-danger){margin-top:calc(var(--border-btn)*-1)}.join.join-horizontal>:where(:not(:first-child)):is(.btn-action-danger){margin-inline-start:calc(var(--border-btn)*-1);margin-top:0}.btn-action-danger{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.btn-action-danger:hover{background-color:rgba(239,68,68,.2)}.btn-action-neutral{display:inline-flex;min-height:3rem;flex-shrink:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-wrap:wrap;align-items:center;justify-content:center;border-radius:var(--rounded-btn,.5rem);border-color:oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;text-align:center;font-size:.875rem;line-height:1em;gap:.5rem;font-weight:600;text-decoration-line:none;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);border-width:var(--border-btn,1px);transition-property:color,background-color,border-color,opacity,box-shadow,transform;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);outline-color:var(--fallback-bc,oklch(var(--bc)/1));background-color:oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity));--tw-bg-opacity:1;--tw-border-opacity:1}.btn-action-neutral:disabled,.btn-action-neutral[disabled]{pointer-events:none}.btn-action-neutral{height:3rem;width:3rem;padding:0}:where(.btn-action-neutral:is(input[type=checkbox])),:where(.btn-action-neutral:is(input[type=radio])){width:auto;-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn-action-neutral:is(input[type=checkbox]):after,.btn-action-neutral:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}@media (hover:hover){.btn-action-neutral:hover{--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-action-neutral:hover{background-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity,1)) 90%,#000);border-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity,1)) 90%,#000)}}@supports not (color:oklch(0% 0 0)){.btn-action-neutral:hover{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-neutral.glass:hover{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-neutral:hover{border-color:transparent}@supports (color:oklch(0% 0 0)){.btn-action-neutral:hover{background-color:var(--fallback-bc,oklch(var(--bc)/.2))}}.btn-action-neutral:disabled:hover,.btn-action-neutral[disabled]:hover{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}@supports (color:color-mix(in oklab,black,black)){.btn-action-neutral:is(input[type=checkbox]:checked):hover,.btn-action-neutral:is(input[type=radio]:checked):hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}}@media (prefers-reduced-motion:no-preference){.btn-action-neutral{animation:button-pop var(--animation-btn,.25s) ease-out}}.btn-action-neutral:active:focus,.btn-action-neutral:active:hover{animation:button-pop 0s ease-out;transform:scale(var(--btn-focus-scale,.97))}@supports not (color:oklch(0% 0 0)){.btn-action-neutral{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn-action-neutral:focus-visible{outline-style:solid;outline-width:2px;outline-offset:2px}.btn-action-neutral.glass{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-neutral.glass.btn-active{--glass-opacity:25%;--glass-border-opacity:15%}.btn-action-neutral{border-width:1px;border-color:transparent;background-color:transparent;color:currentColor;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-action-neutral.btn-active{border-color:transparent;background-color:var(--fallback-bc,oklch(var(--bc)/.2))}.btn-action-neutral.btn-disabled,.btn-action-neutral:disabled,.btn-action-neutral[disabled]{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn-action-neutral:is(input[type=checkbox]:checked),.btn-action-neutral:is(input[type=radio]:checked){--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn-action-neutral:is(input[type=checkbox]:checked):focus-visible,.btn-action-neutral:is(input[type=radio]:checked):focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}.join>:where(:not(:first-child)):is(.btn-action-neutral){margin-inline-start:calc(var(--border-btn)*-1)}.btn-action-neutral{height:1.5rem;min-height:1.5rem;padding-left:.5rem;padding-right:.5rem;font-size:.75rem}.btn-action-neutral:where(.btn-xs){height:1.5rem;width:1.5rem;padding:0}.btn-square:where(.btn-action-neutral){height:1.5rem;width:1.5rem;padding:0}.btn-action-neutral:where(.btn-sm){height:2rem;width:2rem;padding:0}.btn-action-neutral:where(.btn-md){height:3rem;width:3rem;padding:0}.btn-action-neutral:where(.btn-lg){height:4rem;width:4rem;padding:0}.btn-circle:where(.btn-action-neutral){height:1.5rem;width:1.5rem;border-radius:9999px;padding:0}.join.join-vertical>:where(:not(:first-child)):is(.btn-action-neutral){margin-top:calc(var(--border-btn)*-1)}.join.join-horizontal>:where(:not(:first-child)):is(.btn-action-neutral){margin-inline-start:calc(var(--border-btn)*-1);margin-top:0}.btn-action-neutral{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.btn-action-neutral:hover{background-color:hsla(220,9%,46%,.2)}.status-pill{border-radius:.25rem;border-width:1px;padding:.25rem .5rem;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:10px;font-weight:700;text-transform:uppercase}.status-pill-purple{border-color:rgba(168,85,247,.3);background-color:rgba(168,85,247,.1);color:rgb(168 85 247/var(--tw-text-opacity,1));border-radius:.25rem;border-width:1px}.status-pill-purple,.status-pill-ultra{--tw-text-opacity:1;padding:.25rem .5rem;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:10px;font-weight:700;text-transform:uppercase}.status-pill-ultra{border-color:rgba(234,179,8,.3);background-color:rgba(234,179,8,.1);color:rgb(250 204 21/var(--tw-text-opacity,1));border-radius:.25rem;border-width:1px}.status-pill-pro{border-color:rgba(59,130,246,.3);background-color:rgba(59,130,246,.1);color:rgb(96 165 250/var(--tw-text-opacity,1));border-radius:.25rem;border-width:1px}.status-pill-free,.status-pill-pro{--tw-text-opacity:1;padding:.25rem .5rem;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:10px;font-weight:700;text-transform:uppercase}.status-pill-free{border-color:hsla(220,9%,46%,.3);background-color:hsla(220,9%,46%,.1);color:rgb(156 163 175/var(--tw-text-opacity,1));border-radius:.25rem;border-width:1px}.status-pill-success{border-color:rgba(34,197,94,.3);background-color:rgba(34,197,94,.1);color:rgb(34 197 94/var(--tw-text-opacity,1));border-radius:.25rem;border-width:1px}.status-pill-success,.status-pill-warning{--tw-text-opacity:1;padding:.25rem .5rem;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:10px;font-weight:700;text-transform:uppercase}.status-pill-warning{border-color:rgba(234,179,8,.3);background-color:rgba(234,179,8,.1);color:rgb(250 204 21/var(--tw-text-opacity,1));border-radius:.25rem;border-width:1px}.status-pill-error{border-color:rgba(239,68,68,.3);background-color:rgba(239,68,68,.1);--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1));border-radius:.25rem;border-width:1px;padding:.25rem .5rem;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:10px;font-weight:700;text-transform:uppercase}.input-search{width:100%;border-radius:.5rem;border-width:1px;border-color:rgba(39,39,42,.5);background-color:rgba(15,15,17,.5);padding:.5rem 1rem .5rem 2.5rem;--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.input-search::-moz-placeholder{color:rgba(75,85,99,.8)}.input-search::placeholder{color:rgba(75,85,99,.8)}.input-search{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.input-search:hover{--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));background-color:rgba(24,24,27,.8)}.input-search:focus{border-color:rgba(168,85,247,.5);--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1));outline:2px solid transparent;outline-offset:2px}.input-search-sm{height:2rem;font-size:.75rem;line-height:1rem;font-weight:400;width:100%;border-radius:.5rem;border-width:1px;border-color:rgba(39,39,42,.5);background-color:rgba(15,15,17,.5);padding:.5rem 1rem .5rem 2.5rem;--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.input-search-sm::-moz-placeholder{color:rgba(75,85,99,.8)}.input-search-sm::placeholder{color:rgba(75,85,99,.8)}.input-search-sm{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.input-search-sm:hover{--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));background-color:rgba(24,24,27,.8)}.input-search-sm:focus{border-color:rgba(168,85,247,.5);--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1));outline:2px solid transparent;outline-offset:2px}@keyframes skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}.skeleton{background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from:rgba(15,15,17,.6) var(--tw-gradient-from-position);--tw-gradient-to:rgba(15,15,17,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);--tw-gradient-to:rgba(24,24,27,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(24,24,27,.4) var(--tw-gradient-via-position),var(--tw-gradient-to);--tw-gradient-to:rgba(15,15,17,.6) var(--tw-gradient-to-position);background-size:200% 100%;animation:skeleton-pulse 1.5s ease-in-out infinite;border-radius:.375rem}.skeleton-text{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));will-change:background-position;animation:skeleton 1.8s ease-in-out infinite;background-image:linear-gradient(105deg,transparent 0,transparent 40%,var(--fallback-b1,oklch(var(--b1)/1)) 50%,transparent 60%,transparent 100%);background-size:200% auto;background-repeat:no-repeat;background-position-x:-50%}@media (prefers-reduced-motion){.skeleton-text{animation-duration:15s}}.skeleton-text{height:1rem;width:100%;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from:rgba(15,15,17,.6) var(--tw-gradient-from-position);--tw-gradient-to:rgba(15,15,17,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);--tw-gradient-to:rgba(24,24,27,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(24,24,27,.4) var(--tw-gradient-via-position),var(--tw-gradient-to);--tw-gradient-to:rgba(15,15,17,.6) var(--tw-gradient-to-position);background-size:200% 100%;animation:skeleton-pulse 1.5s ease-in-out infinite;border-radius:.375rem}.skeleton-text-sm{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));will-change:background-position;animation:skeleton 1.8s ease-in-out infinite;background-image:linear-gradient(105deg,transparent 0,transparent 40%,var(--fallback-b1,oklch(var(--b1)/1)) 50%,transparent 60%,transparent 100%);background-size:200% auto;background-repeat:no-repeat;background-position-x:-50%}@media (prefers-reduced-motion){.skeleton-text-sm{animation-duration:15s}}.skeleton-text-sm{height:.75rem;width:75%;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from:rgba(15,15,17,.6) var(--tw-gradient-from-position);--tw-gradient-to:rgba(15,15,17,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);--tw-gradient-to:rgba(24,24,27,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(24,24,27,.4) var(--tw-gradient-via-position),var(--tw-gradient-to);--tw-gradient-to:rgba(15,15,17,.6) var(--tw-gradient-to-position);background-size:200% 100%;animation:skeleton-pulse 1.5s ease-in-out infinite;border-radius:.375rem}.skeleton-title{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));will-change:background-position;animation:skeleton 1.8s ease-in-out infinite;background-image:linear-gradient(105deg,transparent 0,transparent 40%,var(--fallback-b1,oklch(var(--b1)/1)) 50%,transparent 60%,transparent 100%);background-size:200% auto;background-repeat:no-repeat;background-position-x:-50%}@media (prefers-reduced-motion){.skeleton-title{animation-duration:15s}}.skeleton-title{height:1.5rem;width:50%;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from:rgba(15,15,17,.6) var(--tw-gradient-from-position);--tw-gradient-to:rgba(15,15,17,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);--tw-gradient-to:rgba(24,24,27,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(24,24,27,.4) var(--tw-gradient-via-position),var(--tw-gradient-to);--tw-gradient-to:rgba(15,15,17,.6) var(--tw-gradient-to-position);background-size:200% 100%;animation:skeleton-pulse 1.5s ease-in-out infinite;border-radius:.375rem}.skeleton-circle{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));will-change:background-position;animation:skeleton 1.8s ease-in-out infinite;background-image:linear-gradient(105deg,transparent 0,transparent 40%,var(--fallback-b1,oklch(var(--b1)/1)) 50%,transparent 60%,transparent 100%);background-size:200% auto;background-repeat:no-repeat;background-position-x:-50%}@media (prefers-reduced-motion){.skeleton-circle{animation-duration:15s}}.skeleton-circle{border-radius:9999px;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from:rgba(15,15,17,.6) var(--tw-gradient-from-position);--tw-gradient-to:rgba(15,15,17,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);--tw-gradient-to:rgba(24,24,27,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(24,24,27,.4) var(--tw-gradient-via-position),var(--tw-gradient-to);--tw-gradient-to:rgba(15,15,17,.6) var(--tw-gradient-to-position);background-size:200% 100%;animation:skeleton-pulse 1.5s ease-in-out infinite;border-radius:.375rem}.skeleton-stat-card{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));will-change:background-position;animation:skeleton 1.8s ease-in-out infinite;background-image:linear-gradient(105deg,transparent 0,transparent 40%,var(--fallback-b1,oklch(var(--b1)/1)) 50%,transparent 60%,transparent 100%);background-size:200% auto;background-repeat:no-repeat;background-position-x:-50%}@media (prefers-reduced-motion){.skeleton-stat-card{animation-duration:15s}}.skeleton-stat-card{height:8rem;width:100%;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from:rgba(15,15,17,.6) var(--tw-gradient-from-position);--tw-gradient-to:rgba(15,15,17,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);--tw-gradient-to:rgba(24,24,27,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(24,24,27,.4) var(--tw-gradient-via-position),var(--tw-gradient-to);--tw-gradient-to:rgba(15,15,17,.6) var(--tw-gradient-to-position);background-size:200% 100%;animation:skeleton-pulse 1.5s ease-in-out infinite;border-radius:.375rem}.skeleton-chart{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));will-change:background-position;animation:skeleton 1.8s ease-in-out infinite;background-image:linear-gradient(105deg,transparent 0,transparent 40%,var(--fallback-b1,oklch(var(--b1)/1)) 50%,transparent 60%,transparent 100%);background-size:200% auto;background-repeat:no-repeat;background-position-x:-50%}@media (prefers-reduced-motion){.skeleton-chart{animation-duration:15s}}.skeleton-chart{height:16rem;width:100%;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from:rgba(15,15,17,.6) var(--tw-gradient-from-position);--tw-gradient-to:rgba(15,15,17,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);--tw-gradient-to:rgba(24,24,27,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(24,24,27,.4) var(--tw-gradient-via-position),var(--tw-gradient-to);--tw-gradient-to:rgba(15,15,17,.6) var(--tw-gradient-to-position);background-size:200% 100%;animation:skeleton-pulse 1.5s ease-in-out infinite;border-radius:.375rem}.skeleton-table-row{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));will-change:background-position;animation:skeleton 1.8s ease-in-out infinite;background-image:linear-gradient(105deg,transparent 0,transparent 40%,var(--fallback-b1,oklch(var(--b1)/1)) 50%,transparent 60%,transparent 100%);background-size:200% auto;background-repeat:no-repeat;background-position-x:-50%}@media (prefers-reduced-motion){.skeleton-table-row{animation-duration:15s}}.skeleton-table-row{margin-bottom:.5rem;height:3rem;width:100%;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from:rgba(15,15,17,.6) var(--tw-gradient-from-position);--tw-gradient-to:rgba(15,15,17,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);--tw-gradient-to:rgba(24,24,27,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(24,24,27,.4) var(--tw-gradient-via-position),var(--tw-gradient-to);--tw-gradient-to:rgba(15,15,17,.6) var(--tw-gradient-to-position);background-size:200% 100%;animation:skeleton-pulse 1.5s ease-in-out infinite;border-radius:.375rem}.selection\:bg-neon-purple ::-moz-selection{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.selection\:bg-neon-purple ::selection{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.selection\:text-white ::-moz-selection{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.selection\:text-white ::selection{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.selection\:bg-neon-purple::-moz-selection{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.selection\:bg-neon-purple::selection{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.selection\:text-white::-moz-selection{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.selection\:text-white::selection{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.placeholder\:\!text-gray-600::-moz-placeholder{--tw-text-opacity:1!important;color:rgb(75 85 99/var(--tw-text-opacity,1))!important}.placeholder\:\!text-gray-600::placeholder{--tw-text-opacity:1!important;color:rgb(75 85 99/var(--tw-text-opacity,1))!important}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:start-\[2px\]:after{content:var(--tw-content);inset-inline-start:2px}.after\:top-\[2px\]:after{content:var(--tw-content);top:2px}.after\:h-3\.5:after{content:var(--tw-content);height:.875rem}.after\:h-4:after{content:var(--tw-content);height:1rem}.after\:w-3\.5:after{content:var(--tw-content);width:.875rem}.after\:w-4:after{content:var(--tw-content);width:1rem}.after\:rounded-full:after{content:var(--tw-content);border-radius:9999px}.after\:bg-gray-600:after{content:var(--tw-content);--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.after\:transition-all:after{content:var(--tw-content);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.after\:content-\[\'\'\]:after{--tw-content:"";content:var(--tw-content)}.last\:border-0:last-child{border-width:0}.hover\:scale-125:hover{--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-cyan-500\/30:hover{border-color:rgba(6,182,212,.3)}.hover\:border-green-500\/30:hover{border-color:rgba(34,197,94,.3)}.hover\:border-neon-cyan\/50:hover{border-color:rgba(6,182,212,.5)}.hover\:border-neon-green\/50:hover{border-color:rgba(34,197,94,.5)}.hover\:border-neon-purple\/50:hover{border-color:rgba(168,85,247,.5)}.hover\:border-red-500\/30:hover{border-color:rgba(239,68,68,.3)}.hover\:border-space-border:hover{--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.hover\:border-space-border\/60:hover{border-color:rgba(39,39,42,.6)}.hover\:border-yellow-500\/50:hover{border-color:rgba(234,179,8,.5)}.hover\:bg-cyan-500\/5:hover{background-color:rgba(6,182,212,.05)}.hover\:bg-gray-600\/70:hover{background-color:rgba(75,85,99,.7)}.hover\:bg-green-500\/5:hover{background-color:rgba(34,197,94,.05)}.hover\:bg-neon-purple\/30:hover{background-color:rgba(168,85,247,.3)}.hover\:bg-neon-yellow:hover{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.hover\:bg-purple-600:hover{--tw-bg-opacity:1;background-color:rgb(147 51 234/var(--tw-bg-opacity,1))}.hover\:bg-red-500\/10:hover{background-color:rgba(239,68,68,.1)}.hover\:bg-red-500\/30:hover{background-color:rgba(239,68,68,.3)}.hover\:bg-red-500\/5:hover{background-color:rgba(239,68,68,.05)}.hover\:bg-red-600:hover{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.hover\:bg-space-800:hover{--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.hover\:bg-white\/10:hover{background-color:hsla(0,0%,100%,.1)}.hover\:bg-white\/5:hover{background-color:hsla(0,0%,100%,.05)}.hover\:bg-white\/\[0\.03\]:hover{background-color:hsla(0,0%,100%,.03)}.hover\:bg-yellow-500\/20:hover{background-color:rgba(234,179,8,.2)}.hover\:text-black:hover{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.hover\:text-gray-300:hover{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.hover\:text-neon-cyan:hover{--tw-text-opacity:1;color:rgb(6 182 212/var(--tw-text-opacity,1))}.hover\:text-neon-green:hover{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.hover\:text-neon-purple:hover{--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity,1))}.hover\:text-red-400:hover{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.focus\:\!border-neon-cyan:focus{--tw-border-opacity:1!important;border-color:rgb(6 182 212/var(--tw-border-opacity,1))!important}.focus\:\!border-neon-purple:focus{--tw-border-opacity:1!important;border-color:rgb(168 85 247/var(--tw-border-opacity,1))!important}.focus\:border-neon-cyan:focus{--tw-border-opacity:1;border-color:rgb(6 182 212/var(--tw-border-opacity,1))}.focus\:border-neon-purple:focus{--tw-border-opacity:1;border-color:rgb(168 85 247/var(--tw-border-opacity,1))}.focus\:\!bg-space-800:focus{--tw-bg-opacity:1!important;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))!important}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-neon-purple:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(168 85 247/var(--tw-ring-opacity,1))}.group[open] .group-open\:rotate-90{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:text-cyan-400\/70{color:rgba(34,211,238,.7)}.group:hover .group-hover\:text-green-400\/70{color:rgba(74,222,128,.7)}.group:hover .group-hover\:text-neon-purple{--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity,1))}.group:hover .group-hover\:text-red-500\/70{color:rgba(239,68,68,.7)}.group:hover .group-hover\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.group:hover .group-hover\:text-zinc-500{--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.group:hover .group-hover\:opacity-100,.group\/legend:hover .group-hover\/legend\:opacity-100{opacity:1}.peer:checked~.peer-checked\:bg-neon-green{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.peer:checked~.peer-checked\:bg-neon-purple{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.peer:checked~.peer-checked\:after\:translate-x-full:after{content:var(--tw-content);--tw-translate-x:100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.peer:checked~.peer-checked\:after\:border-white:after{content:var(--tw-content);--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity,1))}.peer:checked~.peer-checked\:after\:bg-white:after{content:var(--tw-content);--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.peer:focus~.peer-focus\:outline-none{outline:2px solid transparent;outline-offset:2px}@media (min-width:640px){.sm\:inline-block{display:inline-block}.sm\:w-auto{width:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}}@media (min-width:768px){.md\:flex{display:flex}.md\:w-64{width:16rem}.md\:w-auto{width:auto}.md\:flex-none{flex:none}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:flex-row{flex-direction:row}}@media (min-width:1024px){.lg\:col-start-4{grid-column-start:4}.lg\:row-start-1{grid-row-start:1}.lg\:block{display:block}.lg\:h-16{height:4rem}.lg\:w-16{width:4rem}.lg\:w-auto{width:auto}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}}@media (min-width:1280px){.xl\:block{display:block}}.peer:checked~.rtl\:peer-checked\:after\:-translate-x-full:where([dir=rtl],[dir=rtl] *):after{content:var(--tw-content);--tw-translate-x:-100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))} \ No newline at end of file diff --git a/public/index.html b/public/index.html index c948359..136c591 100644 --- a/public/index.html +++ b/public/index.html @@ -9,57 +9,10 @@ - - - - + @@ -354,6 +307,7 @@ + diff --git a/public/js/components/account-manager.js b/public/js/components/account-manager.js index 8324b9a..fe26751 100644 --- a/public/js/components/account-manager.js +++ b/public/js/components/account-manager.js @@ -7,6 +7,10 @@ window.Components = window.Components || {}; window.Components.accountManager = () => ({ searchQuery: '', deleteTarget: '', + refreshing: false, + toggling: false, + deleting: false, + reloading: false, get filteredAccounts() { const accounts = Alpine.store('data').accounts || []; @@ -36,11 +40,15 @@ window.Components.accountManager = () => ({ }, async refreshAccount(email) { - const store = Alpine.store('global'); - store.showToast(store.t('refreshingAccount', { email }), 'info'); - const password = store.webuiPassword; - try { - const { response, newPassword } = await window.utils.request(`/api/accounts/${encodeURIComponent(email)}/refresh`, { method: 'POST' }, password); + return await window.ErrorHandler.withLoading(async () => { + const store = Alpine.store('global'); + store.showToast(store.t('refreshingAccount', { email }), 'info'); + + const { response, newPassword } = await window.utils.request( + `/api/accounts/${encodeURIComponent(email)}/refresh`, + { method: 'POST' }, + store.webuiPassword + ); if (newPassword) store.webuiPassword = newPassword; const data = await response.json(); @@ -48,11 +56,9 @@ window.Components.accountManager = () => ({ store.showToast(store.t('refreshedAccount', { email }), 'success'); Alpine.store('data').fetchData(); } else { - store.showToast(data.error || store.t('refreshFailed'), 'error'); + throw new Error(data.error || store.t('refreshFailed')); } - } catch (e) { - store.showToast(store.t('refreshFailed') + ': ' + e.message, 'error'); - } + }, this, 'refreshing', { errorMessage: 'Failed to refresh account' }); }, async toggleAccount(email, enabled) { @@ -125,11 +131,14 @@ window.Components.accountManager = () => ({ async executeDelete() { const email = this.deleteTarget; - const store = Alpine.store('global'); - const password = store.webuiPassword; + return await window.ErrorHandler.withLoading(async () => { + const store = Alpine.store('global'); - try { - const { response, newPassword } = await window.utils.request(`/api/accounts/${encodeURIComponent(email)}`, { method: 'DELETE' }, password); + const { response, newPassword } = await window.utils.request( + `/api/accounts/${encodeURIComponent(email)}`, + { method: 'DELETE' }, + store.webuiPassword + ); if (newPassword) store.webuiPassword = newPassword; const data = await response.json(); @@ -139,18 +148,20 @@ window.Components.accountManager = () => ({ document.getElementById('delete_account_modal').close(); this.deleteTarget = ''; } else { - store.showToast(data.error || store.t('deleteFailed'), 'error'); + throw new Error(data.error || store.t('deleteFailed')); } - } catch (e) { - store.showToast(store.t('deleteFailed') + ': ' + e.message, 'error'); - } + }, this, 'deleting', { errorMessage: 'Failed to delete account' }); }, async reloadAccounts() { - const store = Alpine.store('global'); - const password = store.webuiPassword; - try { - const { response, newPassword } = await window.utils.request('/api/accounts/reload', { method: 'POST' }, password); + return await window.ErrorHandler.withLoading(async () => { + const store = Alpine.store('global'); + + const { response, newPassword } = await window.utils.request( + '/api/accounts/reload', + { method: 'POST' }, + store.webuiPassword + ); if (newPassword) store.webuiPassword = newPassword; const data = await response.json(); @@ -158,11 +169,9 @@ window.Components.accountManager = () => ({ store.showToast(store.t('accountsReloaded'), 'success'); Alpine.store('data').fetchData(); } else { - store.showToast(data.error || store.t('reloadFailed'), 'error'); + throw new Error(data.error || store.t('reloadFailed')); } - } catch (e) { - store.showToast(store.t('reloadFailed') + ': ' + e.message, 'error'); - } + }, this, 'reloading', { errorMessage: 'Failed to reload accounts' }); }, /** diff --git a/public/js/components/dashboard/charts.js b/public/js/components/dashboard/charts.js index 0767865..76c511a 100644 --- a/public/js/components/dashboard/charts.js +++ b/public/js/components/dashboard/charts.js @@ -1,6 +1,22 @@ /** * Dashboard Charts Module - * Handles Chart.js visualizations (quota distribution & usage trend) + * 职责:使用 Chart.js 渲染配额分布图和使用趋势图 + * + * 调用时机: + * - dashboard 组件 init() 时初始化图表 + * - 筛选器变化时更新图表数据 + * - $store.data 更新时刷新图表 + * + * 图表类型: + * 1. Quota Distribution(饼图):按模型家族或具体模型显示配额分布 + * 2. Usage Trend(折线图):显示历史使用趋势 + * + * 特殊处理: + * - 使用 _trendChartUpdateLock 防止并发更新导致的竞争条件 + * - 通过 debounce 优化频繁更新的性能 + * - 响应式处理:移动端自动调整图表大小和标签显示 + * + * @module DashboardCharts */ window.DashboardCharts = window.DashboardCharts || {}; @@ -158,7 +174,7 @@ window.DashboardCharts.updateCharts = function (component) { if (!healthByFamily[family]) { healthByFamily[family] = { total: 0, weighted: 0 }; } - + // Calculate average health from quotaInfo (each entry has { pct }) // Health = average of all account quotas for this model const quotaInfo = row.quotaInfo || []; @@ -172,8 +188,8 @@ window.DashboardCharts.updateCharts = function (component) { }); // Update overall health for dashboard display - component.stats.overallHealth = totalModelCount > 0 - ? Math.round(totalHealthSum / totalModelCount) + component.stats.overallHealth = totalModelCount > 0 + ? Math.round(totalHealthSum / totalModelCount) : 0; const familyColors = { @@ -355,13 +371,13 @@ window.DashboardCharts.updateTrendChart = function (component) { // Determine if data spans multiple days (for smart label formatting) const timestamps = sortedEntries.map(([iso]) => new Date(iso)); - const isMultiDay = timestamps.length > 1 && + const isMultiDay = timestamps.length > 1 && timestamps[0].toDateString() !== timestamps[timestamps.length - 1].toDateString(); // Helper to format X-axis labels based on time range and multi-day status const formatLabel = (date) => { const timeRange = component.timeRange || '24h'; - + if (timeRange === '7d') { // Week view: show MM/DD return date.toLocaleDateString([], { month: '2-digit', day: '2-digit' }); diff --git a/public/js/components/dashboard/filters.js b/public/js/components/dashboard/filters.js index a420518..44d09fc 100644 --- a/public/js/components/dashboard/filters.js +++ b/public/js/components/dashboard/filters.js @@ -1,6 +1,21 @@ /** * Dashboard Filters Module - * Handles model/family filter selection and persistence + * 职责:管理图表筛选器的状态和持久化 + * + * 功能: + * 1. 时间范围筛选(1h/6h/24h/7d/all) + * 2. 显示模式切换(按家族/按模型) + * 3. 模型/家族多选筛选 + * 4. 筛选器状态持久化到 localStorage + * + * 调用时机: + * - 组件初始化时加载用户偏好 + * - 筛选器变化时保存并触发图表更新 + * + * 持久化键: + * - localStorage['dashboard_chart_prefs'] + * + * @module DashboardFilters */ window.DashboardFilters = window.DashboardFilters || {}; diff --git a/public/js/components/dashboard/stats.js b/public/js/components/dashboard/stats.js index 53ad22a..68a6aaf 100644 --- a/public/js/components/dashboard/stats.js +++ b/public/js/components/dashboard/stats.js @@ -1,12 +1,37 @@ /** * Dashboard Stats Module - * Handles account statistics calculation + * 职责:根据 Alpine.store('data') 计算账号统计数据 + * + * 调用时机: + * - dashboard 组件 init() 时 + * - $store.data 更新时(通过 $watch 监听) + * + * 统计维度: + * - total: 启用账号总数(排除禁用账号) + * - active: 有可用配额的账号数 + * - limited: 配额受限或失效的账号数 + * - subscription: 按订阅级别分类(ultra/pro/free) + * + * @module DashboardStats */ window.DashboardStats = window.DashboardStats || {}; /** - * Update account statistics (active, limited, total) - * @param {object} component - Dashboard component instance + * 更新账号统计数据 + * + * 统计逻辑: + * 1. 仅统计启用的账号(enabled !== false) + * 2. 优先统计核心模型(Sonnet/Opus/Pro/Flash)的配额 + * 3. 配额 > 5% 视为 active,否则为 limited + * 4. 状态非 'ok' 的账号归为 limited + * + * @param {object} component - Dashboard 组件实例(Alpine.js 上下文) + * @param {object} component.stats - 统计数据对象(会被修改) + * @param {number} component.stats.total - 启用账号总数 + * @param {number} component.stats.active - 活跃账号数 + * @param {number} component.stats.limited - 受限账号数 + * @param {object} component.stats.subscription - 订阅级别分布 + * @returns {void} */ window.DashboardStats.updateStats = function(component) { const accounts = Alpine.store('data').accounts; diff --git a/public/js/data-store.js b/public/js/data-store.js index 4bcb24d..56b0baa 100644 --- a/public/js/data-store.js +++ b/public/js/data-store.js @@ -14,6 +14,7 @@ document.addEventListener('alpine:init', () => { quotaRows: [], // Filtered view usageHistory: {}, // Usage statistics history (from /account-limits?includeHistory=true) loading: false, + initialLoad: true, // Track first load for skeleton screen connectionStatus: 'connecting', lastUpdated: '-', @@ -36,7 +37,10 @@ document.addEventListener('alpine:init', () => { }, async fetchData() { - this.loading = true; + // Only show skeleton on initial load, not on refresh + if (this.initialLoad) { + this.loading = true; + } try { // Get password from global store const password = Alpine.store('global').webuiPassword; @@ -72,6 +76,7 @@ document.addEventListener('alpine:init', () => { store.showToast(store.t('connectionLost'), 'error'); } finally { this.loading = false; + this.initialLoad = false; // Mark initial load as complete } }, diff --git a/public/js/store.js b/public/js/store.js index 15ee217..aabba10 100644 --- a/public/js/store.js +++ b/public/js/store.js @@ -79,6 +79,7 @@ document.addEventListener('alpine:init', () => { linkedAccounts: "Linked Accounts", noSignal: "NO SIGNAL DETECTED", establishingUplink: "ESTABLISHING UPLINK...", + goToAccounts: "Go to Accounts", // Settings - Models modelsDesc: "Configure model visibility, pinning, and request routing.", modelsPageDesc: "Real-time quota and status for all available models.", @@ -326,6 +327,7 @@ document.addEventListener('alpine:init', () => { linkedAccounts: "已关联账号", noSignal: "无信号连接", establishingUplink: "正在建立上行链路...", + goToAccounts: "前往账号管理", // Settings - Models modelsDesc: "配置模型的可见性、置顶和请求路由。", modelsPageDesc: "所有可用模型的实时配额和状态。", diff --git a/public/js/utils/account-actions.js b/public/js/utils/account-actions.js new file mode 100644 index 0000000..d2757ff --- /dev/null +++ b/public/js/utils/account-actions.js @@ -0,0 +1,199 @@ +/** + * Account Actions Service + * 纯业务逻辑层 - 处理账号操作的 HTTP 请求、乐观更新和数据刷新 + * 不包含 UI 关注点(Toast、Loading、模态框由组件层处理) + */ +window.AccountActions = window.AccountActions || {}; + +/** + * 刷新账号 token 和配额信息 + * @param {string} email - 账号邮箱 + * @returns {Promise<{success: boolean, data?: object, error?: string}>} + */ +window.AccountActions.refreshAccount = async function(email) { + const store = Alpine.store('global'); + + try { + const { response, newPassword } = await window.utils.request( + `/api/accounts/${encodeURIComponent(email)}/refresh`, + { method: 'POST' }, + store.webuiPassword + ); + + if (newPassword) { + store.webuiPassword = newPassword; + } + + const data = await response.json(); + if (data.status !== 'ok') { + return { success: false, error: data.error || 'Refresh failed' }; + } + + // 触发数据刷新 + await Alpine.store('data').fetchData(); + + return { success: true, data }; + } catch (error) { + return { success: false, error: error.message }; + } +}; + +/** + * 切换账号启用/禁用状态(包含乐观更新和错误回滚) + * @param {string} email - 账号邮箱 + * @param {boolean} enabled - 目标状态(true=启用, false=禁用) + * @returns {Promise<{success: boolean, rolledBack?: boolean, data?: object, error?: string}>} + */ +window.AccountActions.toggleAccount = async function(email, enabled) { + const store = Alpine.store('global'); + const dataStore = Alpine.store('data'); + + // 乐观更新:立即修改 UI + const account = dataStore.accounts.find(a => a.email === email); + const previousState = account ? account.enabled : !enabled; + + if (account) { + account.enabled = enabled; + } + + try { + const { response, newPassword } = await window.utils.request( + `/api/accounts/${encodeURIComponent(email)}/toggle`, + { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ enabled }) + }, + store.webuiPassword + ); + + if (newPassword) { + store.webuiPassword = newPassword; + } + + const data = await response.json(); + if (data.status !== 'ok') { + throw new Error(data.error || 'Toggle failed'); + } + + // 确认服务器状态 + await dataStore.fetchData(); + return { success: true, data }; + + } catch (error) { + // 错误回滚:恢复原状态 + if (account) { + account.enabled = previousState; + } + await dataStore.fetchData(); + return { success: false, error: error.message, rolledBack: true }; + } +}; + +/** + * 删除账号 + * @param {string} email - 账号邮箱 + * @returns {Promise<{success: boolean, data?: object, error?: string}>} + */ +window.AccountActions.deleteAccount = async function(email) { + const store = Alpine.store('global'); + + try { + const { response, newPassword } = await window.utils.request( + `/api/accounts/${encodeURIComponent(email)}`, + { method: 'DELETE' }, + store.webuiPassword + ); + + if (newPassword) { + store.webuiPassword = newPassword; + } + + const data = await response.json(); + if (data.status !== 'ok') { + return { success: false, error: data.error || 'Delete failed' }; + } + + // 触发数据刷新 + await Alpine.store('data').fetchData(); + return { success: true, data }; + + } catch (error) { + return { success: false, error: error.message }; + } +}; + +/** + * 获取账号重新认证的 OAuth URL + * 注意:此方法仅返回 URL,不打开窗口(由组件层决定如何处理) + * @param {string} email - 账号邮箱 + * @returns {Promise<{success: boolean, url?: string, error?: string}>} + */ +window.AccountActions.getFixAccountUrl = async function(email) { + const store = Alpine.store('global'); + + try { + const urlPath = `/api/auth/url?email=${encodeURIComponent(email)}`; + const { response, newPassword } = await window.utils.request( + urlPath, + {}, + store.webuiPassword + ); + + if (newPassword) { + store.webuiPassword = newPassword; + } + + const data = await response.json(); + if (data.status !== 'ok') { + return { success: false, error: data.error || 'Failed to get auth URL' }; + } + + return { success: true, url: data.url }; + + } catch (error) { + return { success: false, error: error.message }; + } +}; + +/** + * 从磁盘重新加载所有账号配置 + * @returns {Promise<{success: boolean, data?: object, error?: string}>} + */ +window.AccountActions.reloadAccounts = async function() { + const store = Alpine.store('global'); + + try { + const { response, newPassword } = await window.utils.request( + '/api/accounts/reload', + { method: 'POST' }, + store.webuiPassword + ); + + if (newPassword) { + store.webuiPassword = newPassword; + } + + const data = await response.json(); + if (data.status !== 'ok') { + return { success: false, error: data.error || 'Reload failed' }; + } + + // 触发数据刷新 + await Alpine.store('data').fetchData(); + return { success: true, data }; + + } catch (error) { + return { success: false, error: error.message }; + } +}; + +/** + * 检查账号是否可以删除 + * 来自 Antigravity 数据库的账号(source='database')不可删除 + * @param {object} account - 账号对象 + * @returns {boolean} true 表示可删除 + */ +window.AccountActions.canDelete = function(account) { + return account && account.source !== 'database'; +}; diff --git a/public/js/utils/error-handler.js b/public/js/utils/error-handler.js index 8289485..0835357 100644 --- a/public/js/utils/error-handler.js +++ b/public/js/utils/error-handler.js @@ -105,3 +105,41 @@ window.ErrorHandler.apiCall = async function(apiCall, successMessage = null, err return result; }; + +/** + * Execute an async function with automatic loading state management + * @param {Function} asyncFn - Async function to execute + * @param {object} context - Component context (this) that contains the loading state + * @param {string} loadingKey - Name of the loading state property (default: 'loading') + * @param {object} options - Additional options (same as safeAsync) + * @returns {Promise} Result of the function or undefined on error + * + * @example + * // In your Alpine component: + * async refreshAccount(email) { + * return await window.ErrorHandler.withLoading(async () => { + * const response = await window.utils.request(`/api/accounts/${email}/refresh`, { method: 'POST' }); + * this.$store.global.showToast('Account refreshed', 'success'); + * return response; + * }, this, 'refreshing'); + * } + * + * // In HTML: + * // + */ +window.ErrorHandler.withLoading = async function(asyncFn, context, loadingKey = 'loading', options = {}) { + // Set loading state to true + context[loadingKey] = true; + + try { + // Execute the async function with error handling + const result = await window.ErrorHandler.safeAsync(asyncFn, options.errorMessage, options); + return result; + } finally { + // Always reset loading state, even if there was an error + context[loadingKey] = false; + } +}; diff --git a/public/views/accounts.html b/public/views/accounts.html index b34a451..f78347e 100644 --- a/public/views/accounts.html +++ b/public/views/accounts.html @@ -19,15 +19,20 @@ + @@ -245,8 +252,10 @@ Cancel + diff --git a/public/views/settings.html b/public/views/settings.html index ed3a2f0..78aa7b4 100644 --- a/public/views/settings.html +++ b/public/views/settings.html @@ -2,7 +2,7 @@ activeTab: 'ui' }" class="view-container"> -
+

@@ -558,7 +558,7 @@

-
+
@@ -609,7 +609,7 @@ placeholder="e.g. claude-sonnet-4-5 or gemini-3-flash" @keydown.enter="await updateModelConfig(modelId, { mapping: newMapping }); stopEditing()" @keydown.escape="newMapping = config.mapping || ''; stopEditing()"> - - + - + diff --git a/public/js/components/claude-config.js b/public/js/components/claude-config.js index 3d91702..8b4c645 100644 --- a/public/js/components/claude-config.js +++ b/public/js/components/claude-config.js @@ -6,6 +6,7 @@ window.Components = window.Components || {}; window.Components.claudeConfig = () => ({ config: { env: {} }, + configPath: '', // Dynamic path from backend models: [], loading: false, gemini1mSuffix: false, @@ -76,7 +77,7 @@ window.Components.claudeConfig = () => ({ */ selectModel(field, modelId) { if (!this.config.env) this.config.env = {}; - + let finalModelId = modelId; // If 1M mode is enabled and it's a Gemini model, append the suffix if (this.gemini1mSuffix && modelId.toLowerCase().includes('gemini')) { @@ -84,7 +85,7 @@ window.Components.claudeConfig = () => ({ finalModelId = finalModelId.trim() + ' [1m]'; } } - + this.config.env[field] = finalModelId; }, @@ -97,6 +98,7 @@ window.Components.claudeConfig = () => ({ if (!response.ok) throw new Error(`HTTP ${response.status}`); const data = await response.json(); this.config = data.config || {}; + this.configPath = data.path || '~/.claude/settings.json'; // Save dynamic path if (!this.config.env) this.config.env = {}; // Default MCP CLI to true if not set @@ -106,10 +108,10 @@ window.Components.claudeConfig = () => ({ // Detect existing [1m] suffix state, default to true const hasExistingSuffix = this.detectGemini1mSuffix(); - const hasGeminiModels = this.geminiModelFields.some(f => + const hasGeminiModels = this.geminiModelFields.some(f => this.config.env[f]?.toLowerCase().includes('gemini') ); - + // Default to enabled: if no suffix found but Gemini models exist, apply suffix if (!hasExistingSuffix && hasGeminiModels) { this.toggleGemini1mSuffix(true); diff --git a/public/js/components/dashboard/charts.js b/public/js/components/dashboard/charts.js index 76c511a..b14ca3e 100644 --- a/public/js/components/dashboard/charts.js +++ b/public/js/components/dashboard/charts.js @@ -149,7 +149,7 @@ window.DashboardCharts.updateCharts = function (component) { // Safety checks if (!canvas) { - console.warn("quotaChart canvas not found"); + console.debug("quotaChart canvas not found"); return; } if (typeof Chart === "undefined") { @@ -157,7 +157,7 @@ window.DashboardCharts.updateCharts = function (component) { return; } if (!isCanvasReady(canvas)) { - console.warn("quotaChart canvas not ready, skipping update"); + console.debug("quotaChart canvas not ready, skipping update"); return; } diff --git a/public/js/data-store.js b/public/js/data-store.js index 56b0baa..4b5262c 100644 --- a/public/js/data-store.js +++ b/public/js/data-store.js @@ -69,6 +69,11 @@ document.addEventListener('alpine:init', () => { this.connectionStatus = 'connected'; this.lastUpdated = new Date().toLocaleTimeString(); + + // Fetch version from config endpoint if not already loaded + if (this.initialLoad) { + this.fetchVersion(password); + } } catch (error) { console.error('Fetch error:', error); this.connectionStatus = 'disconnected'; @@ -80,6 +85,20 @@ document.addEventListener('alpine:init', () => { } }, + async fetchVersion(password) { + try { + const { response } = await window.utils.request('/api/config', {}, password); + if (response.ok) { + const data = await response.json(); + if (data.version) { + Alpine.store('global').version = data.version; + } + } + } catch (error) { + console.warn('Failed to fetch version:', error); + } + }, + computeQuotaRows() { const models = this.models || []; const rows = []; diff --git a/public/js/store.js b/public/js/store.js index aabba10..e8727ce 100644 --- a/public/js/store.js +++ b/public/js/store.js @@ -98,7 +98,8 @@ document.addEventListener('alpine:init', () => { opusAlias: "Opus Alias", sonnetAlias: "Sonnet Alias", haikuAlias: "Haiku Alias", - claudeSettingsAlert: "Settings below directly modify ~/.claude/settings.json. Restart Claude CLI to apply.", + claudeSettingsAlertPrefix: "Settings below directly modify", + claudeSettingsAlertSuffix: "Restart Claude CLI to apply.", applyToClaude: "Apply to Claude CLI", // Settings - Server port: "Port", @@ -118,7 +119,7 @@ document.addEventListener('alpine:init', () => { sonnetModel: "Sonnet Model", haikuModel: "Haiku Model", authToken: "Auth Token", - saveConfig: "Save to ~/.claude/settings.json", + saveConfig: "Save to Claude CLI settings", envVar: "Env", // New Keys systemName: "ANTIGRAVITY", @@ -346,7 +347,8 @@ document.addEventListener('alpine:init', () => { opusAlias: "Opus 别名", sonnetAlias: "Sonnet 别名", haikuAlias: "Haiku 别名", - claudeSettingsAlert: "以下设置直接修改 ~/.claude/settings.json。重启 Claude CLI 生效。", + claudeSettingsAlertPrefix: "以下设置直接修改", + claudeSettingsAlertSuffix: "重启 Claude CLI 生效。", applyToClaude: "应用到 Claude CLI", // Settings - Server port: "端口", @@ -366,7 +368,7 @@ document.addEventListener('alpine:init', () => { sonnetModel: "Sonnet 模型", haikuModel: "Haiku 模型", authToken: "认证令牌", - saveConfig: "保存到 ~/.claude/settings.json", + saveConfig: "保存到 Claude CLI 设置", envVar: "环境变量", // New Keys systemName: "ANTIGRAVITY", diff --git a/public/views/settings.html b/public/views/settings.html index 78aa7b4..72d114f 100644 --- a/public/views/settings.html +++ b/public/views/settings.html @@ -53,7 +53,7 @@ + d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01" /> Server @@ -197,9 +197,11 @@ - Settings below directly - modify ~/.claude/settings.json. Restart Claude CLI - to apply. + + Settings below directly modify + ~/.claude/settings.json. + Restart Claude CLI to apply. + diff --git a/src/webui/index.js b/src/webui/index.js index 80e1099..9594621 100644 --- a/src/webui/index.js +++ b/src/webui/index.js @@ -13,6 +13,8 @@ */ import path from 'path'; +import { readFileSync } from 'fs'; +import { fileURLToPath } from 'url'; import express from 'express'; import { getPublicConfig, saveConfig, config } from '../config.js'; import { DEFAULT_PORT, ACCOUNT_CONFIG_PATH } from '../constants.js'; @@ -21,6 +23,18 @@ import { logger } from '../utils/logger.js'; import { getAuthorizationUrl, completeOAuthFlow, startCallbackServer } from '../auth/oauth.js'; import { loadAccounts, saveAccounts } from '../account-manager/storage.js'; +// Get package version +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +let packageVersion = '1.0.0'; +try { + const packageJsonPath = path.join(__dirname, '../../package.json'); + const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')); + packageVersion = packageJson.version; +} catch (error) { + logger.warn('[WebUI] Could not read package.json version, using default'); +} + // OAuth state storage (state -> { server, verifier, state, timestamp }) // Maps state ID to active OAuth flow data const pendingOAuthFlows = new Map(); @@ -254,6 +268,7 @@ export function mountWebUI(app, dirname, accountManager) { res.json({ status: 'ok', config: publicConfig, + version: packageVersion, note: 'Edit ~/.config/antigravity-proxy/config.json or use env vars to change these values' }); } catch (error) { diff --git a/tailwind.config.js b/tailwind.config.js index 14c7fc2..b0a6069 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,9 +1,7 @@ /** @type {import('tailwindcss').Config} */ export default { content: [ - "./public/**/*.{html,js}", - "./public/views/**/*.html", - "./public/js/**/*.js" + "./public/**/*.{html,js}" // Simplified: already covers all subdirectories ], darkMode: 'class', theme: { @@ -37,16 +35,17 @@ export default { daisyui: { themes: [{ antigravity: { - "primary": "var(--color-neon-purple)", - "secondary": "var(--color-neon-green)", - "accent": "var(--color-neon-cyan)", - "neutral": "var(--color-space-800)", - "base-100": "var(--color-space-950)", - "info": "var(--color-neon-cyan)", - "success": "var(--color-neon-green)", - "warning": "var(--color-neon-yellow)", - "error": "var(--color-neon-red)", + "primary": "#a855f7", // neon-purple + "secondary": "#22c55e", // neon-green + "accent": "#06b6d4", // neon-cyan + "neutral": "#18181b", // space-800 + "base-100": "#09090b", // space-950 + "info": "#06b6d4", // neon-cyan + "success": "#22c55e", // neon-green + "warning": "#eab308", // neon-yellow + "error": "#ef4444", // neon-red } - }] + }], + logs: false // Disable console logs in production } }