diff --git a/.cursor/rules/README.mdc b/.cursor/rules/README.mdc new file mode 100644 index 000000000..3eb1c56fb --- /dev/null +++ b/.cursor/rules/README.mdc @@ -0,0 +1,292 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify Cursor Rules - Complete Guide + +## Overview + +This comprehensive set of Cursor Rules provides deep insights into **Coolify**, an open-source self-hostable alternative to Heroku/Netlify/Vercel. These rules will help you understand, navigate, and contribute to this complex Laravel-based deployment platform. + +## Rule Categories + +### ๐Ÿ—๏ธ Architecture & Foundation +- **[project-overview.mdc](mdc:.cursor/rules/project-overview.mdc)** - What Coolify is and its core mission +- **[technology-stack.mdc](mdc:.cursor/rules/technology-stack.mdc)** - Complete technology stack and dependencies +- **[application-architecture.mdc](mdc:.cursor/rules/application-architecture.mdc)** - Laravel application structure and patterns + +### ๐ŸŽจ Frontend Development +- **[frontend-patterns.mdc](mdc:.cursor/rules/frontend-patterns.mdc)** - Livewire + Alpine.js + Tailwind architecture + +### ๐Ÿ—„๏ธ Data & Backend +- **[database-patterns.mdc](mdc:.cursor/rules/database-patterns.mdc)** - Database architecture, models, and data management +- **[deployment-architecture.mdc](mdc:.cursor/rules/deployment-architecture.mdc)** - Docker orchestration and deployment workflows + +### ๐ŸŒ API & Communication +- **[api-and-routing.mdc](mdc:.cursor/rules/api-and-routing.mdc)** - RESTful APIs, webhooks, and routing patterns + +### ๐Ÿงช Quality Assurance +- **[testing-patterns.mdc](mdc:.cursor/rules/testing-patterns.mdc)** - Testing strategies with Pest PHP and Laravel Dusk + +### ๐Ÿ”ง Development Process +- **[development-workflow.mdc](mdc:.cursor/rules/development-workflow.mdc)** - Development setup, coding standards, and contribution guidelines + +### ๐Ÿ”’ Security +- **[security-patterns.mdc](mdc:.cursor/rules/security-patterns.mdc)** - Security architecture, authentication, and best practices + +## Quick Navigation + +### Core Application Files +- **[app/Models/Application.php](mdc:app/Models/Application.php)** - Main application entity (74KB, highly complex) +- **[app/Models/Server.php](mdc:app/Models/Server.php)** - Server management (46KB, complex) +- **[app/Models/Service.php](mdc:app/Models/Service.php)** - Service definitions (58KB, complex) +- **[app/Models/Team.php](mdc:app/Models/Team.php)** - Multi-tenant structure (8.9KB) + +### Configuration Files +- **[composer.json](mdc:composer.json)** - PHP dependencies and Laravel setup +- **[package.json](mdc:package.json)** - Frontend dependencies and build scripts +- **[vite.config.js](mdc:vite.config.js)** - Frontend build configuration +- **[docker-compose.dev.yml](mdc:docker-compose.dev.yml)** - Development environment + +### API Documentation +- **[openapi.json](mdc:openapi.json)** - Complete API documentation (373KB) +- **[routes/api.php](mdc:routes/api.php)** - API endpoint definitions (13KB) +- **[routes/web.php](mdc:routes/web.php)** - Web application routes (21KB) + +## Key Concepts to Understand + +### 1. Multi-Tenant Architecture +Coolify uses a **team-based multi-tenancy** model where: +- Users belong to multiple teams +- Resources are scoped to teams +- Access control is team-based +- Data isolation is enforced at the database level + +### 2. Deployment Philosophy +- **Docker-first** approach for all deployments +- **Zero-downtime** deployments with health checks +- **Git-based** workflows with webhook integration +- **Multi-server** support with SSH connections + +### 3. Technology Stack +- **Backend**: Laravel 11 + PHP 8.4 +- **Frontend**: Livewire 3.5 + Alpine.js + Tailwind CSS 4.1 +- **Database**: PostgreSQL 15 + Redis 7 +- **Containerization**: Docker + Docker Compose +- **Testing**: Pest PHP 3.8 + Laravel Dusk + +### 4. Security Model +- **Defense-in-depth** security architecture +- **OAuth integration** with multiple providers +- **API token** authentication with Sanctum +- **Encrypted storage** for sensitive data +- **SSH key** management for server access + +## Development Quick Start + +### Local Setup +```bash +# Clone and setup +git clone https://github.com/coollabsio/coolify.git +cd coolify +cp .env.example .env + +# Docker development (recommended) +docker-compose -f docker-compose.dev.yml up -d +docker-compose exec app composer install +docker-compose exec app npm install +docker-compose exec app php artisan migrate +``` + +### Code Quality +```bash +# PHP code style +./vendor/bin/pint + +# Static analysis +./vendor/bin/phpstan analyse + +# Run tests +./vendor/bin/pest +``` + +## Common Patterns + +### Livewire Components +```php +class ApplicationShow extends Component +{ + public Application $application; + + protected $listeners = [ + 'deployment.started' => 'refresh', + 'deployment.completed' => 'refresh', + ]; + + public function deploy(): void + { + $this->authorize('deploy', $this->application); + app(ApplicationDeploymentService::class)->deploy($this->application); + } +} +``` + +### API Controllers +```php +class ApplicationController extends Controller +{ + public function __construct() + { + $this->middleware('auth:sanctum'); + $this->middleware('team.access'); + } + + public function deploy(Application $application): JsonResponse + { + $this->authorize('deploy', $application); + $deployment = app(ApplicationDeploymentService::class)->deploy($application); + return response()->json(['deployment_id' => $deployment->id]); + } +} +``` + +### Queue Jobs +```php +class DeployApplicationJob implements ShouldQueue +{ + public function handle(DockerService $dockerService): void + { + $this->deployment->update(['status' => 'running']); + + try { + $dockerService->deployContainer($this->deployment->application); + $this->deployment->update(['status' => 'success']); + } catch (Exception $e) { + $this->deployment->update(['status' => 'failed']); + throw $e; + } + } +} +``` + +## Testing Patterns + +### Feature Tests +```php +test('user can deploy application via API', function () { + $user = User::factory()->create(); + $application = Application::factory()->create(['team_id' => $user->currentTeam->id]); + + $response = $this->actingAs($user) + ->postJson("/api/v1/applications/{$application->id}/deploy"); + + $response->assertStatus(200); + expect($application->deployments()->count())->toBe(1); +}); +``` + +### Browser Tests +```php +test('user can create application through UI', function () { + $user = User::factory()->create(); + + $this->browse(function (Browser $browser) use ($user) { + $browser->loginAs($user) + ->visit('/applications/create') + ->type('name', 'Test App') + ->press('Create Application') + ->assertSee('Application created successfully'); + }); +}); +``` + +## Security Considerations + +### Authentication +- Multi-provider OAuth support +- API token authentication +- Team-based access control +- Session management + +### Data Protection +- Encrypted environment variables +- Secure SSH key storage +- Input validation and sanitization +- SQL injection prevention + +### Container Security +- Non-root container users +- Minimal capabilities +- Read-only filesystems +- Network isolation + +## Performance Optimization + +### Database +- Eager loading relationships +- Query optimization +- Connection pooling +- Caching strategies + +### Frontend +- Lazy loading components +- Asset optimization +- CDN integration +- Real-time updates via WebSockets + +## Contributing Guidelines + +### Code Standards +- PSR-12 PHP coding standards +- Laravel best practices +- Comprehensive test coverage +- Security-first approach + +### Pull Request Process +1. Fork repository +2. Create feature branch +3. Implement with tests +4. Run quality checks +5. Submit PR with clear description + +## Useful Commands + +### Development +```bash +# Start development environment +docker-compose -f docker-compose.dev.yml up -d + +# Run tests +./vendor/bin/pest + +# Code formatting +./vendor/bin/pint + +# Frontend development +npm run dev +``` + +### Production +```bash +# Install Coolify +curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash + +# Update Coolify +./scripts/upgrade.sh +``` + +## Resources + +### Documentation +- **[README.md](mdc:README.md)** - Project overview and installation +- **[CONTRIBUTING.md](mdc:CONTRIBUTING.md)** - Contribution guidelines +- **[CHANGELOG.md](mdc:CHANGELOG.md)** - Release history +- **[TECH_STACK.md](mdc:TECH_STACK.md)** - Technology overview + +### Configuration +- **[config/](mdc:config)** - Laravel configuration files +- **[database/migrations/](mdc:database/migrations)** - Database schema +- **[tests/](mdc:tests)** - Test suite + +This comprehensive rule set provides everything needed to understand, develop, and contribute to the Coolify project effectively. Each rule focuses on specific aspects while maintaining connections to the broader architecture. diff --git a/.cursor/rules/api-and-routing.mdc b/.cursor/rules/api-and-routing.mdc new file mode 100644 index 000000000..21daf22d2 --- /dev/null +++ b/.cursor/rules/api-and-routing.mdc @@ -0,0 +1,474 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify API & Routing Architecture + +## Routing Structure + +Coolify implements **multi-layered routing** with web interfaces, RESTful APIs, webhook endpoints, and real-time communication channels. + +## Route Files + +### Core Route Definitions +- **[routes/web.php](mdc:routes/web.php)** - Web application routes (21KB, 362 lines) +- **[routes/api.php](mdc:routes/api.php)** - RESTful API endpoints (13KB, 185 lines) +- **[routes/webhooks.php](mdc:routes/webhooks.php)** - Webhook receivers (815B, 22 lines) +- **[routes/channels.php](mdc:routes/channels.php)** - WebSocket channel definitions (829B, 33 lines) +- **[routes/console.php](mdc:routes/console.php)** - Artisan command routes (592B, 20 lines) + +## Web Application Routing + +### Authentication Routes +```php +// Laravel Fortify authentication +Route::middleware('guest')->group(function () { + Route::get('/login', [AuthController::class, 'login']); + Route::get('/register', [AuthController::class, 'register']); + Route::get('/forgot-password', [AuthController::class, 'forgotPassword']); +}); +``` + +### Dashboard & Core Features +```php +// Main application routes +Route::middleware(['auth', 'verified'])->group(function () { + Route::get('/dashboard', Dashboard::class)->name('dashboard'); + Route::get('/projects', ProjectIndex::class)->name('projects'); + Route::get('/servers', ServerIndex::class)->name('servers'); + Route::get('/teams', TeamIndex::class)->name('teams'); +}); +``` + +### Resource Management Routes +```php +// Server management +Route::prefix('servers')->group(function () { + Route::get('/{server}', ServerShow::class)->name('server.show'); + Route::get('/{server}/edit', ServerEdit::class)->name('server.edit'); + Route::get('/{server}/logs', ServerLogs::class)->name('server.logs'); +}); + +// Application management +Route::prefix('applications')->group(function () { + Route::get('/{application}', ApplicationShow::class)->name('application.show'); + Route::get('/{application}/deployments', ApplicationDeployments::class); + Route::get('/{application}/environment-variables', ApplicationEnvironmentVariables::class); + Route::get('/{application}/logs', ApplicationLogs::class); +}); +``` + +## RESTful API Architecture + +### API Versioning +```php +// API route structure +Route::prefix('v1')->group(function () { + // Application endpoints + Route::apiResource('applications', ApplicationController::class); + Route::apiResource('servers', ServerController::class); + Route::apiResource('teams', TeamController::class); +}); +``` + +### Authentication & Authorization +```php +// Sanctum API authentication +Route::middleware('auth:sanctum')->group(function () { + Route::get('/user', function (Request $request) { + return $request->user(); + }); + + // Team-scoped resources + Route::middleware('team.access')->group(function () { + Route::apiResource('applications', ApplicationController::class); + }); +}); +``` + +### Application Management API +```php +// Application CRUD operations +Route::prefix('applications')->group(function () { + Route::get('/', [ApplicationController::class, 'index']); + Route::post('/', [ApplicationController::class, 'store']); + Route::get('/{application}', [ApplicationController::class, 'show']); + Route::patch('/{application}', [ApplicationController::class, 'update']); + Route::delete('/{application}', [ApplicationController::class, 'destroy']); + + // Deployment operations + Route::post('/{application}/deploy', [ApplicationController::class, 'deploy']); + Route::post('/{application}/restart', [ApplicationController::class, 'restart']); + Route::post('/{application}/stop', [ApplicationController::class, 'stop']); + Route::get('/{application}/logs', [ApplicationController::class, 'logs']); +}); +``` + +### Server Management API +```php +// Server operations +Route::prefix('servers')->group(function () { + Route::get('/', [ServerController::class, 'index']); + Route::post('/', [ServerController::class, 'store']); + Route::get('/{server}', [ServerController::class, 'show']); + Route::patch('/{server}', [ServerController::class, 'update']); + Route::delete('/{server}', [ServerController::class, 'destroy']); + + // Server actions + Route::post('/{server}/validate', [ServerController::class, 'validate']); + Route::get('/{server}/usage', [ServerController::class, 'usage']); + Route::post('/{server}/cleanup', [ServerController::class, 'cleanup']); +}); +``` + +### Database Management API +```php +// Database operations +Route::prefix('databases')->group(function () { + Route::get('/', [DatabaseController::class, 'index']); + Route::post('/', [DatabaseController::class, 'store']); + Route::get('/{database}', [DatabaseController::class, 'show']); + Route::patch('/{database}', [DatabaseController::class, 'update']); + Route::delete('/{database}', [DatabaseController::class, 'destroy']); + + // Database actions + Route::post('/{database}/backup', [DatabaseController::class, 'backup']); + Route::post('/{database}/restore', [DatabaseController::class, 'restore']); + Route::get('/{database}/logs', [DatabaseController::class, 'logs']); +}); +``` + +## Webhook Architecture + +### Git Integration Webhooks +```php +// GitHub webhook endpoints +Route::post('/webhooks/github/{application}', [GitHubWebhookController::class, 'handle']) + ->name('webhooks.github'); + +// GitLab webhook endpoints +Route::post('/webhooks/gitlab/{application}', [GitLabWebhookController::class, 'handle']) + ->name('webhooks.gitlab'); + +// Generic Git webhooks +Route::post('/webhooks/git/{application}', [GitWebhookController::class, 'handle']) + ->name('webhooks.git'); +``` + +### Deployment Webhooks +```php +// Deployment status webhooks +Route::post('/webhooks/deployment/{deployment}/success', [DeploymentWebhookController::class, 'success']); +Route::post('/webhooks/deployment/{deployment}/failure', [DeploymentWebhookController::class, 'failure']); +Route::post('/webhooks/deployment/{deployment}/progress', [DeploymentWebhookController::class, 'progress']); +``` + +### Third-Party Integration Webhooks +```php +// Monitoring webhooks +Route::post('/webhooks/monitoring/{server}', [MonitoringWebhookController::class, 'handle']); + +// Backup status webhooks +Route::post('/webhooks/backup/{backup}', [BackupWebhookController::class, 'handle']); + +// SSL certificate webhooks +Route::post('/webhooks/ssl/{certificate}', [SslWebhookController::class, 'handle']); +``` + +## WebSocket Channel Definitions + +### Real-Time Channels +```php +// Private channels for team members +Broadcast::channel('team.{teamId}', function ($user, $teamId) { + return $user->teams->contains('id', $teamId); +}); + +// Application deployment channels +Broadcast::channel('application.{applicationId}', function ($user, $applicationId) { + return $user->hasAccessToApplication($applicationId); +}); + +// Server monitoring channels +Broadcast::channel('server.{serverId}', function ($user, $serverId) { + return $user->hasAccessToServer($serverId); +}); +``` + +### Presence Channels +```php +// Team collaboration presence +Broadcast::channel('team.{teamId}.presence', function ($user, $teamId) { + if ($user->teams->contains('id', $teamId)) { + return ['id' => $user->id, 'name' => $user->name]; + } +}); +``` + +## API Controllers + +### Location: [app/Http/Controllers/Api/](mdc:app/Http/Controllers) + +#### Resource Controllers +```php +class ApplicationController extends Controller +{ + public function index(Request $request) + { + return ApplicationResource::collection( + $request->user()->currentTeam->applications() + ->with(['server', 'environment']) + ->paginate() + ); + } + + public function store(StoreApplicationRequest $request) + { + $application = $request->user()->currentTeam + ->applications() + ->create($request->validated()); + + return new ApplicationResource($application); + } + + public function deploy(Application $application) + { + $deployment = $application->deploy(); + + return response()->json([ + 'message' => 'Deployment started', + 'deployment_id' => $deployment->id + ]); + } +} +``` + +### API Responses & Resources +```php +// API Resource classes +class ApplicationResource extends JsonResource +{ + public function toArray($request) + { + return [ + 'id' => $this->id, + 'name' => $this->name, + 'fqdn' => $this->fqdn, + 'status' => $this->status, + 'git_repository' => $this->git_repository, + 'git_branch' => $this->git_branch, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + 'server' => new ServerResource($this->whenLoaded('server')), + 'environment' => new EnvironmentResource($this->whenLoaded('environment')), + ]; + } +} +``` + +## API Authentication + +### Sanctum Token Authentication +```php +// API token generation +Route::post('/auth/tokens', function (Request $request) { + $request->validate([ + 'name' => 'required|string', + 'abilities' => 'array' + ]); + + $token = $request->user()->createToken( + $request->name, + $request->abilities ?? [] + ); + + return response()->json([ + 'token' => $token->plainTextToken, + 'abilities' => $token->accessToken->abilities + ]); +}); +``` + +### Team-Based Authorization +```php +// Team access middleware +class EnsureTeamAccess +{ + public function handle($request, Closure $next) + { + $teamId = $request->route('team'); + + if (!$request->user()->teams->contains('id', $teamId)) { + abort(403, 'Access denied to team resources'); + } + + return $next($request); + } +} +``` + +## Rate Limiting + +### API Rate Limits +```php +// API throttling configuration +RateLimiter::for('api', function (Request $request) { + return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); +}); + +// Deployment rate limiting +RateLimiter::for('deployments', function (Request $request) { + return Limit::perMinute(10)->by($request->user()->id); +}); +``` + +### Webhook Rate Limiting +```php +// Webhook throttling +RateLimiter::for('webhooks', function (Request $request) { + return Limit::perMinute(100)->by($request->ip()); +}); +``` + +## Route Model Binding + +### Custom Route Bindings +```php +// Custom model binding for applications +Route::bind('application', function ($value) { + return Application::where('uuid', $value) + ->orWhere('id', $value) + ->firstOrFail(); +}); + +// Team-scoped model binding +Route::bind('team_application', function ($value, $route) { + $teamId = $route->parameter('team'); + return Application::whereHas('environment.project', function ($query) use ($teamId) { + $query->where('team_id', $teamId); + })->findOrFail($value); +}); +``` + +## API Documentation + +### OpenAPI Specification +- **[openapi.json](mdc:openapi.json)** - API documentation (373KB, 8316 lines) +- **[openapi.yaml](mdc:openapi.yaml)** - YAML format documentation (184KB, 5579 lines) + +### Documentation Generation +```php +// Swagger/OpenAPI annotations +/** + * @OA\Get( + * path="/api/v1/applications", + * summary="List applications", + * tags={"Applications"}, + * security={{"bearerAuth":{}}}, + * @OA\Response( + * response=200, + * description="List of applications", + * @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Application")) + * ) + * ) + */ +``` + +## Error Handling + +### API Error Responses +```php +// Standardized error response format +class ApiExceptionHandler +{ + public function render($request, Throwable $exception) + { + if ($request->expectsJson()) { + return response()->json([ + 'message' => $exception->getMessage(), + 'error_code' => $this->getErrorCode($exception), + 'timestamp' => now()->toISOString() + ], $this->getStatusCode($exception)); + } + + return parent::render($request, $exception); + } +} +``` + +### Validation Error Handling +```php +// Form request validation +class StoreApplicationRequest extends FormRequest +{ + public function rules() + { + return [ + 'name' => 'required|string|max:255', + 'git_repository' => 'required|url', + 'git_branch' => 'required|string', + 'server_id' => 'required|exists:servers,id', + 'environment_id' => 'required|exists:environments,id' + ]; + } + + public function failedValidation(Validator $validator) + { + throw new HttpResponseException( + response()->json([ + 'message' => 'Validation failed', + 'errors' => $validator->errors() + ], 422) + ); + } +} +``` + +## Real-Time API Integration + +### WebSocket Events +```php +// Broadcasting deployment events +class DeploymentStarted implements ShouldBroadcast +{ + public $application; + public $deployment; + + public function broadcastOn() + { + return [ + new PrivateChannel("application.{$this->application->id}"), + new PrivateChannel("team.{$this->application->team->id}") + ]; + } + + public function broadcastWith() + { + return [ + 'deployment_id' => $this->deployment->id, + 'status' => 'started', + 'timestamp' => now() + ]; + } +} +``` + +### API Event Streaming +```php +// Server-Sent Events for real-time updates +Route::get('/api/v1/applications/{application}/events', function (Application $application) { + return response()->stream(function () use ($application) { + while (true) { + $events = $application->getRecentEvents(); + foreach ($events as $event) { + echo "data: " . json_encode($event) . "\n\n"; + } + usleep(1000000); // 1 second + } + }, 200, [ + 'Content-Type' => 'text/event-stream', + 'Cache-Control' => 'no-cache', + ]); +}); +``` diff --git a/.cursor/rules/application-architecture.mdc b/.cursor/rules/application-architecture.mdc new file mode 100644 index 000000000..162c0840f --- /dev/null +++ b/.cursor/rules/application-architecture.mdc @@ -0,0 +1,368 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify Application Architecture + +## Laravel Project Structure + +### **Core Application Directory** ([app/](mdc:app)) + +``` +app/ +โ”œโ”€โ”€ Actions/ # Business logic actions (Action pattern) +โ”œโ”€โ”€ Console/ # Artisan commands +โ”œโ”€โ”€ Contracts/ # Interface definitions +โ”œโ”€โ”€ Data/ # Data Transfer Objects (Spatie Laravel Data) +โ”œโ”€โ”€ Enums/ # Enumeration classes +โ”œโ”€โ”€ Events/ # Event classes +โ”œโ”€โ”€ Exceptions/ # Custom exception classes +โ”œโ”€โ”€ Helpers/ # Utility helper classes +โ”œโ”€โ”€ Http/ # HTTP layer (Controllers, Middleware, Requests) +โ”œโ”€โ”€ Jobs/ # Background job classes +โ”œโ”€โ”€ Listeners/ # Event listeners +โ”œโ”€โ”€ Livewire/ # Livewire components (Frontend) +โ”œโ”€โ”€ Models/ # Eloquent models (Domain entities) +โ”œโ”€โ”€ Notifications/ # Notification classes +โ”œโ”€โ”€ Policies/ # Authorization policies +โ”œโ”€โ”€ Providers/ # Service providers +โ”œโ”€โ”€ Repositories/ # Repository pattern implementations +โ”œโ”€โ”€ Services/ # Service layer classes +โ”œโ”€โ”€ Traits/ # Reusable trait classes +โ””โ”€โ”€ View/ # View composers and creators +``` + +## Core Domain Models + +### **Infrastructure Management** + +#### **[Server.php](mdc:app/Models/Server.php)** (46KB, 1343 lines) +- **Purpose**: Physical/virtual server management +- **Key Relationships**: + - `hasMany(Application::class)` - Deployed applications + - `hasMany(StandalonePostgresql::class)` - Database instances + - `belongsTo(Team::class)` - Team ownership +- **Key Features**: + - SSH connection management + - Resource monitoring + - Proxy configuration (Traefik/Caddy) + - Docker daemon interaction + +#### **[Application.php](mdc:app/Models/Application.php)** (74KB, 1734 lines) +- **Purpose**: Application deployment and management +- **Key Relationships**: + - `belongsTo(Server::class)` - Deployment target + - `belongsTo(Environment::class)` - Environment context + - `hasMany(ApplicationDeploymentQueue::class)` - Deployment history +- **Key Features**: + - Git repository integration + - Docker build and deployment + - Environment variable management + - SSL certificate handling + +#### **[Service.php](mdc:app/Models/Service.php)** (58KB, 1325 lines) +- **Purpose**: Multi-container service orchestration +- **Key Relationships**: + - `hasMany(ServiceApplication::class)` - Service components + - `hasMany(ServiceDatabase::class)` - Service databases + - `belongsTo(Environment::class)` - Environment context +- **Key Features**: + - Docker Compose generation + - Service dependency management + - Health check configuration + +### **Team & Project Organization** + +#### **[Team.php](mdc:app/Models/Team.php)** (8.9KB, 308 lines) +- **Purpose**: Multi-tenant team management +- **Key Relationships**: + - `hasMany(User::class)` - Team members + - `hasMany(Project::class)` - Team projects + - `hasMany(Server::class)` - Team servers +- **Key Features**: + - Resource limits and quotas + - Team-based access control + - Subscription management + +#### **[Project.php](mdc:app/Models/Project.php)** (4.3KB, 156 lines) +- **Purpose**: Project organization and grouping +- **Key Relationships**: + - `hasMany(Environment::class)` - Project environments + - `belongsTo(Team::class)` - Team ownership +- **Key Features**: + - Environment isolation + - Resource organization + +#### **[Environment.php](mdc:app/Models/Environment.php)** +- **Purpose**: Environment-specific configuration +- **Key Relationships**: + - `hasMany(Application::class)` - Environment applications + - `hasMany(Service::class)` - Environment services + - `belongsTo(Project::class)` - Project context + +### **Database Management Models** + +#### **Standalone Database Models** +- **[StandalonePostgresql.php](mdc:app/Models/StandalonePostgresql.php)** (11KB, 351 lines) +- **[StandaloneMysql.php](mdc:app/Models/StandaloneMysql.php)** (11KB, 351 lines) +- **[StandaloneMariadb.php](mdc:app/Models/StandaloneMariadb.php)** (10KB, 337 lines) +- **[StandaloneMongodb.php](mdc:app/Models/StandaloneMongodb.php)** (12KB, 370 lines) +- **[StandaloneRedis.php](mdc:app/Models/StandaloneRedis.php)** (12KB, 394 lines) +- **[StandaloneKeydb.php](mdc:app/Models/StandaloneKeydb.php)** (11KB, 347 lines) +- **[StandaloneDragonfly.php](mdc:app/Models/StandaloneDragonfly.php)** (11KB, 347 lines) +- **[StandaloneClickhouse.php](mdc:app/Models/StandaloneClickhouse.php)** (10KB, 336 lines) + +**Common Features**: +- Database configuration management +- Backup scheduling and execution +- Connection string generation +- Health monitoring + +### **Configuration & Settings** + +#### **[EnvironmentVariable.php](mdc:app/Models/EnvironmentVariable.php)** (7.6KB, 219 lines) +- **Purpose**: Application environment variable management +- **Key Features**: + - Encrypted value storage + - Build-time vs runtime variables + - Shared variable inheritance + +#### **[InstanceSettings.php](mdc:app/Models/InstanceSettings.php)** (3.2KB, 124 lines) +- **Purpose**: Global Coolify instance configuration +- **Key Features**: + - FQDN and port configuration + - Auto-update settings + - Security configurations + +## Architectural Patterns + +### **Action Pattern** ([app/Actions/](mdc:app/Actions)) + +Using [lorisleiva/laravel-actions](mdc:composer.json) for business logic encapsulation: + +```php +// Example Action structure +class DeployApplication extends Action +{ + public function handle(Application $application): void + { + // Business logic for deployment + } + + public function asJob(Application $application): void + { + // Queue job implementation + } +} +``` + +**Key Action Categories**: +- **Application/**: Deployment and management actions +- **Database/**: Database operations +- **Server/**: Server management actions +- **Service/**: Service orchestration actions + +### **Repository Pattern** ([app/Repositories/](mdc:app/Repositories)) + +Data access abstraction layer: +- Encapsulates database queries +- Provides testable data layer +- Abstracts complex query logic + +### **Service Layer** ([app/Services/](mdc:app/Services)) + +Business logic services: +- External API integrations +- Complex business operations +- Cross-cutting concerns + +## Data Flow Architecture + +### **Request Lifecycle** + +1. **HTTP Request** โ†’ [routes/web.php](mdc:routes/web.php) +2. **Middleware** โ†’ Authentication, authorization +3. **Livewire Component** โ†’ [app/Livewire/](mdc:app/Livewire) +4. **Action/Service** โ†’ Business logic execution +5. **Model/Repository** โ†’ Data persistence +6. **Response** โ†’ Livewire reactive update + +### **Background Processing** + +1. **Job Dispatch** โ†’ Queue system (Redis) +2. **Job Processing** โ†’ [app/Jobs/](mdc:app/Jobs) +3. **Action Execution** โ†’ Business logic +4. **Event Broadcasting** โ†’ Real-time updates +5. **Notification** โ†’ User feedback + +## Security Architecture + +### **Multi-Tenant Isolation** + +```php +// Team-based query scoping +class Application extends Model +{ + public function scopeOwnedByCurrentTeam($query) + { + return $query->whereHas('environment.project.team', function ($q) { + $q->where('id', currentTeam()->id); + }); + } +} +``` + +### **Authorization Layers** + +1. **Team Membership** โ†’ User belongs to team +2. **Resource Ownership** โ†’ Resource belongs to team +3. **Policy Authorization** โ†’ [app/Policies/](mdc:app/Policies) +4. **Environment Isolation** โ†’ Project/environment boundaries + +### **Data Protection** + +- **Environment Variables**: Encrypted at rest +- **SSH Keys**: Secure storage and transmission +- **API Tokens**: Sanctum-based authentication +- **Audit Logging**: [spatie/laravel-activitylog](mdc:composer.json) + +## Configuration Hierarchy + +### **Global Configuration** +- **[InstanceSettings](mdc:app/Models/InstanceSettings.php)**: System-wide settings +- **[config/](mdc:config)**: Laravel configuration files + +### **Team Configuration** +- **[Team](mdc:app/Models/Team.php)**: Team-specific settings +- **[ServerSetting](mdc:app/Models/ServerSetting.php)**: Server configurations + +### **Project Configuration** +- **[ProjectSetting](mdc:app/Models/ProjectSetting.php)**: Project settings +- **[Environment](mdc:app/Models/Environment.php)**: Environment variables + +### **Application Configuration** +- **[ApplicationSetting](mdc:app/Models/ApplicationSetting.php)**: App-specific settings +- **[EnvironmentVariable](mdc:app/Models/EnvironmentVariable.php)**: Runtime configuration + +## Event-Driven Architecture + +### **Event Broadcasting** ([app/Events/](mdc:app/Events)) + +Real-time updates using Laravel Echo and WebSockets: + +```php +// Example event structure +class ApplicationDeploymentStarted implements ShouldBroadcast +{ + public function broadcastOn(): array + { + return [ + new PrivateChannel("team.{$this->application->team->id}"), + ]; + } +} +``` + +### **Event Listeners** ([app/Listeners/](mdc:app/Listeners)) + +- Deployment status updates +- Resource monitoring alerts +- Notification dispatching +- Audit log creation + +## Database Design Patterns + +### **Polymorphic Relationships** + +```php +// Environment variables can belong to multiple resource types +class EnvironmentVariable extends Model +{ + public function resource(): MorphTo + { + return $this->morphTo(); + } +} +``` + +### **Team-Based Soft Scoping** + +All major resources include team-based query scoping: + +```php +// Automatic team filtering +$applications = Application::ownedByCurrentTeam()->get(); +$servers = Server::ownedByCurrentTeam()->get(); +``` + +### **Configuration Inheritance** + +Environment variables cascade from: +1. **Shared Variables** โ†’ Team-wide defaults +2. **Project Variables** โ†’ Project-specific overrides +3. **Application Variables** โ†’ Application-specific values + +## Integration Patterns + +### **Git Provider Integration** + +Abstracted git operations supporting: +- **GitHub**: [app/Models/GithubApp.php](mdc:app/Models/GithubApp.php) +- **GitLab**: [app/Models/GitlabApp.php](mdc:app/Models/GitlabApp.php) +- **Bitbucket**: Webhook integration +- **Gitea**: Self-hosted Git support + +### **Docker Integration** + +- **Container Management**: Direct Docker API communication +- **Image Building**: Dockerfile and Buildpack support +- **Network Management**: Custom Docker networks +- **Volume Management**: Persistent storage handling + +### **SSH Communication** + +- **[phpseclib/phpseclib](mdc:composer.json)**: Secure SSH connections +- **Multiplexing**: Connection pooling for efficiency +- **Key Management**: [PrivateKey](mdc:app/Models/PrivateKey.php) model + +## Testing Architecture + +### **Test Structure** ([tests/](mdc:tests)) + +``` +tests/ +โ”œโ”€โ”€ Feature/ # Integration tests +โ”œโ”€โ”€ Unit/ # Unit tests +โ”œโ”€โ”€ Browser/ # Dusk browser tests +โ”œโ”€โ”€ Traits/ # Test helper traits +โ”œโ”€โ”€ Pest.php # Pest configuration +โ””โ”€โ”€ TestCase.php # Base test case +``` + +### **Testing Patterns** + +- **Feature Tests**: Full request lifecycle testing +- **Unit Tests**: Individual class/method testing +- **Browser Tests**: End-to-end user workflows +- **Database Testing**: Factories and seeders + +## Performance Considerations + +### **Query Optimization** + +- **Eager Loading**: Prevent N+1 queries +- **Query Scoping**: Team-based filtering +- **Database Indexing**: Optimized for common queries + +### **Caching Strategy** + +- **Redis**: Session and cache storage +- **Model Caching**: Frequently accessed data +- **Query Caching**: Expensive query results + +### **Background Processing** + +- **Queue Workers**: Horizon-managed job processing +- **Job Batching**: Related job grouping +- **Failed Job Handling**: Automatic retry logic diff --git a/.cursor/rules/cursor_rules.mdc b/.cursor/rules/cursor_rules.mdc new file mode 100644 index 000000000..7dfae3de0 --- /dev/null +++ b/.cursor/rules/cursor_rules.mdc @@ -0,0 +1,53 @@ +--- +description: Guidelines for creating and maintaining Cursor rules to ensure consistency and effectiveness. +globs: .cursor/rules/*.mdc +alwaysApply: true +--- + +- **Required Rule Structure:** + ```markdown + --- + description: Clear, one-line description of what the rule enforces + globs: path/to/files/*.ext, other/path/**/* + alwaysApply: boolean + --- + + - **Main Points in Bold** + - Sub-points with details + - Examples and explanations + ``` + +- **File References:** + - Use `[filename](mdc:path/to/file)` ([filename](mdc:filename)) to reference files + - Example: [prisma.mdc](mdc:.cursor/rules/prisma.mdc) for rule references + - Example: [schema.prisma](mdc:prisma/schema.prisma) for code references + +- **Code Examples:** + - Use language-specific code blocks + ```typescript + // โœ… DO: Show good examples + const goodExample = true; + + // โŒ DON'T: Show anti-patterns + const badExample = false; + ``` + +- **Rule Content Guidelines:** + - Start with high-level overview + - Include specific, actionable requirements + - Show examples of correct implementation + - Reference existing code when possible + - Keep rules DRY by referencing other rules + +- **Rule Maintenance:** + - Update rules when new patterns emerge + - Add examples from actual codebase + - Remove outdated patterns + - Cross-reference related rules + +- **Best Practices:** + - Use bullet points for clarity + - Keep descriptions concise + - Include both DO and DON'T examples + - Reference actual code over theoretical examples + - Use consistent formatting across rules \ No newline at end of file diff --git a/.cursor/rules/database-patterns.mdc b/.cursor/rules/database-patterns.mdc new file mode 100644 index 000000000..58934598b --- /dev/null +++ b/.cursor/rules/database-patterns.mdc @@ -0,0 +1,306 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify Database Architecture & Patterns + +## Database Strategy + +Coolify uses **PostgreSQL 15** as the primary database with **Redis 7** for caching and real-time features. The architecture supports managing multiple external databases across different servers. + +## Primary Database (PostgreSQL) + +### Core Tables & Models + +#### User & Team Management +- **[User.php](mdc:app/Models/User.php)** - User authentication and profiles +- **[Team.php](mdc:app/Models/Team.php)** - Multi-tenant organization structure +- **[TeamInvitation.php](mdc:app/Models/TeamInvitation.php)** - Team collaboration invitations +- **[PersonalAccessToken.php](mdc:app/Models/PersonalAccessToken.php)** - API token management + +#### Infrastructure Management +- **[Server.php](mdc:app/Models/Server.php)** - Physical/virtual server definitions (46KB, complex) +- **[PrivateKey.php](mdc:app/Models/PrivateKey.php)** - SSH key management +- **[ServerSetting.php](mdc:app/Models/ServerSetting.php)** - Server-specific configurations + +#### Project Organization +- **[Project.php](mdc:app/Models/Project.php)** - Project containers for applications +- **[Environment.php](mdc:app/Models/Environment.php)** - Environment isolation (staging, production, etc.) +- **[ProjectSetting.php](mdc:app/Models/ProjectSetting.php)** - Project-specific settings + +#### Application Deployment +- **[Application.php](mdc:app/Models/Application.php)** - Main application entity (74KB, highly complex) +- **[ApplicationSetting.php](mdc:app/Models/ApplicationSetting.php)** - Application configurations +- **[ApplicationDeploymentQueue.php](mdc:app/Models/ApplicationDeploymentQueue.php)** - Deployment orchestration +- **[ApplicationPreview.php](mdc:app/Models/ApplicationPreview.php)** - Preview environment management + +#### Service Management +- **[Service.php](mdc:app/Models/Service.php)** - Service definitions (58KB, complex) +- **[ServiceApplication.php](mdc:app/Models/ServiceApplication.php)** - Service components +- **[ServiceDatabase.php](mdc:app/Models/ServiceDatabase.php)** - Service-attached databases + +## Database Type Support + +### Standalone Database Models +Each database type has its own dedicated model with specific configurations: + +#### SQL Databases +- **[StandalonePostgresql.php](mdc:app/Models/StandalonePostgresql.php)** - PostgreSQL instances +- **[StandaloneMysql.php](mdc:app/Models/StandaloneMysql.php)** - MySQL instances +- **[StandaloneMariadb.php](mdc:app/Models/StandaloneMariadb.php)** - MariaDB instances + +#### NoSQL & Analytics +- **[StandaloneMongodb.php](mdc:app/Models/StandaloneMongodb.php)** - MongoDB instances +- **[StandaloneClickhouse.php](mdc:app/Models/StandaloneClickhouse.php)** - ClickHouse analytics + +#### Caching & In-Memory +- **[StandaloneRedis.php](mdc:app/Models/StandaloneRedis.php)** - Redis instances +- **[StandaloneKeydb.php](mdc:app/Models/StandaloneKeydb.php)** - KeyDB instances +- **[StandaloneDragonfly.php](mdc:app/Models/StandaloneDragonfly.php)** - Dragonfly instances + +## Configuration Management + +### Environment Variables +- **[EnvironmentVariable.php](mdc:app/Models/EnvironmentVariable.php)** - Application-specific environment variables +- **[SharedEnvironmentVariable.php](mdc:app/Models/SharedEnvironmentVariable.php)** - Shared across applications + +### Settings Hierarchy +- **[InstanceSettings.php](mdc:app/Models/InstanceSettings.php)** - Global Coolify instance settings +- **[ServerSetting.php](mdc:app/Models/ServerSetting.php)** - Server-specific settings +- **[ProjectSetting.php](mdc:app/Models/ProjectSetting.php)** - Project-level settings +- **[ApplicationSetting.php](mdc:app/Models/ApplicationSetting.php)** - Application settings + +## Storage & Backup Systems + +### Storage Management +- **[S3Storage.php](mdc:app/Models/S3Storage.php)** - S3-compatible storage configurations +- **[LocalFileVolume.php](mdc:app/Models/LocalFileVolume.php)** - Local filesystem volumes +- **[LocalPersistentVolume.php](mdc:app/Models/LocalPersistentVolume.php)** - Persistent volume management + +### Backup Infrastructure +- **[ScheduledDatabaseBackup.php](mdc:app/Models/ScheduledDatabaseBackup.php)** - Automated backup scheduling +- **[ScheduledDatabaseBackupExecution.php](mdc:app/Models/ScheduledDatabaseBackupExecution.php)** - Backup execution tracking + +### Task Scheduling +- **[ScheduledTask.php](mdc:app/Models/ScheduledTask.php)** - Cron job management +- **[ScheduledTaskExecution.php](mdc:app/Models/ScheduledTaskExecution.php)** - Task execution history + +## Notification & Integration Models + +### Notification Channels +- **[EmailNotificationSettings.php](mdc:app/Models/EmailNotificationSettings.php)** - Email notifications +- **[DiscordNotificationSettings.php](mdc:app/Models/DiscordNotificationSettings.php)** - Discord integration +- **[SlackNotificationSettings.php](mdc:app/Models/SlackNotificationSettings.php)** - Slack integration +- **[TelegramNotificationSettings.php](mdc:app/Models/TelegramNotificationSettings.php)** - Telegram bot +- **[PushoverNotificationSettings.php](mdc:app/Models/PushoverNotificationSettings.php)** - Pushover notifications + +### Source Control Integration +- **[GithubApp.php](mdc:app/Models/GithubApp.php)** - GitHub App integration +- **[GitlabApp.php](mdc:app/Models/GitlabApp.php)** - GitLab integration + +### OAuth & Authentication +- **[OauthSetting.php](mdc:app/Models/OauthSetting.php)** - OAuth provider configurations + +## Docker & Container Management + +### Container Orchestration +- **[StandaloneDocker.php](mdc:app/Models/StandaloneDocker.php)** - Standalone Docker containers +- **[SwarmDocker.php](mdc:app/Models/SwarmDocker.php)** - Docker Swarm management + +### SSL & Security +- **[SslCertificate.php](mdc:app/Models/SslCertificate.php)** - SSL certificate management + +## Database Migration Strategy + +### Migration Location: [database/migrations/](mdc:database/migrations) + +#### Migration Patterns +```php +// Typical Coolify migration structure +Schema::create('applications', function (Blueprint $table) { + $table->id(); + $table->string('name'); + $table->string('fqdn')->nullable(); + $table->json('environment_variables')->nullable(); + $table->foreignId('destination_id'); + $table->foreignId('source_id'); + $table->timestamps(); +}); +``` + +### Schema Versioning +- **Incremental migrations** for database evolution +- **Data migrations** for complex transformations +- **Rollback support** for deployment safety + +## Eloquent Model Patterns + +### Base Model Structure +- **[BaseModel.php](mdc:app/Models/BaseModel.php)** - Common model functionality +- **UUID primary keys** for distributed systems +- **Soft deletes** for audit trails +- **Activity logging** with Spatie package + +### Relationship Patterns +```php +// Typical relationship structure in Application model +class Application extends Model +{ + public function server() + { + return $this->belongsTo(Server::class); + } + + public function environment() + { + return $this->belongsTo(Environment::class); + } + + public function deployments() + { + return $this->hasMany(ApplicationDeploymentQueue::class); + } + + public function environmentVariables() + { + return $this->hasMany(EnvironmentVariable::class); + } +} +``` + +### Model Traits +```php +// Common traits used across models +use SoftDeletes; +use LogsActivity; +use HasFactory; +use HasUuids; +``` + +## Caching Strategy (Redis) + +### Cache Usage Patterns +- **Session storage** - User authentication sessions +- **Queue backend** - Background job processing +- **Model caching** - Expensive query results +- **Real-time data** - WebSocket state management + +### Cache Keys Structure +``` +coolify:session:{session_id} +coolify:server:{server_id}:status +coolify:deployment:{deployment_id}:logs +coolify:user:{user_id}:teams +``` + +## Query Optimization Patterns + +### Eager Loading +```php +// Optimized queries with relationships +$applications = Application::with([ + 'server', + 'environment.project', + 'environmentVariables', + 'deployments' => function ($query) { + $query->latest()->limit(5); + } +])->get(); +``` + +### Chunking for Large Datasets +```php +// Processing large datasets efficiently +Server::chunk(100, function ($servers) { + foreach ($servers as $server) { + // Process server monitoring + } +}); +``` + +### Database Indexes +- **Primary keys** on all tables +- **Foreign key indexes** for relationships +- **Composite indexes** for common queries +- **Unique constraints** for business rules + +## Data Consistency Patterns + +### Database Transactions +```php +// Atomic operations for deployment +DB::transaction(function () { + $application = Application::create($data); + $application->environmentVariables()->createMany($envVars); + $application->deployments()->create(['status' => 'queued']); +}); +``` + +### Model Events +```php +// Automatic cleanup on model deletion +class Application extends Model +{ + protected static function booted() + { + static::deleting(function ($application) { + $application->environmentVariables()->delete(); + $application->deployments()->delete(); + }); + } +} +``` + +## Backup & Recovery + +### Database Backup Strategy +- **Automated PostgreSQL backups** via scheduled tasks +- **Point-in-time recovery** capability +- **Cross-region backup** replication +- **Backup verification** and testing + +### Data Export/Import +- **Application configurations** export/import +- **Environment variable** bulk operations +- **Server configurations** backup and restore + +## Performance Monitoring + +### Query Performance +- **Laravel Telescope** for development debugging +- **Slow query logging** in production +- **Database connection** pooling +- **Read replica** support for scaling + +### Metrics Collection +- **Database size** monitoring +- **Connection count** tracking +- **Query execution time** analysis +- **Cache hit rates** monitoring + +## Multi-Tenancy Pattern + +### Team-Based Isolation +```php +// Global scope for team-based filtering +class Application extends Model +{ + protected static function booted() + { + static::addGlobalScope('team', function (Builder $builder) { + if (auth()->user()) { + $builder->whereHas('environment.project', function ($query) { + $query->where('team_id', auth()->user()->currentTeam->id); + }); + } + }); + } +} +``` + +### Data Separation +- **Team-scoped queries** by default +- **Cross-team access** controls +- **Admin access** patterns +- **Data isolation** guarantees diff --git a/.cursor/rules/deployment-architecture.mdc b/.cursor/rules/deployment-architecture.mdc new file mode 100644 index 000000000..5174cbb99 --- /dev/null +++ b/.cursor/rules/deployment-architecture.mdc @@ -0,0 +1,310 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify Deployment Architecture + +## Deployment Philosophy + +Coolify orchestrates **Docker-based deployments** across multiple servers with automated configuration generation, zero-downtime deployments, and comprehensive monitoring. + +## Core Deployment Components + +### Deployment Models +- **[Application.php](mdc:app/Models/Application.php)** - Main application entity with deployment configurations +- **[ApplicationDeploymentQueue.php](mdc:app/Models/ApplicationDeploymentQueue.php)** - Deployment job orchestration +- **[Service.php](mdc:app/Models/Service.php)** - Multi-container service definitions +- **[Server.php](mdc:app/Models/Server.php)** - Target deployment infrastructure + +### Infrastructure Management +- **[PrivateKey.php](mdc:app/Models/PrivateKey.php)** - SSH key management for secure server access +- **[StandaloneDocker.php](mdc:app/Models/StandaloneDocker.php)** - Single container deployments +- **[SwarmDocker.php](mdc:app/Models/SwarmDocker.php)** - Docker Swarm orchestration + +## Deployment Workflow + +### 1. Source Code Integration +``` +Git Repository โ†’ Webhook โ†’ Coolify โ†’ Build & Deploy +``` + +#### Source Control Models +- **[GithubApp.php](mdc:app/Models/GithubApp.php)** - GitHub integration and webhooks +- **[GitlabApp.php](mdc:app/Models/GitlabApp.php)** - GitLab CI/CD integration + +#### Deployment Triggers +- **Git push** to configured branches +- **Manual deployment** via UI +- **Scheduled deployments** via cron +- **API-triggered** deployments + +### 2. Build Process +``` +Source Code โ†’ Docker Build โ†’ Image Registry โ†’ Deployment +``` + +#### Build Configurations +- **Dockerfile detection** and custom Dockerfile support +- **Buildpack integration** for framework detection +- **Multi-stage builds** for optimization +- **Cache layer** management for faster builds + +### 3. Deployment Orchestration +``` +Queue Job โ†’ Configuration Generation โ†’ Container Deployment โ†’ Health Checks +``` + +## Deployment Actions + +### Location: [app/Actions/](mdc:app/Actions) + +#### Application Deployment Actions +- **Application/** - Core application deployment logic +- **Docker/** - Docker container management +- **Service/** - Multi-container service orchestration +- **Proxy/** - Reverse proxy configuration + +#### Database Actions +- **Database/** - Database deployment and management +- Automated backup scheduling +- Connection management and health checks + +#### Server Management Actions +- **Server/** - Server provisioning and configuration +- SSH connection establishment +- Docker daemon management + +## Configuration Generation + +### Dynamic Configuration +- **[ConfigurationGenerator.php](mdc:app/Services/ConfigurationGenerator.php)** - Generates deployment configurations +- **[ConfigurationRepository.php](mdc:app/Services/ConfigurationRepository.php)** - Configuration management + +### Generated Configurations +#### Docker Compose Files +```yaml +# Generated docker-compose.yml structure +version: '3.8' +services: + app: + image: ${APP_IMAGE} + environment: + - ${ENV_VARIABLES} + labels: + - traefik.enable=true + - traefik.http.routers.app.rule=Host(`${FQDN}`) + volumes: + - ${VOLUME_MAPPINGS} + networks: + - coolify +``` + +#### Nginx Configurations +- **Reverse proxy** setup +- **SSL termination** with automatic certificates +- **Load balancing** for multiple instances +- **Custom headers** and routing rules + +## Container Orchestration + +### Docker Integration +- **[DockerImageParser.php](mdc:app/Services/DockerImageParser.php)** - Parse and validate Docker images +- **Container lifecycle** management +- **Resource allocation** and limits +- **Network isolation** and communication + +### Volume Management +- **[LocalFileVolume.php](mdc:app/Models/LocalFileVolume.php)** - Persistent file storage +- **[LocalPersistentVolume.php](mdc:app/Models/LocalPersistentVolume.php)** - Data persistence +- **Backup integration** for volume data + +### Network Configuration +- **Custom Docker networks** for isolation +- **Service discovery** between containers +- **Port mapping** and exposure +- **SSL/TLS termination** + +## Environment Management + +### Environment Isolation +- **[Environment.php](mdc:app/Models/Environment.php)** - Development, staging, production environments +- **[EnvironmentVariable.php](mdc:app/Models/EnvironmentVariable.php)** - Application-specific variables +- **[SharedEnvironmentVariable.php](mdc:app/Models/SharedEnvironmentVariable.php)** - Cross-application variables + +### Configuration Hierarchy +``` +Instance Settings โ†’ Server Settings โ†’ Project Settings โ†’ Application Settings +``` + +## Preview Environments + +### Git-Based Previews +- **[ApplicationPreview.php](mdc:app/Models/ApplicationPreview.php)** - Preview environment management +- **Automatic PR/MR previews** for feature branches +- **Isolated environments** for testing +- **Automatic cleanup** after merge/close + +### Preview Workflow +``` +Feature Branch โ†’ Auto-Deploy โ†’ Preview URL โ†’ Review โ†’ Cleanup +``` + +## SSL & Security + +### Certificate Management +- **[SslCertificate.php](mdc:app/Models/SslCertificate.php)** - SSL certificate automation +- **Let's Encrypt** integration for free certificates +- **Custom certificate** upload support +- **Automatic renewal** and monitoring + +### Security Patterns +- **Private Docker networks** for container isolation +- **SSH key-based** server authentication +- **Environment variable** encryption +- **Access control** via team permissions + +## Backup & Recovery + +### Database Backups +- **[ScheduledDatabaseBackup.php](mdc:app/Models/ScheduledDatabaseBackup.php)** - Automated database backups +- **[ScheduledDatabaseBackupExecution.php](mdc:app/Models/ScheduledDatabaseBackupExecution.php)** - Backup execution tracking +- **S3-compatible storage** for backup destinations + +### Application Backups +- **Volume snapshots** for persistent data +- **Configuration export** for disaster recovery +- **Cross-region replication** for high availability + +## Monitoring & Logging + +### Real-Time Monitoring +- **[ActivityMonitor.php](mdc:app/Livewire/ActivityMonitor.php)** - Live deployment monitoring +- **WebSocket-based** log streaming +- **Container health checks** and alerts +- **Resource usage** tracking + +### Deployment Logs +- **Build process** logging +- **Container startup** logs +- **Application runtime** logs +- **Error tracking** and alerting + +## Queue System + +### Background Jobs +Location: [app/Jobs/](mdc:app/Jobs) +- **Deployment jobs** for async processing +- **Server monitoring** jobs +- **Backup scheduling** jobs +- **Notification delivery** jobs + +### Queue Processing +- **Redis-backed** job queues +- **Laravel Horizon** for queue monitoring +- **Failed job** retry mechanisms +- **Queue worker** auto-scaling + +## Multi-Server Deployment + +### Server Types +- **Standalone servers** - Single Docker host +- **Docker Swarm** - Multi-node orchestration +- **Remote servers** - SSH-based deployment +- **Local development** - Docker Desktop integration + +### Load Balancing +- **Traefik integration** for automatic load balancing +- **Health check** based routing +- **Blue-green deployments** for zero downtime +- **Rolling updates** with configurable strategies + +## Deployment Strategies + +### Zero-Downtime Deployment +``` +Old Container โ†’ New Container Build โ†’ Health Check โ†’ Traffic Switch โ†’ Old Container Cleanup +``` + +### Blue-Green Deployment +- **Parallel environments** for safe deployments +- **Instant rollback** capability +- **Database migration** handling +- **Configuration synchronization** + +### Rolling Updates +- **Gradual instance** replacement +- **Configurable update** strategy +- **Automatic rollback** on failure +- **Health check** validation + +## API Integration + +### Deployment API +Routes: [routes/api.php](mdc:routes/api.php) +- **RESTful endpoints** for deployment management +- **Webhook receivers** for CI/CD integration +- **Status reporting** endpoints +- **Deployment triggering** via API + +### Authentication +- **Laravel Sanctum** API tokens +- **Team-based** access control +- **Rate limiting** for API calls +- **Audit logging** for API usage + +## Error Handling & Recovery + +### Deployment Failure Recovery +- **Automatic rollback** on deployment failure +- **Health check** failure handling +- **Container crash** recovery +- **Resource exhaustion** protection + +### Monitoring & Alerting +- **Failed deployment** notifications +- **Resource threshold** alerts +- **SSL certificate** expiry warnings +- **Backup failure** notifications + +## Performance Optimization + +### Build Optimization +- **Docker layer** caching +- **Multi-stage builds** for smaller images +- **Build artifact** reuse +- **Parallel build** processing + +### Runtime Optimization +- **Container resource** limits +- **Auto-scaling** based on metrics +- **Connection pooling** for databases +- **CDN integration** for static assets + +## Compliance & Governance + +### Audit Trail +- **Deployment history** tracking +- **Configuration changes** logging +- **User action** auditing +- **Resource access** monitoring + +### Backup Compliance +- **Retention policies** for backups +- **Encryption at rest** for sensitive data +- **Cross-region** backup replication +- **Recovery testing** automation + +## Integration Patterns + +### CI/CD Integration +- **GitHub Actions** compatibility +- **GitLab CI** pipeline integration +- **Custom webhook** endpoints +- **Build status** reporting + +### External Services +- **S3-compatible** storage integration +- **External database** connections +- **Third-party monitoring** tools +- **Custom notification** channels diff --git a/.cursor/rules/dev_workflow.mdc b/.cursor/rules/dev_workflow.mdc new file mode 100644 index 000000000..003251d8a --- /dev/null +++ b/.cursor/rules/dev_workflow.mdc @@ -0,0 +1,219 @@ +--- +description: Guide for using Task Master to manage task-driven development workflows +globs: **/* +alwaysApply: true +--- +# Task Master Development Workflow + +This guide outlines the typical process for using Task Master to manage software development projects. + +## Primary Interaction: MCP Server vs. CLI + +Task Master offers two primary ways to interact: + +1. **MCP Server (Recommended for Integrated Tools)**: + - For AI agents and integrated development environments (like Cursor), interacting via the **MCP server is the preferred method**. + - The MCP server exposes Task Master functionality through a set of tools (e.g., `get_tasks`, `add_subtask`). + - This method offers better performance, structured data exchange, and richer error handling compared to CLI parsing. + - Refer to [`mcp.mdc`](mdc:.cursor/rules/mcp.mdc) for details on the MCP architecture and available tools. + - A comprehensive list and description of MCP tools and their corresponding CLI commands can be found in [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc). + - **Restart the MCP server** if core logic in `scripts/modules` or MCP tool/direct function definitions change. + +2. **`task-master` CLI (For Users & Fallback)**: + - The global `task-master` command provides a user-friendly interface for direct terminal interaction. + - It can also serve as a fallback if the MCP server is inaccessible or a specific function isn't exposed via MCP. + - Install globally with `npm install -g task-master-ai` or use locally via `npx task-master-ai ...`. + - The CLI commands often mirror the MCP tools (e.g., `task-master list` corresponds to `get_tasks`). + - Refer to [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc) for a detailed command reference. + +## Standard Development Workflow Process + +- Start new projects by running `initialize_project` tool / `task-master init` or `parse_prd` / `task-master parse-prd --input=''` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to generate initial tasks.json +- Begin coding sessions with `get_tasks` / `task-master list` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to see current tasks, status, and IDs +- Determine the next task to work on using `next_task` / `task-master next` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)). +- Analyze task complexity with `analyze_project_complexity` / `task-master analyze-complexity --research` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) before breaking down tasks +- Review complexity report using `complexity_report` / `task-master complexity-report` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)). +- Select tasks based on dependencies (all marked 'done'), priority level, and ID order +- Clarify tasks by checking task files in tasks/ directory or asking for user input +- View specific task details using `get_task` / `task-master show ` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to understand implementation requirements +- Break down complex tasks using `expand_task` / `task-master expand --id= --force --research` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) with appropriate flags like `--force` (to replace existing subtasks) and `--research`. +- Clear existing subtasks if needed using `clear_subtasks` / `task-master clear-subtasks --id=` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) before regenerating +- Implement code following task details, dependencies, and project standards +- Verify tasks according to test strategies before marking as complete (See [`tests.mdc`](mdc:.cursor/rules/tests.mdc)) +- Mark completed tasks with `set_task_status` / `task-master set-status --id= --status=done` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) +- Update dependent tasks when implementation differs from original plan using `update` / `task-master update --from= --prompt="..."` or `update_task` / `task-master update-task --id= --prompt="..."` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) +- Add new tasks discovered during implementation using `add_task` / `task-master add-task --prompt="..." --research` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)). +- Add new subtasks as needed using `add_subtask` / `task-master add-subtask --parent= --title="..."` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)). +- Append notes or details to subtasks using `update_subtask` / `task-master update-subtask --id= --prompt='Add implementation notes here...\nMore details...'` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)). +- Generate task files with `generate` / `task-master generate` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) after updating tasks.json +- Maintain valid dependency structure with `add_dependency`/`remove_dependency` tools or `task-master add-dependency`/`remove-dependency` commands, `validate_dependencies` / `task-master validate-dependencies`, and `fix_dependencies` / `task-master fix-dependencies` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) when needed +- Respect dependency chains and task priorities when selecting work +- Report progress regularly using `get_tasks` / `task-master list` + +## Task Complexity Analysis + +- Run `analyze_project_complexity` / `task-master analyze-complexity --research` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) for comprehensive analysis +- Review complexity report via `complexity_report` / `task-master complexity-report` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) for a formatted, readable version. +- Focus on tasks with highest complexity scores (8-10) for detailed breakdown +- Use analysis results to determine appropriate subtask allocation +- Note that reports are automatically used by the `expand_task` tool/command + +## Task Breakdown Process + +- Use `expand_task` / `task-master expand --id=`. It automatically uses the complexity report if found, otherwise generates default number of subtasks. +- Use `--num=` to specify an explicit number of subtasks, overriding defaults or complexity report recommendations. +- Add `--research` flag to leverage Perplexity AI for research-backed expansion. +- Add `--force` flag to clear existing subtasks before generating new ones (default is to append). +- Use `--prompt=""` to provide additional context when needed. +- Review and adjust generated subtasks as necessary. +- Use `expand_all` tool or `task-master expand --all` to expand multiple pending tasks at once, respecting flags like `--force` and `--research`. +- If subtasks need complete replacement (regardless of the `--force` flag on `expand`), clear them first with `clear_subtasks` / `task-master clear-subtasks --id=`. + +## Implementation Drift Handling + +- When implementation differs significantly from planned approach +- When future tasks need modification due to current implementation choices +- When new dependencies or requirements emerge +- Use `update` / `task-master update --from= --prompt='\nUpdate context...' --research` to update multiple future tasks. +- Use `update_task` / `task-master update-task --id= --prompt='\nUpdate context...' --research` to update a single specific task. + +## Task Status Management + +- Use 'pending' for tasks ready to be worked on +- Use 'done' for completed and verified tasks +- Use 'deferred' for postponed tasks +- Add custom status values as needed for project-specific workflows + +## Task Structure Fields + +- **id**: Unique identifier for the task (Example: `1`, `1.1`) +- **title**: Brief, descriptive title (Example: `"Initialize Repo"`) +- **description**: Concise summary of what the task involves (Example: `"Create a new repository, set up initial structure."`) +- **status**: Current state of the task (Example: `"pending"`, `"done"`, `"deferred"`) +- **dependencies**: IDs of prerequisite tasks (Example: `[1, 2.1]`) + - Dependencies are displayed with status indicators (โœ… for completed, โฑ๏ธ for pending) + - This helps quickly identify which prerequisite tasks are blocking work +- **priority**: Importance level (Example: `"high"`, `"medium"`, `"low"`) +- **details**: In-depth implementation instructions (Example: `"Use GitHub client ID/secret, handle callback, set session token."`) +- **testStrategy**: Verification approach (Example: `"Deploy and call endpoint to confirm 'Hello World' response."`) +- **subtasks**: List of smaller, more specific tasks (Example: `[{"id": 1, "title": "Configure OAuth", ...}]`) +- Refer to task structure details (previously linked to `tasks.mdc`). + +## Configuration Management (Updated) + +Taskmaster configuration is managed through two main mechanisms: + +1. **`.taskmasterconfig` File (Primary):** + * Located in the project root directory. + * Stores most configuration settings: AI model selections (main, research, fallback), parameters (max tokens, temperature), logging level, default subtasks/priority, project name, etc. + * **Managed via `task-master models --setup` command.** Do not edit manually unless you know what you are doing. + * **View/Set specific models via `task-master models` command or `models` MCP tool.** + * Created automatically when you run `task-master models --setup` for the first time. + +2. **Environment Variables (`.env` / `mcp.json`):** + * Used **only** for sensitive API keys and specific endpoint URLs. + * Place API keys (one per provider) in a `.env` file in the project root for CLI usage. + * For MCP/Cursor integration, configure these keys in the `env` section of `.cursor/mcp.json`. + * Available keys/variables: See `assets/env.example` or the Configuration section in the command reference (previously linked to `taskmaster.mdc`). + +**Important:** Non-API key settings (like model selections, `MAX_TOKENS`, `TASKMASTER_LOG_LEVEL`) are **no longer configured via environment variables**. Use the `task-master models` command (or `--setup` for interactive configuration) or the `models` MCP tool. +**If AI commands FAIL in MCP** verify that the API key for the selected provider is present in the `env` section of `.cursor/mcp.json`. +**If AI commands FAIL in CLI** verify that the API key for the selected provider is present in the `.env` file in the root of the project. + +## Determining the Next Task + +- Run `next_task` / `task-master next` to show the next task to work on. +- The command identifies tasks with all dependencies satisfied +- Tasks are prioritized by priority level, dependency count, and ID +- The command shows comprehensive task information including: + - Basic task details and description + - Implementation details + - Subtasks (if they exist) + - Contextual suggested actions +- Recommended before starting any new development work +- Respects your project's dependency structure +- Ensures tasks are completed in the appropriate sequence +- Provides ready-to-use commands for common task actions + +## Viewing Specific Task Details + +- Run `get_task` / `task-master show ` to view a specific task. +- Use dot notation for subtasks: `task-master show 1.2` (shows subtask 2 of task 1) +- Displays comprehensive information similar to the next command, but for a specific task +- For parent tasks, shows all subtasks and their current status +- For subtasks, shows parent task information and relationship +- Provides contextual suggested actions appropriate for the specific task +- Useful for examining task details before implementation or checking status + +## Managing Task Dependencies + +- Use `add_dependency` / `task-master add-dependency --id= --depends-on=` to add a dependency. +- Use `remove_dependency` / `task-master remove-dependency --id= --depends-on=` to remove a dependency. +- The system prevents circular dependencies and duplicate dependency entries +- Dependencies are checked for existence before being added or removed +- Task files are automatically regenerated after dependency changes +- Dependencies are visualized with status indicators in task listings and files + +## Iterative Subtask Implementation + +Once a task has been broken down into subtasks using `expand_task` or similar methods, follow this iterative process for implementation: + +1. **Understand the Goal (Preparation):** + * Use `get_task` / `task-master show ` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to thoroughly understand the specific goals and requirements of the subtask. + +2. **Initial Exploration & Planning (Iteration 1):** + * This is the first attempt at creating a concrete implementation plan. + * Explore the codebase to identify the precise files, functions, and even specific lines of code that will need modification. + * Determine the intended code changes (diffs) and their locations. + * Gather *all* relevant details from this exploration phase. + +3. **Log the Plan:** + * Run `update_subtask` / `task-master update-subtask --id= --prompt=''`. + * Provide the *complete and detailed* findings from the exploration phase in the prompt. Include file paths, line numbers, proposed diffs, reasoning, and any potential challenges identified. Do not omit details. The goal is to create a rich, timestamped log within the subtask's `details`. + +4. **Verify the Plan:** + * Run `get_task` / `task-master show ` again to confirm that the detailed implementation plan has been successfully appended to the subtask's details. + +5. **Begin Implementation:** + * Set the subtask status using `set_task_status` / `task-master set-status --id= --status=in-progress`. + * Start coding based on the logged plan. + +6. **Refine and Log Progress (Iteration 2+):** + * As implementation progresses, you will encounter challenges, discover nuances, or confirm successful approaches. + * **Before appending new information**: Briefly review the *existing* details logged in the subtask (using `get_task` or recalling from context) to ensure the update adds fresh insights and avoids redundancy. + * **Regularly** use `update_subtask` / `task-master update-subtask --id= --prompt='\n- What worked...\n- What didn't work...'` to append new findings. + * **Crucially, log:** + * What worked ("fundamental truths" discovered). + * What didn't work and why (to avoid repeating mistakes). + * Specific code snippets or configurations that were successful. + * Decisions made, especially if confirmed with user input. + * Any deviations from the initial plan and the reasoning. + * The objective is to continuously enrich the subtask's details, creating a log of the implementation journey that helps the AI (and human developers) learn, adapt, and avoid repeating errors. + +7. **Review & Update Rules (Post-Implementation):** + * Once the implementation for the subtask is functionally complete, review all code changes and the relevant chat history. + * Identify any new or modified code patterns, conventions, or best practices established during the implementation. + * Create new or update existing rules following internal guidelines (previously linked to `cursor_rules.mdc` and `self_improve.mdc`). + +8. **Mark Task Complete:** + * After verifying the implementation and updating any necessary rules, mark the subtask as completed: `set_task_status` / `task-master set-status --id= --status=done`. + +9. **Commit Changes (If using Git):** + * Stage the relevant code changes and any updated/new rule files (`git add .`). + * Craft a comprehensive Git commit message summarizing the work done for the subtask, including both code implementation and any rule adjustments. + * Execute the commit command directly in the terminal (e.g., `git commit -m 'feat(module): Implement feature X for subtask \n\n- Details about changes...\n- Updated rule Y for pattern Z'`). + * Consider if a Changeset is needed according to internal versioning guidelines (previously linked to `changeset.mdc`). If so, run `npm run changeset`, stage the generated file, and amend the commit or create a new one. + +10. **Proceed to Next Subtask:** + * Identify the next subtask (e.g., using `next_task` / `task-master next`). + +## Code Analysis & Refactoring Techniques + +- **Top-Level Function Search**: + - Useful for understanding module structure or planning refactors. + - Use grep/ripgrep to find exported functions/constants: + `rg "export (async function|function|const) \w+"` or similar patterns. + - Can help compare functions between files during migrations or identify potential naming conflicts. + +--- +*This workflow provides a general guideline. Adapt it based on your specific project needs and team practices.* \ No newline at end of file diff --git a/.cursor/rules/development-workflow.mdc b/.cursor/rules/development-workflow.mdc new file mode 100644 index 000000000..dd38cbc3f --- /dev/null +++ b/.cursor/rules/development-workflow.mdc @@ -0,0 +1,653 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify Development Workflow + +## Development Environment Setup + +### Prerequisites +- **PHP 8.4+** - Latest PHP version for modern features +- **Node.js 18+** - For frontend asset compilation +- **Docker & Docker Compose** - Container orchestration +- **PostgreSQL 15** - Primary database +- **Redis 7** - Caching and queues + +### Local Development Setup + +#### Using Docker (Recommended) +```bash +# Clone the repository +git clone https://github.com/coollabsio/coolify.git +cd coolify + +# Copy environment configuration +cp .env.example .env + +# Start development environment +docker-compose -f docker-compose.dev.yml up -d + +# Install PHP dependencies +docker-compose exec app composer install + +# Install Node.js dependencies +docker-compose exec app npm install + +# Generate application key +docker-compose exec app php artisan key:generate + +# Run database migrations +docker-compose exec app php artisan migrate + +# Seed development data +docker-compose exec app php artisan db:seed +``` + +#### Native Development +```bash +# Install PHP dependencies +composer install + +# Install Node.js dependencies +npm install + +# Setup environment +cp .env.example .env +php artisan key:generate + +# Setup database +createdb coolify_dev +php artisan migrate +php artisan db:seed + +# Start development servers +php artisan serve & +npm run dev & +php artisan queue:work & +``` + +## Development Tools & Configuration + +### Code Quality Tools +- **[Laravel Pint](mdc:pint.json)** - PHP code style fixer +- **[Rector](mdc:rector.php)** - PHP automated refactoring (989B, 35 lines) +- **PHPStan** - Static analysis for type safety +- **ESLint** - JavaScript code quality + +### Development Configuration Files +- **[docker-compose.dev.yml](mdc:docker-compose.dev.yml)** - Development Docker setup (3.4KB, 126 lines) +- **[vite.config.js](mdc:vite.config.js)** - Frontend build configuration (1.0KB, 42 lines) +- **[.editorconfig](mdc:.editorconfig)** - Code formatting standards (258B, 19 lines) + +### Git Configuration +- **[.gitignore](mdc:.gitignore)** - Version control exclusions (522B, 40 lines) +- **[.gitattributes](mdc:.gitattributes)** - Git file handling (185B, 11 lines) + +## Development Workflow Process + +### 1. Feature Development +```bash +# Create feature branch +git checkout -b feature/new-deployment-strategy + +# Make changes following coding standards +# Run code quality checks +./vendor/bin/pint +./vendor/bin/rector process --dry-run +./vendor/bin/phpstan analyse + +# Run tests +./vendor/bin/pest +./vendor/bin/pest --coverage + +# Commit changes +git add . +git commit -m "feat: implement blue-green deployment strategy" +``` + +### 2. Code Review Process +```bash +# Push feature branch +git push origin feature/new-deployment-strategy + +# Create pull request with: +# - Clear description of changes +# - Screenshots for UI changes +# - Test coverage information +# - Breaking change documentation +``` + +### 3. Testing Requirements +- **Unit tests** for new models and services +- **Feature tests** for API endpoints +- **Browser tests** for UI changes +- **Integration tests** for deployment workflows + +## Coding Standards & Conventions + +### PHP Coding Standards +```php +// Follow PSR-12 coding standards +class ApplicationDeploymentService +{ + public function __construct( + private readonly DockerService $dockerService, + private readonly ConfigurationGenerator $configGenerator + ) {} + + public function deploy(Application $application): ApplicationDeploymentQueue + { + return DB::transaction(function () use ($application) { + $deployment = $application->deployments()->create([ + 'status' => 'queued', + 'commit_sha' => $application->getLatestCommitSha(), + ]); + + DeployApplicationJob::dispatch($deployment); + + return $deployment; + }); + } +} +``` + +### Laravel Best Practices +```php +// Use Laravel conventions +class Application extends Model +{ + // Mass assignment protection + protected $fillable = [ + 'name', 'git_repository', 'git_branch', 'fqdn' + ]; + + // Type casting + protected $casts = [ + 'environment_variables' => 'array', + 'build_pack' => BuildPack::class, + 'created_at' => 'datetime', + ]; + + // Relationships + public function server(): BelongsTo + { + return $this->belongsTo(Server::class); + } + + public function deployments(): HasMany + { + return $this->hasMany(ApplicationDeploymentQueue::class); + } +} +``` + +### Frontend Standards +```javascript +// Alpine.js component structure +document.addEventListener('alpine:init', () => { + Alpine.data('deploymentMonitor', () => ({ + status: 'idle', + logs: [], + + init() { + this.connectWebSocket(); + }, + + connectWebSocket() { + Echo.private(`application.${this.applicationId}`) + .listen('DeploymentStarted', (e) => { + this.status = 'deploying'; + }) + .listen('DeploymentCompleted', (e) => { + this.status = 'completed'; + }); + } + })); +}); +``` + +### CSS/Tailwind Standards +```html + +
+
+

+ Application Status +

+
+ +
+
+
+``` + +## Database Development + +### Migration Best Practices +```php +// Create descriptive migration files +class CreateApplicationDeploymentQueuesTable extends Migration +{ + public function up(): void + { + Schema::create('application_deployment_queues', function (Blueprint $table) { + $table->id(); + $table->foreignId('application_id')->constrained()->cascadeOnDelete(); + $table->string('status')->default('queued'); + $table->string('commit_sha')->nullable(); + $table->text('build_logs')->nullable(); + $table->text('deployment_logs')->nullable(); + $table->timestamp('started_at')->nullable(); + $table->timestamp('finished_at')->nullable(); + $table->timestamps(); + + $table->index(['application_id', 'status']); + $table->index('created_at'); + }); + } + + public function down(): void + { + Schema::dropIfExists('application_deployment_queues'); + } +} +``` + +### Model Factory Development +```php +// Create comprehensive factories for testing +class ApplicationFactory extends Factory +{ + protected $model = Application::class; + + public function definition(): array + { + return [ + 'name' => $this->faker->words(2, true), + 'fqdn' => $this->faker->domainName, + 'git_repository' => 'https://github.com/' . $this->faker->userName . '/' . $this->faker->word . '.git', + 'git_branch' => 'main', + 'build_pack' => BuildPack::NIXPACKS, + 'server_id' => Server::factory(), + 'environment_id' => Environment::factory(), + ]; + } + + public function withCustomDomain(): static + { + return $this->state(fn (array $attributes) => [ + 'fqdn' => $this->faker->domainName, + ]); + } +} +``` + +## API Development + +### Controller Standards +```php +class ApplicationController extends Controller +{ + public function __construct() + { + $this->middleware('auth:sanctum'); + $this->middleware('team.access'); + } + + public function index(Request $request): AnonymousResourceCollection + { + $applications = $request->user() + ->currentTeam + ->applications() + ->with(['server', 'environment', 'latestDeployment']) + ->paginate(); + + return ApplicationResource::collection($applications); + } + + public function store(StoreApplicationRequest $request): ApplicationResource + { + $application = $request->user() + ->currentTeam + ->applications() + ->create($request->validated()); + + return new ApplicationResource($application); + } + + public function deploy(Application $application): JsonResponse + { + $this->authorize('deploy', $application); + + $deployment = app(ApplicationDeploymentService::class) + ->deploy($application); + + return response()->json([ + 'message' => 'Deployment started successfully', + 'deployment_id' => $deployment->id, + ]); + } +} +``` + +### API Resource Development +```php +class ApplicationResource extends JsonResource +{ + public function toArray($request): array + { + return [ + 'id' => $this->id, + 'name' => $this->name, + 'fqdn' => $this->fqdn, + 'status' => $this->status, + 'git_repository' => $this->git_repository, + 'git_branch' => $this->git_branch, + 'build_pack' => $this->build_pack, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + + // Conditional relationships + 'server' => new ServerResource($this->whenLoaded('server')), + 'environment' => new EnvironmentResource($this->whenLoaded('environment')), + 'latest_deployment' => new DeploymentResource($this->whenLoaded('latestDeployment')), + + // Computed attributes + 'deployment_url' => $this->getDeploymentUrl(), + 'can_deploy' => $this->canDeploy(), + ]; + } +} +``` + +## Livewire Component Development + +### Component Structure +```php +class ApplicationShow extends Component +{ + public Application $application; + public bool $showLogs = false; + + protected $listeners = [ + 'deployment.started' => 'refreshDeploymentStatus', + 'deployment.completed' => 'refreshDeploymentStatus', + ]; + + public function mount(Application $application): void + { + $this->authorize('view', $application); + $this->application = $application; + } + + public function deploy(): void + { + $this->authorize('deploy', $this->application); + + try { + app(ApplicationDeploymentService::class)->deploy($this->application); + + $this->dispatch('deployment.started', [ + 'application_id' => $this->application->id + ]); + + session()->flash('success', 'Deployment started successfully'); + } catch (Exception $e) { + session()->flash('error', 'Failed to start deployment: ' . $e->getMessage()); + } + } + + public function refreshDeploymentStatus(): void + { + $this->application->refresh(); + } + + public function render(): View + { + return view('livewire.application.show', [ + 'deployments' => $this->application + ->deployments() + ->latest() + ->limit(10) + ->get() + ]); + } +} +``` + +## Queue Job Development + +### Job Structure +```php +class DeployApplicationJob implements ShouldQueue +{ + use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + + public int $tries = 3; + public int $maxExceptions = 1; + + public function __construct( + public ApplicationDeploymentQueue $deployment + ) {} + + public function handle( + DockerService $dockerService, + ConfigurationGenerator $configGenerator + ): void { + $this->deployment->update(['status' => 'running', 'started_at' => now()]); + + try { + // Generate configuration + $config = $configGenerator->generateDockerCompose($this->deployment->application); + + // Build and deploy + $imageTag = $dockerService->buildImage($this->deployment->application); + $dockerService->deployContainer($this->deployment->application, $imageTag); + + $this->deployment->update([ + 'status' => 'success', + 'finished_at' => now() + ]); + + // Broadcast success + broadcast(new DeploymentCompleted($this->deployment)); + + } catch (Exception $e) { + $this->deployment->update([ + 'status' => 'failed', + 'error_message' => $e->getMessage(), + 'finished_at' => now() + ]); + + broadcast(new DeploymentFailed($this->deployment)); + + throw $e; + } + } + + public function backoff(): array + { + return [1, 5, 10]; + } + + public function failed(Throwable $exception): void + { + $this->deployment->update([ + 'status' => 'failed', + 'error_message' => $exception->getMessage(), + 'finished_at' => now() + ]); + } +} +``` + +## Testing Development + +### Test Structure +```php +// Feature test example +test('user can deploy application via API', function () { + $user = User::factory()->create(); + $application = Application::factory()->create([ + 'team_id' => $user->currentTeam->id + ]); + + // Mock external services + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andReturn('app:latest'); + $mock->shouldReceive('deployContainer')->andReturn(true); + }); + + $response = $this->actingAs($user) + ->postJson("/api/v1/applications/{$application->id}/deploy"); + + $response->assertStatus(200) + ->assertJson([ + 'message' => 'Deployment started successfully' + ]); + + expect($application->deployments()->count())->toBe(1); + expect($application->deployments()->first()->status)->toBe('queued'); +}); +``` + +## Documentation Standards + +### Code Documentation +```php +/** + * Deploy an application to the specified server. + * + * This method creates a new deployment queue entry and dispatches + * a background job to handle the actual deployment process. + * + * @param Application $application The application to deploy + * @param array $options Additional deployment options + * @return ApplicationDeploymentQueue The created deployment queue entry + * + * @throws DeploymentException When deployment cannot be started + * @throws ServerConnectionException When server is unreachable + */ +public function deploy(Application $application, array $options = []): ApplicationDeploymentQueue +{ + // Implementation +} +``` + +### API Documentation +```php +/** + * @OA\Post( + * path="/api/v1/applications/{application}/deploy", + * summary="Deploy an application", + * description="Triggers a new deployment for the specified application", + * operationId="deployApplication", + * tags={"Applications"}, + * security={{"bearerAuth":{}}}, + * @OA\Parameter( + * name="application", + * in="path", + * required=true, + * @OA\Schema(type="integer"), + * description="Application ID" + * ), + * @OA\Response( + * response=200, + * description="Deployment started successfully", + * @OA\JsonContent( + * @OA\Property(property="message", type="string"), + * @OA\Property(property="deployment_id", type="integer") + * ) + * ) + * ) + */ +``` + +## Performance Optimization + +### Database Optimization +```php +// Use eager loading to prevent N+1 queries +$applications = Application::with([ + 'server:id,name,ip', + 'environment:id,name', + 'latestDeployment:id,application_id,status,created_at' +])->get(); + +// Use database transactions for consistency +DB::transaction(function () use ($application) { + $deployment = $application->deployments()->create(['status' => 'queued']); + $application->update(['last_deployment_at' => now()]); + DeployApplicationJob::dispatch($deployment); +}); +``` + +### Caching Strategies +```php +// Cache expensive operations +public function getServerMetrics(Server $server): array +{ + return Cache::remember( + "server.{$server->id}.metrics", + now()->addMinutes(5), + fn () => $this->fetchServerMetrics($server) + ); +} +``` + +## Deployment & Release Process + +### Version Management +- **[versions.json](mdc:versions.json)** - Version tracking (355B, 19 lines) +- **[CHANGELOG.md](mdc:CHANGELOG.md)** - Release notes (187KB, 7411 lines) +- **[cliff.toml](mdc:cliff.toml)** - Changelog generation (3.2KB, 85 lines) + +### Release Workflow +```bash +# Create release branch +git checkout -b release/v4.1.0 + +# Update version numbers +# Update CHANGELOG.md +# Run full test suite +./vendor/bin/pest +npm run test + +# Create release commit +git commit -m "chore: release v4.1.0" + +# Create and push tag +git tag v4.1.0 +git push origin v4.1.0 + +# Merge to main +git checkout main +git merge release/v4.1.0 +``` + +## Contributing Guidelines + +### Pull Request Process +1. **Fork** the repository +2. **Create** feature branch from `main` +3. **Implement** changes with tests +4. **Run** code quality checks +5. **Submit** pull request with clear description +6. **Address** review feedback +7. **Merge** after approval + +### Code Review Checklist +- [ ] Code follows project standards +- [ ] Tests cover new functionality +- [ ] Documentation is updated +- [ ] No breaking changes without migration +- [ ] Performance impact considered +- [ ] Security implications reviewed + +### Issue Reporting +- Use issue templates +- Provide reproduction steps +- Include environment details +- Add relevant logs/screenshots +- Label appropriately diff --git a/.cursor/rules/frontend-patterns.mdc b/.cursor/rules/frontend-patterns.mdc new file mode 100644 index 000000000..45888eee4 --- /dev/null +++ b/.cursor/rules/frontend-patterns.mdc @@ -0,0 +1,319 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify Frontend Architecture & Patterns + +## Frontend Philosophy + +Coolify uses a **server-side first** approach with minimal JavaScript, leveraging Livewire for reactivity and Alpine.js for lightweight client-side interactions. + +## Core Frontend Stack + +### Livewire 3.5+ (Primary Framework) +- **Server-side rendering** with reactive components +- **Real-time updates** without page refreshes +- **State management** handled on the server +- **WebSocket integration** for live updates + +### Alpine.js (Client-Side Interactivity) +- **Lightweight JavaScript** for DOM manipulation +- **Declarative directives** in HTML +- **Component-like behavior** without build steps +- **Perfect companion** to Livewire + +### Tailwind CSS 4.1+ (Styling) +- **Utility-first** CSS framework +- **Custom design system** for deployment platform +- **Responsive design** built-in +- **Dark mode support** + +## Livewire Component Structure + +### Location: [app/Livewire/](mdc:app/Livewire) + +#### Core Application Components +- **[Dashboard.php](mdc:app/Livewire/Dashboard.php)** - Main dashboard interface +- **[ActivityMonitor.php](mdc:app/Livewire/ActivityMonitor.php)** - Real-time activity tracking +- **[MonacoEditor.php](mdc:app/Livewire/MonacoEditor.php)** - Code editor component + +#### Server Management +- **Server/** directory - Server configuration and monitoring +- Real-time server status updates +- SSH connection management +- Resource monitoring + +#### Project & Application Management +- **Project/** directory - Project organization +- Application deployment interfaces +- Environment variable management +- Service configuration + +#### Settings & Configuration +- **Settings/** directory - System configuration +- **[SettingsEmail.php](mdc:app/Livewire/SettingsEmail.php)** - Email notification setup +- **[SettingsOauth.php](mdc:app/Livewire/SettingsOauth.php)** - OAuth provider configuration +- **[SettingsBackup.php](mdc:app/Livewire/SettingsBackup.php)** - Backup configuration + +#### User & Team Management +- **Team/** directory - Team collaboration features +- **Profile/** directory - User profile management +- **Security/** directory - Security settings + +## Blade Template Organization + +### Location: [resources/views/](mdc:resources/views) + +#### Layout Structure +- **layouts/** - Base layout templates +- **components/** - Reusable UI components +- **livewire/** - Livewire component views + +#### Feature-Specific Views +- **server/** - Server management interfaces +- **auth/** - Authentication pages +- **emails/** - Email templates +- **errors/** - Error pages + +## Interactive Components + +### Monaco Editor Integration +- **Code editing** for configuration files +- **Syntax highlighting** for multiple languages +- **Live validation** and error detection +- **Integration** with deployment process + +### Terminal Emulation (XTerm.js) +- **Real-time terminal** access to servers +- **WebSocket-based** communication +- **Multi-session** support +- **Secure connection** through SSH + +### Real-Time Updates +- **WebSocket connections** via Laravel Echo +- **Live deployment logs** streaming +- **Server monitoring** with live metrics +- **Activity notifications** in real-time + +## Alpine.js Patterns + +### Common Directives Used +```html + +
+ + + +``` + +## Tailwind CSS Patterns + +### Design System +- **Consistent spacing** using Tailwind scale +- **Color palette** optimized for deployment platform +- **Typography** hierarchy for technical content +- **Component classes** for reusable elements + +### Responsive Design +```html + +
+ +
+``` + +### Dark Mode Support +```html + +
+ +
+``` + +## Build Process + +### Vite Configuration ([vite.config.js](mdc:vite.config.js)) +- **Fast development** with hot module replacement +- **Optimized production** builds +- **Asset versioning** for cache busting +- **CSS processing** with PostCSS + +### Asset Compilation +```bash +# Development +npm run dev + +# Production build +npm run build +``` + +## State Management Patterns + +### Server-Side State (Livewire) +- **Component properties** for persistent state +- **Session storage** for user preferences +- **Database models** for application state +- **Cache layer** for performance + +### Client-Side State (Alpine.js) +- **Local component state** for UI interactions +- **Form validation** and user feedback +- **Modal and dropdown** state management +- **Temporary UI states** (loading, hover, etc.) + +## Real-Time Features + +### WebSocket Integration +```php +// Livewire component with real-time updates +class ActivityMonitor extends Component +{ + public function getListeners() + { + return [ + 'deployment.started' => 'refresh', + 'deployment.finished' => 'refresh', + 'server.status.changed' => 'updateServerStatus', + ]; + } +} +``` + +### Event Broadcasting +- **Laravel Echo** for client-side WebSocket handling +- **Pusher protocol** for real-time communication +- **Private channels** for user-specific events +- **Presence channels** for collaborative features + +## Performance Patterns + +### Lazy Loading +```php +// Livewire lazy loading +class ServerList extends Component +{ + public function placeholder() + { + return view('components.loading-skeleton'); + } +} +``` + +### Caching Strategies +- **Fragment caching** for expensive operations +- **Image optimization** with lazy loading +- **Asset bundling** and compression +- **CDN integration** for static assets + +## Form Handling Patterns + +### Livewire Forms +```php +class ServerCreateForm extends Component +{ + public $name; + public $ip; + + protected $rules = [ + 'name' => 'required|min:3', + 'ip' => 'required|ip', + ]; + + public function save() + { + $this->validate(); + // Save logic + } +} +``` + +### Real-Time Validation +- **Live validation** as user types +- **Server-side validation** rules +- **Error message** display +- **Success feedback** patterns + +## Component Communication + +### Parent-Child Communication +```php +// Parent component +$this->emit('serverCreated', $server->id); + +// Child component +protected $listeners = ['serverCreated' => 'refresh']; +``` + +### Cross-Component Events +- **Global events** for application-wide updates +- **Scoped events** for feature-specific communication +- **Browser events** for JavaScript integration + +## Error Handling & UX + +### Loading States +- **Skeleton screens** during data loading +- **Progress indicators** for long operations +- **Optimistic updates** with rollback capability + +### Error Display +- **Toast notifications** for user feedback +- **Inline validation** errors +- **Global error** handling +- **Retry mechanisms** for failed operations + +## Accessibility Patterns + +### ARIA Labels and Roles +```html + +``` + +### Keyboard Navigation +- **Tab order** management +- **Keyboard shortcuts** for power users +- **Focus management** in modals and forms +- **Screen reader** compatibility + +## Mobile Optimization + +### Touch-Friendly Interface +- **Larger tap targets** for mobile devices +- **Swipe gestures** where appropriate +- **Mobile-optimized** forms and navigation + +### Progressive Enhancement +- **Core functionality** works without JavaScript +- **Enhanced experience** with JavaScript enabled +- **Offline capabilities** where possible diff --git a/.cursor/rules/project-overview.mdc b/.cursor/rules/project-overview.mdc new file mode 100644 index 000000000..2be9f31e6 --- /dev/null +++ b/.cursor/rules/project-overview.mdc @@ -0,0 +1,161 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify Project Overview + +## What is Coolify? + +Coolify is an **open-source & self-hostable alternative to Heroku / Netlify / Vercel**. It's a comprehensive deployment platform that helps you manage servers, applications, and databases on your own hardware with just an SSH connection. + +## Core Mission + +**"Imagine having the ease of a cloud but with your own servers. That is Coolify."** + +- **No vendor lock-in** - All configurations saved to your servers +- **Self-hosted** - Complete control over your infrastructure +- **SSH-only requirement** - Works with VPS, Bare Metal, Raspberry PIs, anything +- **Docker-first** - Container-based deployment architecture + +## Key Features + +### ๐Ÿš€ **Application Deployment** +- Git-based deployments (GitHub, GitLab, Bitbucket, Gitea) +- Docker & Docker Compose support +- Preview deployments for pull requests +- Zero-downtime deployments +- Build cache optimization + +### ๐Ÿ–ฅ๏ธ **Server Management** +- Multi-server orchestration +- Real-time monitoring and logs +- SSH key management +- Proxy configuration (Traefik/Caddy) +- Resource usage tracking + +### ๐Ÿ—„๏ธ **Database Management** +- PostgreSQL, MySQL, MariaDB, MongoDB +- Redis, KeyDB, Dragonfly, ClickHouse +- Automated backups with S3 integration +- Database clustering support + +### ๐Ÿ”ง **Infrastructure as Code** +- Docker Compose generation +- Environment variable management +- SSL certificate automation +- Custom domain configuration + +### ๐Ÿ‘ฅ **Team Collaboration** +- Multi-tenant team organization +- Role-based access control +- Project and environment isolation +- Team-wide resource sharing + +### ๐Ÿ“Š **Monitoring & Observability** +- Real-time application logs +- Server resource monitoring +- Deployment status tracking +- Webhook integrations +- Notification systems (Email, Discord, Slack, Telegram) + +## Target Users + +### **DevOps Engineers** +- Infrastructure automation +- Multi-environment management +- CI/CD pipeline integration + +### **Developers** +- Easy application deployment +- Development environment provisioning +- Preview deployments for testing + +### **Small to Medium Businesses** +- Cost-effective Heroku alternative +- Self-hosted control and privacy +- Scalable infrastructure management + +### **Agencies & Consultants** +- Client project isolation +- Multi-tenant management +- White-label deployment solutions + +## Business Model + +### **Open Source (Free)** +- Complete feature set +- Self-hosted deployment +- Community support +- No feature restrictions + +### **Cloud Version (Paid)** +- Managed Coolify instance +- High availability +- Premium support +- Email notifications included +- Same price as self-hosted server (~$4-5/month) + +## Architecture Philosophy + +### **Server-Side First** +- Laravel backend with Livewire frontend +- Minimal JavaScript footprint +- Real-time updates via WebSockets +- Progressive enhancement approach + +### **Docker-Native** +- Container-first deployment strategy +- Docker Compose orchestration +- Image building and registry integration +- Volume and network management + +### **Security-Focused** +- SSH-based server communication +- Environment variable encryption +- Team-based access isolation +- Audit logging and activity tracking + +## Project Structure + +``` +coolify/ +โ”œโ”€โ”€ app/ # Laravel application core +โ”‚ โ”œโ”€โ”€ Models/ # Domain models (Application, Server, Service) +โ”‚ โ”œโ”€โ”€ Livewire/ # Frontend components +โ”‚ โ”œโ”€โ”€ Actions/ # Business logic actions +โ”‚ โ””โ”€โ”€ Jobs/ # Background job processing +โ”œโ”€โ”€ resources/ # Frontend assets and views +โ”œโ”€โ”€ database/ # Migrations and seeders +โ”œโ”€โ”€ docker/ # Docker configuration +โ”œโ”€โ”€ scripts/ # Installation and utility scripts +โ””โ”€โ”€ tests/ # Test suites (Pest, Dusk) +``` + +## Key Differentiators + +### **vs. Heroku** +- โœ… Self-hosted (no vendor lock-in) +- โœ… Multi-server support +- โœ… No usage-based pricing +- โœ… Full infrastructure control + +### **vs. Vercel/Netlify** +- โœ… Backend application support +- โœ… Database management included +- โœ… Multi-environment workflows +- โœ… Custom server infrastructure + +### **vs. Docker Swarm/Kubernetes** +- โœ… User-friendly web interface +- โœ… Git-based deployment workflows +- โœ… Integrated monitoring and logging +- โœ… No complex YAML configuration + +## Development Principles + +- **Simplicity over complexity** +- **Convention over configuration** +- **Security by default** +- **Developer experience focused** +- **Community-driven development** diff --git a/.cursor/rules/security-patterns.mdc b/.cursor/rules/security-patterns.mdc new file mode 100644 index 000000000..d47d03375 --- /dev/null +++ b/.cursor/rules/security-patterns.mdc @@ -0,0 +1,786 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify Security Architecture & Patterns + +## Security Philosophy + +Coolify implements **defense-in-depth security** with multiple layers of protection including authentication, authorization, encryption, network isolation, and secure deployment practices. + +## Authentication Architecture + +### Multi-Provider Authentication +- **[Laravel Fortify](mdc:config/fortify.php)** - Core authentication scaffolding (4.9KB, 149 lines) +- **[Laravel Sanctum](mdc:config/sanctum.php)** - API token authentication (2.4KB, 69 lines) +- **[Laravel Socialite](mdc:config/services.php)** - OAuth provider integration + +### OAuth Integration +- **[OauthSetting.php](mdc:app/Models/OauthSetting.php)** - OAuth provider configurations +- **Supported Providers**: + - Google OAuth + - Microsoft Azure AD + - Authentik + - GitHub (via GitHub Apps) + - GitLab + +### Authentication Models +```php +// User authentication with team-based access +class User extends Authenticatable +{ + use HasApiTokens, HasFactory, Notifiable; + + protected $fillable = [ + 'name', 'email', 'password' + ]; + + protected $hidden = [ + 'password', 'remember_token' + ]; + + protected $casts = [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + + public function teams(): BelongsToMany + { + return $this->belongsToMany(Team::class) + ->withPivot('role') + ->withTimestamps(); + } + + public function currentTeam(): BelongsTo + { + return $this->belongsTo(Team::class, 'current_team_id'); + } +} +``` + +## Authorization & Access Control + +### Team-Based Multi-Tenancy +- **[Team.php](mdc:app/Models/Team.php)** - Multi-tenant organization structure (8.9KB, 308 lines) +- **[TeamInvitation.php](mdc:app/Models/TeamInvitation.php)** - Secure team collaboration +- **Role-based permissions** within teams +- **Resource isolation** by team ownership + +### Authorization Patterns +```php +// Team-scoped authorization middleware +class EnsureTeamAccess +{ + public function handle(Request $request, Closure $next): Response + { + $user = $request->user(); + $teamId = $request->route('team'); + + if (!$user->teams->contains('id', $teamId)) { + abort(403, 'Access denied to team resources'); + } + + // Set current team context + $user->switchTeam($teamId); + + return $next($request); + } +} + +// Resource-level authorization policies +class ApplicationPolicy +{ + public function view(User $user, Application $application): bool + { + return $user->teams->contains('id', $application->team_id); + } + + public function deploy(User $user, Application $application): bool + { + return $this->view($user, $application) && + $user->hasTeamPermission($application->team_id, 'deploy'); + } + + public function delete(User $user, Application $application): bool + { + return $this->view($user, $application) && + $user->hasTeamRole($application->team_id, 'admin'); + } +} +``` + +### Global Scopes for Data Isolation +```php +// Automatic team-based filtering +class Application extends Model +{ + protected static function booted(): void + { + static::addGlobalScope('team', function (Builder $builder) { + if (auth()->check() && auth()->user()->currentTeam) { + $builder->whereHas('environment.project', function ($query) { + $query->where('team_id', auth()->user()->currentTeam->id); + }); + } + }); + } +} +``` + +## API Security + +### Token-Based Authentication +```php +// Sanctum API token management +class PersonalAccessToken extends Model +{ + protected $fillable = [ + 'name', 'token', 'abilities', 'expires_at' + ]; + + protected $casts = [ + 'abilities' => 'array', + 'expires_at' => 'datetime', + 'last_used_at' => 'datetime', + ]; + + public function tokenable(): MorphTo + { + return $this->morphTo(); + } + + public function hasAbility(string $ability): bool + { + return in_array('*', $this->abilities) || + in_array($ability, $this->abilities); + } +} +``` + +### API Rate Limiting +```php +// Rate limiting configuration +RateLimiter::for('api', function (Request $request) { + return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); +}); + +RateLimiter::for('deployments', function (Request $request) { + return Limit::perMinute(10)->by($request->user()->id); +}); + +RateLimiter::for('webhooks', function (Request $request) { + return Limit::perMinute(100)->by($request->ip()); +}); +``` + +### API Input Validation +```php +// Comprehensive input validation +class StoreApplicationRequest extends FormRequest +{ + public function authorize(): bool + { + return $this->user()->can('create', Application::class); + } + + public function rules(): array + { + return [ + 'name' => 'required|string|max:255|regex:/^[a-zA-Z0-9\-_]+$/', + 'git_repository' => 'required|url|starts_with:https://', + 'git_branch' => 'required|string|max:100|regex:/^[a-zA-Z0-9\-_\/]+$/', + 'server_id' => 'required|exists:servers,id', + 'environment_id' => 'required|exists:environments,id', + 'environment_variables' => 'array', + 'environment_variables.*' => 'string|max:1000', + ]; + } + + public function prepareForValidation(): void + { + $this->merge([ + 'name' => strip_tags($this->name), + 'git_repository' => filter_var($this->git_repository, FILTER_SANITIZE_URL), + ]); + } +} +``` + +## SSH Security + +### Private Key Management +- **[PrivateKey.php](mdc:app/Models/PrivateKey.php)** - Secure SSH key storage (6.5KB, 247 lines) +- **Encrypted key storage** in database +- **Key rotation** capabilities +- **Access logging** for key usage + +### SSH Connection Security +```php +class SshConnection +{ + private string $host; + private int $port; + private string $username; + private PrivateKey $privateKey; + + public function __construct(Server $server) + { + $this->host = $server->ip; + $this->port = $server->port; + $this->username = $server->user; + $this->privateKey = $server->privateKey; + } + + public function connect(): bool + { + $connection = ssh2_connect($this->host, $this->port); + + if (!$connection) { + throw new SshConnectionException('Failed to connect to server'); + } + + // Use private key authentication + $privateKeyContent = decrypt($this->privateKey->private_key); + $publicKeyContent = decrypt($this->privateKey->public_key); + + if (!ssh2_auth_pubkey_file($connection, $this->username, $publicKeyContent, $privateKeyContent)) { + throw new SshAuthenticationException('SSH authentication failed'); + } + + return true; + } + + public function execute(string $command): string + { + // Sanitize command to prevent injection + $command = escapeshellcmd($command); + + $stream = ssh2_exec($this->connection, $command); + + if (!$stream) { + throw new SshExecutionException('Failed to execute command'); + } + + return stream_get_contents($stream); + } +} +``` + +## Container Security + +### Docker Security Patterns +```php +class DockerSecurityService +{ + public function createSecureContainer(Application $application): array + { + return [ + 'image' => $this->validateImageName($application->docker_image), + 'user' => '1000:1000', // Non-root user + 'read_only' => true, + 'no_new_privileges' => true, + 'security_opt' => [ + 'no-new-privileges:true', + 'apparmor:docker-default' + ], + 'cap_drop' => ['ALL'], + 'cap_add' => ['CHOWN', 'SETUID', 'SETGID'], // Minimal capabilities + 'tmpfs' => [ + '/tmp' => 'rw,noexec,nosuid,size=100m', + '/var/tmp' => 'rw,noexec,nosuid,size=50m' + ], + 'ulimits' => [ + 'nproc' => 1024, + 'nofile' => 1024 + ] + ]; + } + + private function validateImageName(string $image): string + { + // Validate image name against allowed registries + $allowedRegistries = ['docker.io', 'ghcr.io', 'quay.io']; + + $parser = new DockerImageParser(); + $parsed = $parser->parse($image); + + if (!in_array($parsed['registry'], $allowedRegistries)) { + throw new SecurityException('Image registry not allowed'); + } + + return $image; + } +} +``` + +### Network Isolation +```yaml +# Docker Compose security configuration +version: '3.8' +services: + app: + image: ${APP_IMAGE} + networks: + - app-network + security_opt: + - no-new-privileges:true + - apparmor:docker-default + read_only: true + tmpfs: + - /tmp:rw,noexec,nosuid,size=100m + cap_drop: + - ALL + cap_add: + - CHOWN + - SETUID + - SETGID + +networks: + app-network: + driver: bridge + internal: true + ipam: + config: + - subnet: 172.20.0.0/16 +``` + +## SSL/TLS Security + +### Certificate Management +- **[SslCertificate.php](mdc:app/Models/SslCertificate.php)** - SSL certificate automation +- **Let's Encrypt** integration for free certificates +- **Automatic renewal** and monitoring +- **Custom certificate** upload support + +### SSL Configuration +```php +class SslCertificateService +{ + public function generateCertificate(Application $application): SslCertificate + { + $domains = $this->validateDomains($application->getAllDomains()); + + $certificate = SslCertificate::create([ + 'application_id' => $application->id, + 'domains' => $domains, + 'provider' => 'letsencrypt', + 'status' => 'pending' + ]); + + // Generate certificate using ACME protocol + $acmeClient = new AcmeClient(); + $certData = $acmeClient->generateCertificate($domains); + + $certificate->update([ + 'certificate' => encrypt($certData['certificate']), + 'private_key' => encrypt($certData['private_key']), + 'chain' => encrypt($certData['chain']), + 'expires_at' => $certData['expires_at'], + 'status' => 'active' + ]); + + return $certificate; + } + + private function validateDomains(array $domains): array + { + foreach ($domains as $domain) { + if (!filter_var($domain, FILTER_VALIDATE_DOMAIN)) { + throw new InvalidDomainException("Invalid domain: {$domain}"); + } + + // Check domain ownership + if (!$this->verifyDomainOwnership($domain)) { + throw new DomainOwnershipException("Domain ownership verification failed: {$domain}"); + } + } + + return $domains; + } +} +``` + +## Environment Variable Security + +### Secure Configuration Management +```php +class EnvironmentVariable extends Model +{ + protected $fillable = [ + 'key', 'value', 'is_secret', 'application_id' + ]; + + protected $casts = [ + 'is_secret' => 'boolean', + 'value' => 'encrypted' // Automatic encryption for sensitive values + ]; + + public function setValueAttribute($value): void + { + // Automatically encrypt sensitive environment variables + if ($this->isSensitiveKey($this->key)) { + $this->attributes['value'] = encrypt($value); + $this->attributes['is_secret'] = true; + } else { + $this->attributes['value'] = $value; + } + } + + public function getValueAttribute($value): string + { + if ($this->is_secret) { + return decrypt($value); + } + + return $value; + } + + private function isSensitiveKey(string $key): bool + { + $sensitivePatterns = [ + 'PASSWORD', 'SECRET', 'KEY', 'TOKEN', 'API_KEY', + 'DATABASE_URL', 'REDIS_URL', 'PRIVATE', 'CREDENTIAL', + 'AUTH', 'CERTIFICATE', 'ENCRYPTION', 'SALT', 'HASH', + 'OAUTH', 'JWT', 'BEARER', 'ACCESS', 'REFRESH' + ]; + + foreach ($sensitivePatterns as $pattern) { + if (str_contains(strtoupper($key), $pattern)) { + return true; + } + } + + return false; + } +} +``` + +## Webhook Security + +### Webhook Signature Verification +```php +class WebhookSecurityService +{ + public function verifyGitHubSignature(Request $request, string $secret): bool + { + $signature = $request->header('X-Hub-Signature-256'); + + if (!$signature) { + return false; + } + + $expectedSignature = 'sha256=' . hash_hmac('sha256', $request->getContent(), $secret); + + return hash_equals($expectedSignature, $signature); + } + + public function verifyGitLabSignature(Request $request, string $secret): bool + { + $signature = $request->header('X-Gitlab-Token'); + + return hash_equals($secret, $signature); + } + + public function validateWebhookPayload(array $payload): array + { + // Sanitize and validate webhook payload + $validator = Validator::make($payload, [ + 'repository.clone_url' => 'required|url|starts_with:https://', + 'ref' => 'required|string|max:255', + 'head_commit.id' => 'required|string|size:40', // Git SHA + 'head_commit.message' => 'required|string|max:1000' + ]); + + if ($validator->fails()) { + throw new InvalidWebhookPayloadException('Invalid webhook payload'); + } + + return $validator->validated(); + } +} +``` + +## Input Sanitization & Validation + +### XSS Prevention +```php +class SecurityMiddleware +{ + public function handle(Request $request, Closure $next): Response + { + // Sanitize input data + $input = $request->all(); + $sanitized = $this->sanitizeInput($input); + $request->merge($sanitized); + + return $next($request); + } + + private function sanitizeInput(array $input): array + { + foreach ($input as $key => $value) { + if (is_string($value)) { + // Remove potentially dangerous HTML tags + $input[$key] = strip_tags($value, '


'); + + // Escape special characters + $input[$key] = htmlspecialchars($input[$key], ENT_QUOTES, 'UTF-8'); + } elseif (is_array($value)) { + $input[$key] = $this->sanitizeInput($value); + } + } + + return $input; + } +} +``` + +### SQL Injection Prevention +```php +// Always use parameterized queries and Eloquent ORM +class ApplicationRepository +{ + public function findByName(string $name): ?Application + { + // Safe: Uses parameter binding + return Application::where('name', $name)->first(); + } + + public function searchApplications(string $query): Collection + { + // Safe: Eloquent handles escaping + return Application::where('name', 'LIKE', "%{$query}%") + ->orWhere('description', 'LIKE', "%{$query}%") + ->get(); + } + + // NEVER do this - vulnerable to SQL injection + // public function unsafeSearch(string $query): Collection + // { + // return DB::select("SELECT * FROM applications WHERE name LIKE '%{$query}%'"); + // } +} +``` + +## Audit Logging & Monitoring + +### Activity Logging +```php +// Using Spatie Activity Log package +class Application extends Model +{ + use LogsActivity; + + protected static $logAttributes = [ + 'name', 'git_repository', 'git_branch', 'fqdn' + ]; + + protected static $logOnlyDirty = true; + + public function getDescriptionForEvent(string $eventName): string + { + return "Application {$this->name} was {$eventName}"; + } +} + +// Custom security events +class SecurityEventLogger +{ + public function logFailedLogin(string $email, string $ip): void + { + activity('security') + ->withProperties([ + 'email' => $email, + 'ip' => $ip, + 'user_agent' => request()->userAgent() + ]) + ->log('Failed login attempt'); + } + + public function logSuspiciousActivity(User $user, string $activity): void + { + activity('security') + ->causedBy($user) + ->withProperties([ + 'activity' => $activity, + 'ip' => request()->ip(), + 'timestamp' => now() + ]) + ->log('Suspicious activity detected'); + } +} +``` + +### Security Monitoring +```php +class SecurityMonitoringService +{ + public function detectAnomalousActivity(User $user): bool + { + // Check for unusual login patterns + $recentLogins = $user->activities() + ->where('description', 'like', '%login%') + ->where('created_at', '>=', now()->subHours(24)) + ->get(); + + // Multiple failed attempts + $failedAttempts = $recentLogins->where('description', 'Failed login attempt')->count(); + if ($failedAttempts > 5) { + $this->triggerSecurityAlert($user, 'Multiple failed login attempts'); + return true; + } + + // Login from new location + $uniqueIps = $recentLogins->pluck('properties.ip')->unique(); + if ($uniqueIps->count() > 3) { + $this->triggerSecurityAlert($user, 'Login from multiple IP addresses'); + return true; + } + + return false; + } + + private function triggerSecurityAlert(User $user, string $reason): void + { + // Send security notification + $user->notify(new SecurityAlertNotification($reason)); + + // Log security event + activity('security') + ->causedBy($user) + ->withProperties(['reason' => $reason]) + ->log('Security alert triggered'); + } +} +``` + +## Backup Security + +### Encrypted Backups +```php +class SecureBackupService +{ + public function createEncryptedBackup(ScheduledDatabaseBackup $backup): void + { + $database = $backup->database; + $dumpPath = $this->createDatabaseDump($database); + + // Encrypt backup file + $encryptedPath = $this->encryptFile($dumpPath, $backup->encryption_key); + + // Upload to secure storage + $this->uploadToSecureStorage($encryptedPath, $backup->s3Storage); + + // Clean up local files + unlink($dumpPath); + unlink($encryptedPath); + } + + private function encryptFile(string $filePath, string $key): string + { + $data = file_get_contents($filePath); + $encryptedData = encrypt($data, $key); + + $encryptedPath = $filePath . '.encrypted'; + file_put_contents($encryptedPath, $encryptedData); + + return $encryptedPath; + } +} +``` + +## Security Headers & CORS + +### Security Headers Configuration +```php +// Security headers middleware +class SecurityHeadersMiddleware +{ + public function handle(Request $request, Closure $next): Response + { + $response = $next($request); + + $response->headers->set('X-Content-Type-Options', 'nosniff'); + $response->headers->set('X-Frame-Options', 'DENY'); + $response->headers->set('X-XSS-Protection', '1; mode=block'); + $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin'); + $response->headers->set('Permissions-Policy', 'geolocation=(), microphone=(), camera=()'); + + if ($request->secure()) { + $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); + } + + return $response; + } +} +``` + +### CORS Configuration +```php +// CORS configuration for API endpoints +return [ + 'paths' => ['api/*', 'webhooks/*'], + 'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], + 'allowed_origins' => [ + 'https://app.coolify.io', + 'https://*.coolify.io' + ], + 'allowed_origins_patterns' => [], + 'allowed_headers' => ['*'], + 'exposed_headers' => [], + 'max_age' => 0, + 'supports_credentials' => true, +]; +``` + +## Security Testing + +### Security Test Patterns +```php +// Security-focused tests +test('prevents SQL injection in search', function () { + $user = User::factory()->create(); + $maliciousInput = "'; DROP TABLE applications; --"; + + $response = $this->actingAs($user) + ->getJson("/api/v1/applications?search={$maliciousInput}"); + + $response->assertStatus(200); + + // Verify applications table still exists + expect(Schema::hasTable('applications'))->toBeTrue(); +}); + +test('prevents XSS in application names', function () { + $user = User::factory()->create(); + $xssPayload = ''; + + $response = $this->actingAs($user) + ->postJson('/api/v1/applications', [ + 'name' => $xssPayload, + 'git_repository' => 'https://github.com/user/repo.git', + 'server_id' => Server::factory()->create()->id + ]); + + $response->assertStatus(422); +}); + +test('enforces team isolation', function () { + $user1 = User::factory()->create(); + $user2 = User::factory()->create(); + + $team1 = Team::factory()->create(); + $team2 = Team::factory()->create(); + + $user1->teams()->attach($team1); + $user2->teams()->attach($team2); + + $application = Application::factory()->create(['team_id' => $team1->id]); + + $response = $this->actingAs($user2) + ->getJson("/api/v1/applications/{$application->id}"); + + $response->assertStatus(403); +}); +``` diff --git a/.cursor/rules/self_improve.mdc b/.cursor/rules/self_improve.mdc new file mode 100644 index 000000000..40b31b6ea --- /dev/null +++ b/.cursor/rules/self_improve.mdc @@ -0,0 +1,72 @@ +--- +description: Guidelines for continuously improving Cursor rules based on emerging code patterns and best practices. +globs: **/* +alwaysApply: true +--- + +- **Rule Improvement Triggers:** + - New code patterns not covered by existing rules + - Repeated similar implementations across files + - Common error patterns that could be prevented + - New libraries or tools being used consistently + - Emerging best practices in the codebase + +- **Analysis Process:** + - Compare new code with existing rules + - Identify patterns that should be standardized + - Look for references to external documentation + - Check for consistent error handling patterns + - Monitor test patterns and coverage + +- **Rule Updates:** + - **Add New Rules When:** + - A new technology/pattern is used in 3+ files + - Common bugs could be prevented by a rule + - Code reviews repeatedly mention the same feedback + - New security or performance patterns emerge + + - **Modify Existing Rules When:** + - Better examples exist in the codebase + - Additional edge cases are discovered + - Related rules have been updated + - Implementation details have changed + +- **Example Pattern Recognition:** + ```typescript + // If you see repeated patterns like: + const data = await prisma.user.findMany({ + select: { id: true, email: true }, + where: { status: 'ACTIVE' } + }); + + // Consider adding to [prisma.mdc](mdc:.cursor/rules/prisma.mdc): + // - Standard select fields + // - Common where conditions + // - Performance optimization patterns + ``` + +- **Rule Quality Checks:** + - Rules should be actionable and specific + - Examples should come from actual code + - References should be up to date + - Patterns should be consistently enforced + +- **Continuous Improvement:** + - Monitor code review comments + - Track common development questions + - Update rules after major refactors + - Add links to relevant documentation + - Cross-reference related rules + +- **Rule Deprecation:** + - Mark outdated patterns as deprecated + - Remove rules that no longer apply + - Update references to deprecated rules + - Document migration paths for old patterns + +- **Documentation Updates:** + - Keep examples synchronized with code + - Update references to external docs + - Maintain links between related rules + - Document breaking changes +Follow [cursor_rules.mdc](mdc:.cursor/rules/cursor_rules.mdc) for proper rule formatting and structure. diff --git a/.cursor/rules/technology-stack.mdc b/.cursor/rules/technology-stack.mdc new file mode 100644 index 000000000..1e894720c --- /dev/null +++ b/.cursor/rules/technology-stack.mdc @@ -0,0 +1,250 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify Technology Stack + +## Backend Framework + +### **Laravel 12.4.1** (PHP Framework) +- **Location**: [composer.json](mdc:composer.json) +- **Purpose**: Core application framework +- **Key Features**: + - Eloquent ORM for database interactions + - Artisan CLI for development tasks + - Queue system for background jobs + - Event-driven architecture + +### **PHP 8.4** +- **Requirement**: `^8.4` in [composer.json](mdc:composer.json) +- **Features Used**: + - Typed properties and return types + - Attributes for validation and configuration + - Match expressions + - Constructor property promotion + +## Frontend Stack + +### **Livewire 3.5.20** (Primary Frontend Framework) +- **Purpose**: Server-side rendering with reactive components +- **Location**: [app/Livewire/](mdc:app/Livewire/) +- **Key Components**: + - [Dashboard.php](mdc:app/Livewire/Dashboard.php) - Main interface + - [ActivityMonitor.php](mdc:app/Livewire/ActivityMonitor.php) - Real-time monitoring + - [MonacoEditor.php](mdc:app/Livewire/MonacoEditor.php) - Code editor + +### **Alpine.js** (Client-Side Interactivity) +- **Purpose**: Lightweight JavaScript for DOM manipulation +- **Integration**: Works seamlessly with Livewire components +- **Usage**: Declarative directives in Blade templates + +### **Tailwind CSS 4.1.4** (Styling Framework) +- **Location**: [package.json](mdc:package.json) +- **Configuration**: [postcss.config.cjs](mdc:postcss.config.cjs) +- **Extensions**: + - `@tailwindcss/forms` - Form styling + - `@tailwindcss/typography` - Content typography + - `tailwind-scrollbar` - Custom scrollbars + +### **Vue.js 3.5.13** (Component Framework) +- **Purpose**: Enhanced interactive components +- **Integration**: Used alongside Livewire for complex UI +- **Build Tool**: Vite with Vue plugin + +## Database & Caching + +### **PostgreSQL 15** (Primary Database) +- **Purpose**: Main application data storage +- **Features**: JSONB support, advanced indexing +- **Models**: [app/Models/](mdc:app/Models/) + +### **Redis 7** (Caching & Real-time) +- **Purpose**: + - Session storage + - Queue backend + - Real-time data caching + - WebSocket session management + +### **Supported Databases** (For User Applications) +- **PostgreSQL**: [StandalonePostgresql.php](mdc:app/Models/StandalonePostgresql.php) +- **MySQL**: [StandaloneMysql.php](mdc:app/Models/StandaloneMysql.php) +- **MariaDB**: [StandaloneMariadb.php](mdc:app/Models/StandaloneMariadb.php) +- **MongoDB**: [StandaloneMongodb.php](mdc:app/Models/StandaloneMongodb.php) +- **Redis**: [StandaloneRedis.php](mdc:app/Models/StandaloneRedis.php) +- **KeyDB**: [StandaloneKeydb.php](mdc:app/Models/StandaloneKeydb.php) +- **Dragonfly**: [StandaloneDragonfly.php](mdc:app/Models/StandaloneDragonfly.php) +- **ClickHouse**: [StandaloneClickhouse.php](mdc:app/Models/StandaloneClickhouse.php) + +## Authentication & Security + +### **Laravel Sanctum 4.0.8** +- **Purpose**: API token authentication +- **Usage**: Secure API access for external integrations + +### **Laravel Fortify 1.25.4** +- **Purpose**: Authentication scaffolding +- **Features**: Login, registration, password reset + +### **Laravel Socialite 5.18.0** +- **Purpose**: OAuth provider integration +- **Providers**: + - GitHub, GitLab, Google + - Microsoft Azure, Authentik + - Custom OAuth implementations + +## Background Processing + +### **Laravel Horizon 5.30.3** +- **Purpose**: Queue monitoring and management +- **Features**: Real-time queue metrics, failed job handling + +### **Queue System** +- **Backend**: Redis-based queues +- **Jobs**: [app/Jobs/](mdc:app/Jobs/) +- **Processing**: Background deployment and monitoring tasks + +## Development Tools + +### **Build Tools** +- **Vite 6.2.6**: Modern build tool and dev server +- **Laravel Vite Plugin**: Laravel integration +- **PostCSS**: CSS processing pipeline + +### **Code Quality** +- **Laravel Pint**: PHP code style fixer +- **Rector**: PHP automated refactoring +- **PHPStan**: Static analysis tool + +### **Testing Framework** +- **Pest 3.8.0**: Modern PHP testing framework +- **Laravel Dusk**: Browser automation testing +- **PHPUnit**: Unit testing foundation + +## External Integrations + +### **Git Providers** +- **GitHub**: Repository integration and webhooks +- **GitLab**: Self-hosted and cloud GitLab support +- **Bitbucket**: Atlassian integration +- **Gitea**: Self-hosted Git service + +### **Cloud Storage** +- **AWS S3**: [league/flysystem-aws-s3-v3](mdc:composer.json) +- **SFTP**: [league/flysystem-sftp-v3](mdc:composer.json) +- **Local Storage**: File system integration + +### **Notification Services** +- **Email**: [resend/resend-laravel](mdc:composer.json) +- **Discord**: Custom webhook integration +- **Slack**: Webhook notifications +- **Telegram**: Bot API integration +- **Pushover**: Push notifications + +### **Monitoring & Logging** +- **Sentry**: [sentry/sentry-laravel](mdc:composer.json) - Error tracking +- **Laravel Ray**: [spatie/laravel-ray](mdc:composer.json) - Debug tool +- **Activity Log**: [spatie/laravel-activitylog](mdc:composer.json) + +## DevOps & Infrastructure + +### **Docker & Containerization** +- **Docker**: Container runtime +- **Docker Compose**: Multi-container orchestration +- **Docker Swarm**: Container clustering (optional) + +### **Web Servers & Proxies** +- **Nginx**: Primary web server +- **Traefik**: Reverse proxy and load balancer +- **Caddy**: Alternative reverse proxy + +### **Process Management** +- **S6 Overlay**: Process supervisor +- **Supervisor**: Alternative process manager + +### **SSL/TLS** +- **Let's Encrypt**: Automatic SSL certificates +- **Custom Certificates**: Manual SSL management + +## Terminal & Code Editing + +### **XTerm.js 5.5.0** +- **Purpose**: Web-based terminal emulator +- **Features**: SSH session management, real-time command execution +- **Addons**: Fit addon for responsive terminals + +### **Monaco Editor** +- **Purpose**: Code editor component +- **Features**: Syntax highlighting, auto-completion +- **Integration**: Environment variable editing, configuration files + +## API & Documentation + +### **OpenAPI/Swagger** +- **Documentation**: [openapi.json](mdc:openapi.json) (373KB) +- **Generator**: [zircote/swagger-php](mdc:composer.json) +- **API Routes**: [routes/api.php](mdc:routes/api.php) + +### **WebSocket Communication** +- **Laravel Echo**: Real-time event broadcasting +- **Pusher**: WebSocket service integration +- **Soketi**: Self-hosted WebSocket server + +## Package Management + +### **PHP Dependencies** ([composer.json](mdc:composer.json)) +```json +{ + "require": { + "php": "^8.4", + "laravel/framework": "12.4.1", + "livewire/livewire": "^3.5.20", + "spatie/laravel-data": "^4.13.1", + "lorisleiva/laravel-actions": "^2.8.6" + } +} +``` + +### **JavaScript Dependencies** ([package.json](mdc:package.json)) +```json +{ + "devDependencies": { + "vite": "^6.2.6", + "tailwindcss": "^4.1.4", + "@vitejs/plugin-vue": "5.2.3" + }, + "dependencies": { + "@xterm/xterm": "^5.5.0", + "ioredis": "5.6.0" + } +} +``` + +## Configuration Files + +### **Build Configuration** +- **[vite.config.js](mdc:vite.config.js)**: Frontend build setup +- **[postcss.config.cjs](mdc:postcss.config.cjs)**: CSS processing +- **[rector.php](mdc:rector.php)**: PHP refactoring rules +- **[pint.json](mdc:pint.json)**: Code style configuration + +### **Testing Configuration** +- **[phpunit.xml](mdc:phpunit.xml)**: Unit test configuration +- **[phpunit.dusk.xml](mdc:phpunit.dusk.xml)**: Browser test configuration +- **[tests/Pest.php](mdc:tests/Pest.php)**: Pest testing setup + +## Version Requirements + +### **Minimum Requirements** +- **PHP**: 8.4+ +- **Node.js**: 18+ (for build tools) +- **PostgreSQL**: 15+ +- **Redis**: 7+ +- **Docker**: 20.10+ +- **Docker Compose**: 2.0+ + +### **Recommended Versions** +- **Ubuntu**: 22.04 LTS or 24.04 LTS +- **Memory**: 2GB+ RAM +- **Storage**: 20GB+ available space +- **Network**: Stable internet connection for deployments diff --git a/.cursor/rules/testing-patterns.mdc b/.cursor/rules/testing-patterns.mdc new file mode 100644 index 000000000..c3eabe09f --- /dev/null +++ b/.cursor/rules/testing-patterns.mdc @@ -0,0 +1,606 @@ +--- +description: +globs: +alwaysApply: false +--- +# Coolify Testing Architecture & Patterns + +## Testing Philosophy + +Coolify employs **comprehensive testing strategies** using modern PHP testing frameworks to ensure reliability of deployment operations, infrastructure management, and user interactions. + +## Testing Framework Stack + +### Core Testing Tools +- **Pest PHP 3.8+** - Primary testing framework with expressive syntax +- **Laravel Dusk** - Browser automation and end-to-end testing +- **PHPUnit** - Underlying unit testing framework +- **Mockery** - Mocking and stubbing for isolated tests + +### Testing Configuration +- **[tests/Pest.php](mdc:tests/Pest.php)** - Pest configuration and global setup (1.5KB, 45 lines) +- **[tests/TestCase.php](mdc:tests/TestCase.php)** - Base test case class (163B, 11 lines) +- **[tests/CreatesApplication.php](mdc:tests/CreatesApplication.php)** - Application factory trait (375B, 22 lines) +- **[tests/DuskTestCase.php](mdc:tests/DuskTestCase.php)** - Browser testing setup (1.4KB, 58 lines) + +## Test Directory Structure + +### Test Organization +- **[tests/Feature/](mdc:tests/Feature)** - Feature and integration tests +- **[tests/Unit/](mdc:tests/Unit)** - Unit tests for isolated components +- **[tests/Browser/](mdc:tests/Browser)** - Laravel Dusk browser tests +- **[tests/Traits/](mdc:tests/Traits)** - Shared testing utilities + +## Unit Testing Patterns + +### Model Testing +```php +// Testing Eloquent models +test('application model has correct relationships', function () { + $application = Application::factory()->create(); + + expect($application->server)->toBeInstanceOf(Server::class); + expect($application->environment)->toBeInstanceOf(Environment::class); + expect($application->deployments)->toBeInstanceOf(Collection::class); +}); + +test('application can generate deployment configuration', function () { + $application = Application::factory()->create([ + 'name' => 'test-app', + 'git_repository' => 'https://github.com/user/repo.git' + ]); + + $config = $application->generateDockerCompose(); + + expect($config)->toContain('test-app'); + expect($config)->toContain('image:'); + expect($config)->toContain('networks:'); +}); +``` + +### Service Layer Testing +```php +// Testing service classes +test('configuration generator creates valid docker compose', function () { + $generator = new ConfigurationGenerator(); + $application = Application::factory()->create(); + + $compose = $generator->generateDockerCompose($application); + + expect($compose)->toBeString(); + expect(yaml_parse($compose))->toBeArray(); + expect($compose)->toContain('version: "3.8"'); +}); + +test('docker image parser validates image names', function () { + $parser = new DockerImageParser(); + + expect($parser->isValid('nginx:latest'))->toBeTrue(); + expect($parser->isValid('invalid-image-name'))->toBeFalse(); + expect($parser->parse('nginx:1.21'))->toEqual([ + 'registry' => 'docker.io', + 'namespace' => 'library', + 'repository' => 'nginx', + 'tag' => '1.21' + ]); +}); +``` + +### Action Testing +```php +// Testing Laravel Actions +test('deploy application action creates deployment queue', function () { + $application = Application::factory()->create(); + $action = new DeployApplicationAction(); + + $deployment = $action->handle($application); + + expect($deployment)->toBeInstanceOf(ApplicationDeploymentQueue::class); + expect($deployment->status)->toBe('queued'); + expect($deployment->application_id)->toBe($application->id); +}); + +test('server validation action checks ssh connectivity', function () { + $server = Server::factory()->create([ + 'ip' => '192.168.1.100', + 'port' => 22 + ]); + + $action = new ValidateServerAction(); + + // Mock SSH connection + $this->mock(SshConnection::class, function ($mock) { + $mock->shouldReceive('connect')->andReturn(true); + $mock->shouldReceive('execute')->with('docker --version')->andReturn('Docker version 20.10.0'); + }); + + $result = $action->handle($server); + + expect($result['ssh_connection'])->toBeTrue(); + expect($result['docker_installed'])->toBeTrue(); +}); +``` + +## Feature Testing Patterns + +### API Testing +```php +// Testing API endpoints +test('authenticated user can list applications', function () { + $user = User::factory()->create(); + $team = Team::factory()->create(); + $user->teams()->attach($team); + + $applications = Application::factory(3)->create([ + 'team_id' => $team->id + ]); + + $response = $this->actingAs($user) + ->getJson('/api/v1/applications'); + + $response->assertStatus(200) + ->assertJsonCount(3, 'data') + ->assertJsonStructure([ + 'data' => [ + '*' => ['id', 'name', 'fqdn', 'status', 'created_at'] + ] + ]); +}); + +test('user cannot access applications from other teams', function () { + $user = User::factory()->create(); + $otherTeam = Team::factory()->create(); + + $application = Application::factory()->create([ + 'team_id' => $otherTeam->id + ]); + + $response = $this->actingAs($user) + ->getJson("/api/v1/applications/{$application->id}"); + + $response->assertStatus(403); +}); +``` + +### Deployment Testing +```php +// Testing deployment workflows +test('application deployment creates docker containers', function () { + $application = Application::factory()->create([ + 'git_repository' => 'https://github.com/laravel/laravel.git', + 'git_branch' => 'main' + ]); + + // Mock Docker operations + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andReturn('app:latest'); + $mock->shouldReceive('createContainer')->andReturn('container_id'); + $mock->shouldReceive('startContainer')->andReturn(true); + }); + + $deployment = $application->deploy(); + + expect($deployment->status)->toBe('queued'); + + // Process the deployment job + $this->artisan('queue:work --once'); + + $deployment->refresh(); + expect($deployment->status)->toBe('success'); +}); + +test('failed deployment triggers rollback', function () { + $application = Application::factory()->create(); + + // Mock failed deployment + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andThrow(new DeploymentException('Build failed')); + }); + + $deployment = $application->deploy(); + + $this->artisan('queue:work --once'); + + $deployment->refresh(); + expect($deployment->status)->toBe('failed'); + expect($deployment->error_message)->toContain('Build failed'); +}); +``` + +### Webhook Testing +```php +// Testing webhook endpoints +test('github webhook triggers deployment', function () { + $application = Application::factory()->create([ + 'git_repository' => 'https://github.com/user/repo.git', + 'git_branch' => 'main' + ]); + + $payload = [ + 'ref' => 'refs/heads/main', + 'repository' => [ + 'clone_url' => 'https://github.com/user/repo.git' + ], + 'head_commit' => [ + 'id' => 'abc123', + 'message' => 'Update application' + ] + ]; + + $response = $this->postJson("/webhooks/github/{$application->id}", $payload); + + $response->assertStatus(200); + + expect($application->deployments()->count())->toBe(1); + expect($application->deployments()->first()->commit_sha)->toBe('abc123'); +}); + +test('webhook validates payload signature', function () { + $application = Application::factory()->create(); + + $payload = ['invalid' => 'payload']; + + $response = $this->postJson("/webhooks/github/{$application->id}", $payload); + + $response->assertStatus(400); +}); +``` + +## Browser Testing (Laravel Dusk) + +### End-to-End Testing +```php +// Testing complete user workflows +test('user can create and deploy application', function () { + $user = User::factory()->create(); + $server = Server::factory()->create(['team_id' => $user->currentTeam->id]); + + $this->browse(function (Browser $browser) use ($user, $server) { + $browser->loginAs($user) + ->visit('/applications/create') + ->type('name', 'Test Application') + ->type('git_repository', 'https://github.com/laravel/laravel.git') + ->type('git_branch', 'main') + ->select('server_id', $server->id) + ->press('Create Application') + ->assertPathIs('/applications/*') + ->assertSee('Test Application') + ->press('Deploy') + ->waitForText('Deployment started', 10) + ->assertSee('Deployment started'); + }); +}); + +test('user can monitor deployment logs in real-time', function () { + $user = User::factory()->create(); + $application = Application::factory()->create(['team_id' => $user->currentTeam->id]); + + $this->browse(function (Browser $browser) use ($user, $application) { + $browser->loginAs($user) + ->visit("/applications/{$application->id}") + ->press('Deploy') + ->waitForText('Deployment started') + ->click('@logs-tab') + ->waitFor('@deployment-logs') + ->assertSee('Building Docker image') + ->waitForText('Deployment completed', 30); + }); +}); +``` + +### UI Component Testing +```php +// Testing Livewire components +test('server status component updates in real-time', function () { + $user = User::factory()->create(); + $server = Server::factory()->create(['team_id' => $user->currentTeam->id]); + + $this->browse(function (Browser $browser) use ($user, $server) { + $browser->loginAs($user) + ->visit("/servers/{$server->id}") + ->assertSee('Status: Online') + ->waitFor('@server-metrics') + ->assertSee('CPU Usage') + ->assertSee('Memory Usage') + ->assertSee('Disk Usage'); + + // Simulate server going offline + $server->update(['status' => 'offline']); + + $browser->waitForText('Status: Offline', 5) + ->assertSee('Status: Offline'); + }); +}); +``` + +## Database Testing Patterns + +### Migration Testing +```php +// Testing database migrations +test('applications table has correct structure', function () { + expect(Schema::hasTable('applications'))->toBeTrue(); + expect(Schema::hasColumns('applications', [ + 'id', 'name', 'fqdn', 'git_repository', 'git_branch', + 'server_id', 'environment_id', 'created_at', 'updated_at' + ]))->toBeTrue(); +}); + +test('foreign key constraints are properly set', function () { + $application = Application::factory()->create(); + + expect($application->server)->toBeInstanceOf(Server::class); + expect($application->environment)->toBeInstanceOf(Environment::class); + + // Test cascade deletion + $application->server->delete(); + expect(Application::find($application->id))->toBeNull(); +}); +``` + +### Factory Testing +```php +// Testing model factories +test('application factory creates valid models', function () { + $application = Application::factory()->create(); + + expect($application->name)->toBeString(); + expect($application->git_repository)->toStartWith('https://'); + expect($application->server_id)->toBeInt(); + expect($application->environment_id)->toBeInt(); +}); + +test('application factory can create with custom attributes', function () { + $application = Application::factory()->create([ + 'name' => 'Custom App', + 'git_branch' => 'develop' + ]); + + expect($application->name)->toBe('Custom App'); + expect($application->git_branch)->toBe('develop'); +}); +``` + +## Queue Testing + +### Job Testing +```php +// Testing background jobs +test('deploy application job processes successfully', function () { + $application = Application::factory()->create(); + $deployment = ApplicationDeploymentQueue::factory()->create([ + 'application_id' => $application->id, + 'status' => 'queued' + ]); + + $job = new DeployApplicationJob($deployment); + + // Mock external dependencies + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andReturn('app:latest'); + $mock->shouldReceive('deployContainer')->andReturn(true); + }); + + $job->handle(); + + $deployment->refresh(); + expect($deployment->status)->toBe('success'); +}); + +test('failed job is retried with exponential backoff', function () { + $application = Application::factory()->create(); + $deployment = ApplicationDeploymentQueue::factory()->create([ + 'application_id' => $application->id + ]); + + $job = new DeployApplicationJob($deployment); + + // Mock failure + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andThrow(new Exception('Network error')); + }); + + expect(fn() => $job->handle())->toThrow(Exception::class); + + // Job should be retried + expect($job->tries)->toBe(3); + expect($job->backoff())->toBe([1, 5, 10]); +}); +``` + +## Security Testing + +### Authentication Testing +```php +// Testing authentication and authorization +test('unauthenticated users cannot access protected routes', function () { + $response = $this->get('/dashboard'); + $response->assertRedirect('/login'); +}); + +test('users can only access their team resources', function () { + $user1 = User::factory()->create(); + $user2 = User::factory()->create(); + + $team1 = Team::factory()->create(); + $team2 = Team::factory()->create(); + + $user1->teams()->attach($team1); + $user2->teams()->attach($team2); + + $application = Application::factory()->create(['team_id' => $team1->id]); + + $response = $this->actingAs($user2) + ->get("/applications/{$application->id}"); + + $response->assertStatus(403); +}); +``` + +### Input Validation Testing +```php +// Testing input validation and sanitization +test('application creation validates required fields', function () { + $user = User::factory()->create(); + + $response = $this->actingAs($user) + ->postJson('/api/v1/applications', []); + + $response->assertStatus(422) + ->assertJsonValidationErrors(['name', 'git_repository', 'server_id']); +}); + +test('malicious input is properly sanitized', function () { + $user = User::factory()->create(); + + $response = $this->actingAs($user) + ->postJson('/api/v1/applications', [ + 'name' => '', + 'git_repository' => 'javascript:alert("xss")', + 'server_id' => 'invalid' + ]); + + $response->assertStatus(422); +}); +``` + +## Performance Testing + +### Load Testing +```php +// Testing application performance under load +test('application list endpoint handles concurrent requests', function () { + $user = User::factory()->create(); + $applications = Application::factory(100)->create(['team_id' => $user->currentTeam->id]); + + $startTime = microtime(true); + + $response = $this->actingAs($user) + ->getJson('/api/v1/applications'); + + $endTime = microtime(true); + $responseTime = ($endTime - $startTime) * 1000; // Convert to milliseconds + + $response->assertStatus(200); + expect($responseTime)->toBeLessThan(500); // Should respond within 500ms +}); +``` + +### Memory Usage Testing +```php +// Testing memory efficiency +test('deployment process does not exceed memory limits', function () { + $initialMemory = memory_get_usage(); + + $application = Application::factory()->create(); + $deployment = $application->deploy(); + + // Process deployment + $this->artisan('queue:work --once'); + + $finalMemory = memory_get_usage(); + $memoryIncrease = $finalMemory - $initialMemory; + + expect($memoryIncrease)->toBeLessThan(50 * 1024 * 1024); // Less than 50MB +}); +``` + +## Test Utilities and Helpers + +### Custom Assertions +```php +// Custom test assertions +expect()->extend('toBeValidDockerCompose', function () { + $yaml = yaml_parse($this->value); + + return $yaml !== false && + isset($yaml['version']) && + isset($yaml['services']) && + is_array($yaml['services']); +}); + +expect()->extend('toHaveValidSshConnection', function () { + $server = $this->value; + + try { + $connection = new SshConnection($server); + return $connection->test(); + } catch (Exception $e) { + return false; + } +}); +``` + +### Test Traits +```php +// Shared testing functionality +trait CreatesTestServers +{ + protected function createTestServer(array $attributes = []): Server + { + return Server::factory()->create(array_merge([ + 'name' => 'Test Server', + 'ip' => '127.0.0.1', + 'port' => 22, + 'team_id' => $this->user->currentTeam->id + ], $attributes)); + } +} + +trait MocksDockerOperations +{ + protected function mockDockerService(): void + { + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andReturn('test:latest'); + $mock->shouldReceive('createContainer')->andReturn('container_123'); + $mock->shouldReceive('startContainer')->andReturn(true); + $mock->shouldReceive('stopContainer')->andReturn(true); + }); + } +} +``` + +## Continuous Integration Testing + +### GitHub Actions Integration +```yaml +# .github/workflows/tests.yml +name: Tests +on: [push, pull_request] +jobs: + test: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:15 + env: + POSTGRES_PASSWORD: password + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - uses: actions/checkout@v3 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.4 + - name: Install dependencies + run: composer install + - name: Run tests + run: ./vendor/bin/pest +``` + +### Test Coverage +```php +// Generate test coverage reports +test('application has adequate test coverage', function () { + $coverage = $this->getCoverageData(); + + expect($coverage['application'])->toBeGreaterThan(80); + expect($coverage['models'])->toBeGreaterThan(90); + expect($coverage['actions'])->toBeGreaterThan(85); +}); +``` diff --git a/.gitignore b/.gitignore index 541c8e920..65b7faa1b 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,4 @@ scripts/load-test/* .env.dusk.local docker/coolify-realtime/node_modules .DS_Store -Changelog.md +CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index b508df1f7..a3576438e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,18 +2,324 @@ All notable changes to this project will be documented in this file. -## [unreleased] +## [4.0.0-beta.419] - 2025-06-16 + +### ๐Ÿš€ Features + +- *(core)* Add 'postmarketos' to supported OS list +- *(service)* Add memos service template (#5032) +- *(ui)* Upgrade to Tailwind v4 (#5710) +- *(service)* Add Navidrome service template (#5022) +- *(service)* Add Passbolt service (#5769) +- *(service)* Add Vert service (#5663) +- *(service)* Add Ryot service (#5232) +- *(service)* Add Marimo service (#5559) +- *(service)* Add Diun service (#5113) +- *(service)* Add Observium service (#5613) +- *(service)* Add Leantime service (#5792) +- *(service)* Add Limesurvey service (#5751) +- *(service)* Add Paymenter service (#5809) +- *(service)* Add CodiMD service (#4867) +- *(modal)* Add dispatchAction property to confirmation modal +- *(security)* Implement server patching functionality +- *(service)* Add Typesense service (#5643) +- *(service)* Add Yamtrack service (#5845) +- *(service)* Add PG Back Web service (#5079) +- *(service)* Update Maybe service and adjust it for the new release (#5795) +- *(oauth)* Set redirect uri as optional and add default value (#5760) +- *(service)* Add apache superset service (#4891) +- *(service)* Add One Time Secret service (#5650) +- *(service)* Add Seafile service (#5817) +- *(service)* Add Netbird-Client service (#5873) +- *(service)* Add OrangeHRM and Grist services (#5212) +- *(rules)* Add comprehensive documentation for Coolify architecture and development practices for AI tools, especially for cursor +- *(server)* Implement server patch check notifications +- *(api)* Add latest query param to Service restart API (#5881) +- *(api)* Add connect_to_docker_network setting to App creation API (#5691) +- *(routes)* Restrict backup download access to team admins and owners +- *(destination)* Update confirmation modal text and add persistent storage warning for server deployment +- *(terminal-access)* Implement terminal access control for servers and containers, including UI updates and backend logic +- *(ca-certificate)* Add CA certificate management functionality with UI integration and routing +- *(security-patches)* Add update check initialization and enhance notification messaging in UI +- *(previews)* Add force deploy without cache functionality and update deploy method to accept force rebuild parameter +- *(security-patterns)* Expand sensitive patterns list to include additional security-related variables +- *(database-backup)* Add MongoDB credential extraction and backup handling to DatabaseBackupJob +- *(activity-monitor)* Implement auto-scrolling functionality and dynamic content observation for improved user experience +- *(utf8-handling)* Implement UTF-8 sanitization for command outputs and enhance error handling in logs processing +- *(navbar)* Add Traefik dashboard availability check and server IP handling; refactor dynamic configurations loading +- *(proxy-dashboard)* Implement ProxyDashboardCacheService to manage Traefik dashboard cache; clear cache on configuration changes and proxy actions +- *(terminal-connection)* Enhance terminal connection handling with auto-connect feature and improved status messaging +- *(terminal)* Implement resize handling with ResizeObserver for improved terminal responsiveness + +### ๐Ÿ› Bug Fixes + +- *(constants)* Adding 'fedora-asahi-remix' as a supported OS (#5646) +- *(authentik)* Update docker-compose configuration for authentik service +- *(api)* Allow nullable destination_uuid (#5683) +- *(service)* Fix documenso startup and mail (#5737) +- *(docker)* Fix production dockerfile +- *(service)* Navidrome service +- *(service)* Passbolt +- *(service)* Add missing ENVs to NTFY service (#5629) +- *(service)* NTFY is behind a proxy +- *(service)* Vert logo and ENVs +- *(service)* Add platform to Observium service +- *(ActivityMonitor)* Prevent multiple event dispatches during polling +- *(service)* Convex ENVs and update image versions (#5827) +- *(service)* Paymenter +- *(ApplicationDeploymentJob)* Ensure correct COOLIFY_FQDN/COOLIFY_URL values (#4719) +- *(service)* Snapdrop no matching manifest error (#5849) +- *(service)* Use the same volume between chatwoot and sidekiq (#5851) +- *(api)* Validate docker_compose_raw input in ApplicationsController +- *(api)* Enhance validation for docker_compose_raw in ApplicationsController +- *(select)* Update PostgreSQL versions and titles in resource selection +- *(database)* Include DatabaseStatusChanged event in activityMonitor dispatch +- *(css)* Tailwind v5 things +- *(service)* Diun ENV for consistency +- *(service)* Memos service name +- *(css)* 8+ issue with new tailwind v4 +- *(css)* `bg-coollabs-gradient` not working anymore +- *(ui)* Add back missing service navbar components +- *(deploy)* Update resource timestamp handling in deploy_resource method +- *(patches)* DNF reboot logic is flipped +- *(deployment)* Correct syntax for else statement in docker compose build command +- *(shared)* Remove unused relation from queryDatabaseByUuidWithinTeam function +- *(deployment)* Correct COOLIFY_URL and COOLIFY_FQDN assignments based on parsing version in preview deployments +- *(docker)* Ensure correct parsing of environment variables by limiting explode to 2 parts +- *(project)* Update selected environment handling to use environment name instead of UUID +- *(ui)* Update server status display and improve server addition layout +- *(service)* Neon WS Proxy service not working on ARM64 (#5887) +- *(server)* Enhance error handling in server patch check notifications +- *(PushServerUpdateJob)* Add null checks before updating application and database statuses +- *(environment-variables)* Update label text for build variable checkboxes to improve clarity +- *(service-management)* Update service stop and restart messages for improved clarity and formatting +- *(preview-form)* Update helper text formatting in preview URL template input for better readability +- *(application-management)* Improve stop messages for application, database, and service to enhance clarity and formatting +- *(application-configuration)* Prevent access to preview deployments for deploy_key applications and update menu visibility accordingly +- *(select-component)* Handle exceptions during parameter retrieval and environment selection in the mount method +- *(previews)* Escape container names in stopContainers method to prevent shell injection vulnerabilities +- *(docker)* Add protection against empty container queries in GetContainersStatus to prevent unnecessary updates +- *(modal-confirmation)* Decode HTML entities in confirmation text to ensure proper display +- *(select-component)* Enhance user interaction by adding cursor styles and disabling selection during processing +- *(deployment-show)* Remove unnecessary fixed positioning for button container to improve layout responsiveness +- *(email-notifications)* Change notify method to notifyNow for immediate test email delivery +- *(service-templates)* Update Convex service configuration to use FQDN variables +- *(database-heading)* Simplify stop database message for clarity +- *(navbar)* Remove unnecessary x-init directive for loading proxy configuration +- *(patches)* Add padding to loading message for better visibility during update checks +- *(terminal-connection)* Improve error handling and stability for auto-connection; enhance component readiness checks and retry logic +- *(terminal)* Add unique wire:key to terminal component for improved reactivity and state management +- *(css)* Adjust utility classes in utilities.css for consistent application of Tailwind directives +- *(css)* Refine utility classes in utilities.css for proper Tailwind directive application +- *(install)* Update Docker installation script to use dynamic OS_TYPE and correct installation URL +- *(cloudflare)* Add error handling to automated Cloudflare configuration script +- *(navbar)* Add error handling for proxy status check to improve user feedback +- *(web)* Update user team retrieval method for consistent authentication handling +- *(cloudflare)* Update refresh method to correctly set Cloudflare tunnel status and improve user notification on IP address update +- *(service)* Update service template for affine and add migration service for improved deployment process +- *(supabase)* Update Supabase service images and healthcheck methods for improved reliability +- *(terminal)* Now it should work +- *(degraded-status)* Remove unnecessary whitespace in badge element for cleaner HTML +- *(routes)* Add name to security route for improved route management + +### ๐Ÿ’ผ Other + +- Add support for postmarketOS (#5608) +- *(core)* Simplify events for app/db/service status changes + +### ๐Ÿšœ Refactor + +- *(service)* Observium +- *(service)* Improve leantime +- *(service)* Imporve limesurvey +- *(service)* Improve CodiMD +- *(service)* Typsense +- *(services)* Improve yamtrack +- *(service)* Improve paymenter +- *(service)* Consolidate configuration change dispatch logic and remove unused navbar component +- *(sidebar)* Simplify server patching link by removing button element +- *(slide-over)* Streamline button element and improve code readability +- *(service)* Enhance modal confirmation component with event dispatching for service stop actions +- *(slide-over)* Enhance class merging for improved component styling +- *(core)* Use property promotion +- *(service)* Improve maybe +- *(applications)* Remove unused docker compose raw decoding +- *(service)* Make TYPESENSE_API_KEY required +- *(ui)* Show toast when server does not work and on stop +- *(service)* Improve superset +- *(service)* Improve Onetimesecret +- *(service)* Improve Seafile +- *(service)* Improve orangehrm +- *(service)* Improve grist +- *(application)* Enhance application stopping logic to support multiple servers +- *(pricing-plans)* Improve label class binding for payment frequency selection +- *(error-handling)* Replace generic Exception with RuntimeException for improved error specificity +- *(error-handling)* Change Exception to RuntimeException for clearer error reporting +- *(service)* Remove informational dispatch during service stop for cleaner execution +- *(server-ui)* Improve layout and messaging in advanced settings and charts views +- *(terminal-access)* Streamline resource retrieval and enhance terminal access messaging in UI +- *(terminal)* Enhance terminal connection management and error handling, including improved reconnection logic and cleanup procedures +- *(application-deployment)* Separate handling of FAILED and CANCELLED_BY_USER statuses for clearer logic and notification +- *(jobs)* Update middleware to include job-specific identifiers for WithoutOverlapping +- *(jobs)* Modify middleware to use job-specific identifier for WithoutOverlapping +- *(environment-variables)* Remove debug logging from bulk submit handling for cleaner code +- *(environment-variables)* Simplify application build pack check in environment variable handling +- *(logs)* Adjust padding in logs view for improved layout consistency +- *(application-deployment)* Streamline post-deployment process by always dispatching container status check +- *(service-management)* Enhance container stopping logic by implementing parallel processing and removing deprecated methods +- *(activity-monitor)* Change activity property visibility and update view references for consistency +- *(activity-monitor)* Enhance layout responsiveness by adjusting class bindings and structure for better display +- *(service-management)* Update stopContainersInParallel method to enforce Server type hint for improved type safety +- *(service-management)* Rearrange docker cleanup logic in StopService to improve readability +- *(database-management)* Simplify docker cleanup logic in StopDatabase to enhance readability +- *(activity-monitor)* Consolidate activity monitoring logic and remove deprecated NewActivityMonitor component +- *(activity-monitor)* Update dispatch method to use activityMonitor instead of deprecated newActivityMonitor +- *(push-server-update)* Enhance application preview handling by incorporating pull request IDs and adding status update protections +- *(docker-compose)* Replace hardcoded Docker Compose configuration with external YAML template for improved database detection testing +- *(test-database-detection)* Rename services for clarity, add new database configurations, and update application service dependencies +- *(database-detection)* Enhance isDatabaseImage function to utilize service configuration for improved detection accuracy +- *(install-scripts)* Update Docker installation process to include manual installation fallback and improve error handling +- *(logs-view)* Update logs display for service containers with improved headings and dynamic key binding +- *(logs)* Enhance container loading logic and improve UI for logs display across various resource types +- *(cloudflare-tunnel)* Enhance layout and structure of Cloudflare Tunnel documentation and confirmation modal +- *(terminal-connection)* Streamline auto-connection logic and improve component readiness checks +- *(logs)* Remove unused methods and debug functionality from Logs.php for cleaner code +- *(remoteProcess)* Update sanitize_utf8_text function to accept nullable string parameter for improved type safety +- *(events)* Remove ProxyStarted event and associated ProxyStartedNotification listener for code cleanup +- *(navbar)* Remove unnecessary parameters from server navbar component for cleaner implementation +- *(proxy)* Remove commented-out listener and method for cleaner code structure +- *(events)* Update ProxyStatusChangedUI constructor to accept nullable teamId for improved flexibility +- *(cloudflare)* Update server retrieval method for improved query efficiency +- *(navbar)* Remove unused PHP use statement for cleaner code +- *(proxy)* Streamline proxy status handling and improve dashboard availability checks +- *(navbar)* Simplify proxy status handling and enhance loading indicators for better user experience +- *(resource-operations)* Filter out build servers from the server list and clean up commented-out code in the resource operations view +- *(execute-container-command)* Simplify connection logic and improve terminal availability checks +- *(navigation)* Remove wire:navigate directive from configuration links for cleaner HTML structure +- *(proxy)* Update StartProxy calls to use named parameter for async option +- *(clone-project)* Enhance server retrieval by including destinations and filtering out build servers ### ๐Ÿ“š Documentation - Update changelog +- *(service)* Add new docs link for zipline (#5912) +- Update changelog +- Update changelog + +### ๐ŸŽจ Styling + +- *(css)* Update padding utility for password input and add newline in app.css +- *(css)* Refine badge utility styles in utilities.css +- *(css)* Enhance badge utility styles in utilities.css + +### โš™๏ธ Miscellaneous Tasks + +- *(versions)* Update coolify version to 4.0.0-beta.419 and nightly version to 4.0.0-beta.420 in configuration files +- *(service)* Rename hoarder server to karakeep (#5607) +- *(service)* Update Supabase services (#5708) +- *(service)* Remove unused documenso env +- *(service)* Formatting and cleanup of ryot +- *(docs)* Remove changelog and add it to gitignore +- *(versions)* Update version to 4.0.0-beta.419 +- *(service)* Diun formatting +- *(docs)* Update CHANGELOG.md +- *(service)* Switch convex vars +- *(service)* Pgbackweb formatting and naming update +- *(service)* Remove typesense default API key +- *(service)* Format yamtrack healthcheck +- *(core)* Remove unused function +- *(ui)* Remove unused stopEvent code +- *(service)* Remove unused env +- *(tests)* Update test environment database name and add new feature test for converting container environment variables to array +- *(service)* Update Immich service (#5886) +- *(service)* Remove unused logo +- *(api)* Update API docs +- *(dependencies)* Update package versions in composer.json and composer.lock for improved compatibility and performance +- *(dependencies)* Update package versions in package.json and package-lock.json for improved stability and features + +## [4.0.0-beta.417] - 2025-05-07 + +### ๐Ÿ› Bug Fixes + +- *(select)* Update fallback logo path to use absolute URL for improved reliability + +### ๐Ÿ“š Documentation + +- Update changelog + +### โš™๏ธ Miscellaneous Tasks + +- *(versions)* Update coolify version to 4.0.0-beta.418 + +## [4.0.0-beta.416] - 2025-05-05 + +### ๐Ÿš€ Features + +- *(migration)* Add 'is_migrated' and 'custom_type' columns to service_applications and service_databases tables +- *(backup)* Implement custom database type selection and enhance scheduled backups management +- *(README)* Add Gozunga and Macarne to sponsors list +- *(redis)* Add scheduled cleanup command for Redis keys and enhance cleanup logic + +### ๐Ÿ› Bug Fixes + +- *(service)* Graceful shutdown of old container (#5731) +- *(ServerCheck)* Enhance proxy container check to ensure it is running before proceeding +- *(applications)* Include pull_request_id in deployment queue check to prevent duplicate deployments +- *(database)* Update label for image input field to improve clarity +- *(ServerCheck)* Set default proxy status to 'exited' to handle missing container state +- *(database)* Reduce container stop timeout from 300 to 30 seconds for improved responsiveness +- *(ui)* System theming for charts (#5740) +- *(dev)* Mount points?! +- *(dev)* Proxy mount point +- *(ui)* Allow adding scheduled backups for non-migrated databases +- *(DatabaseBackupJob)* Escape PostgreSQL password in backup command (#5759) +- *(ui)* Correct closing div tag in service index view + +### ๐Ÿšœ Refactor + +- *(Database)* Streamline container shutdown process and reduce timeout duration +- *(core)* Streamline container stopping process and reduce timeout duration; update related methods for consistency +- *(database)* Update DB facade usage for consistency across service files +- *(database)* Enhance application conversion logic and add existence checks for databases and applications +- *(actions)* Standardize method naming for network and configuration deletion across application and service classes +- *(logdrain)* Consolidate log drain stopping logic to reduce redundancy +- *(StandaloneMariadb)* Add type hint for destination method to improve code clarity +- *(DeleteResourceJob)* Streamline resource deletion logic and improve conditional checks for database types +- *(jobs)* Update middleware to prevent job release after expiration for CleanupInstanceStuffsJob, RestartProxyJob, and ServerCheckJob +- *(jobs)* Unify middleware configuration to prevent job release after expiration for DockerCleanupJob and PushServerUpdateJob + +### ๐Ÿ“š Documentation + +- Update changelog +- Update changelog + +### โš™๏ธ Miscellaneous Tasks + +- *(seeder)* Update git branch from 'main' to 'v4.x' for multiple examples in ApplicationSeeder +- *(versions)* Update coolify version to 4.0.0-beta.417 and nightly version to 4.0.0-beta.418 ## [4.0.0-beta.415] - 2025-04-29 +### ๐Ÿ› Bug Fixes + +- *(ui)* Remove required attribute from image input in service application view +- *(ui)* Change application image validation to be nullable in service application view +- *(Server)* Correct proxy path formatting for Traefik proxy type + ### ๐Ÿ“š Documentation - Update changelog +### โš™๏ธ Miscellaneous Tasks + +- *(versions)* Update coolify version to 4.0.0-beta.416 and nightly version to 4.0.0-beta.417 in configuration files; fix links in deployment view + +## [4.0.0-beta.414] - 2025-04-28 + +### ๐Ÿ› Bug Fixes + +- *(ui)* Disable livewire navigate feature (causing spam of setInterval()) + ## [4.0.0-beta.413] - 2025-04-28 ### ๐Ÿ’ผ Other @@ -29,12 +335,6 @@ All notable changes to this project will be documented in this file. - *(workflows)* Adjust workflow for announcement -## [4.0.0-beta.412] - 2025-04-23 - -### โš™๏ธ Miscellaneous Tasks - -- *(versions)* Update coolify version to 4.0.0-beta.412 and nightly version to 4.0.0-beta.413 in configuration files - ## [4.0.0-beta.411] - 2025-04-23 ### ๐Ÿš€ Features @@ -43,6 +343,7 @@ All notable changes to this project will be documented in this file. - *(api)* Enhance OpenAPI specifications with token variable and additional key attributes - *(docker)* Add HTTP Basic Authentication support and enhance hostname parsing in Docker run conversion - *(api)* Add HTTP Basic Authentication fields to OpenAPI specifications and enhance PrivateKey model descriptions +- *(README)* Add InterviewPal sponsorship link and corresponding SVG icon ### ๐Ÿ› Bug Fixes @@ -53,6 +354,8 @@ All notable changes to this project will be documented in this file. - Add 201 json code to servers validate api response - *(docker)* Ensure password hashing only occurs when HTTP Basic Authentication is enabled - *(docker)* Enhance hostname and GPU option validation in Docker run to compose conversion +- *(terminal)* Enhance WebSocket client verification with authorized IPs in terminal server +- *(ApplicationDeploymentJob)* Ensure source is an object before checking GitHub app properties ### ๐Ÿšœ Refactor @@ -76,6 +379,12 @@ All notable changes to this project will be documented in this file. ### โš™๏ธ Miscellaneous Tasks - *(versions)* Update coolify version to 4.0.0-beta.411 and nightly version to 4.0.0-beta.412 in configuration files +- *(versions)* Update coolify version to 4.0.0-beta.412 and nightly version to 4.0.0-beta.413 in configuration files +- *(versions)* Update coolify version to 4.0.0-beta.413 and nightly version to 4.0.0-beta.414 in configuration files +- *(versions)* Update realtime version to 1.0.8 in versions.json +- *(versions)* Update realtime version to 1.0.8 in versions.json +- *(docker)* Update soketi image version to 1.0.8 in production configuration files +- *(versions)* Update coolify version to 4.0.0-beta.414 and nightly version to 4.0.0-beta.415 in configuration files ## [4.0.0-beta.410] - 2025-04-18 diff --git a/app/Actions/Application/StopApplication.php b/app/Actions/Application/StopApplication.php index f5f16f3fe..0ca703fce 100644 --- a/app/Actions/Application/StopApplication.php +++ b/app/Actions/Application/StopApplication.php @@ -3,6 +3,7 @@ namespace App\Actions\Application; use App\Actions\Server\CleanupDocker; +use App\Events\ServiceStatusChanged; use App\Models\Application; use Lorisleiva\Actions\Concerns\AsAction; @@ -14,30 +15,46 @@ class StopApplication public function handle(Application $application, bool $previewDeployments = false, bool $dockerCleanup = true) { - try { - $server = $application->destination->server; - if (! $server->isFunctional()) { - return 'Server is not functional'; - } - - if ($server->isSwarm()) { - instant_remote_process(["docker stack rm {$application->uuid}"], $server); - - return; - } - - $containersToStop = $application->getContainersToStop($previewDeployments); - $application->stopContainers($containersToStop, $server); - - if ($application->build_pack === 'dockercompose') { - $application->deleteConnectedNetworks(); - } - - if ($dockerCleanup) { - CleanupDocker::dispatch($server, true); - } - } catch (\Exception $e) { - return $e->getMessage(); + $servers = collect([$application->destination->server]); + if ($application?->additional_servers?->count() > 0) { + $servers = $servers->merge($application->additional_servers); } + foreach ($servers as $server) { + try { + if (! $server->isFunctional()) { + return 'Server is not functional'; + } + + if ($server->isSwarm()) { + instant_remote_process(["docker stack rm {$application->uuid}"], $server); + + return; + } + + $containers = $previewDeployments + ? getCurrentApplicationContainerStatus($server, $application->id, includePullrequests: true) + : getCurrentApplicationContainerStatus($server, $application->id, 0); + + $containersToStop = $containers->pluck('Names')->toArray(); + + foreach ($containersToStop as $containerName) { + instant_remote_process(command: [ + "docker stop --time=30 $containerName", + "docker rm -f $containerName", + ], server: $server, throwError: false); + } + + if ($application->build_pack === 'dockercompose') { + $application->deleteConnectedNetworks(); + } + + if ($dockerCleanup) { + CleanupDocker::dispatch($server, true); + } + } catch (\Exception $e) { + return $e->getMessage(); + } + } + ServiceStatusChanged::dispatch($application->environment->project->team->id); } } diff --git a/app/Actions/Application/StopApplicationOneServer.php b/app/Actions/Application/StopApplicationOneServer.php index b13b10efd..600b1cb9a 100644 --- a/app/Actions/Application/StopApplicationOneServer.php +++ b/app/Actions/Application/StopApplicationOneServer.php @@ -25,7 +25,10 @@ class StopApplicationOneServer $containerName = data_get($container, 'Names'); if ($containerName) { instant_remote_process( - ["docker rm -f {$containerName}"], + [ + "docker stop --time=30 $containerName", + "docker rm -f $containerName", + ], $server ); } diff --git a/app/Actions/CoolifyTask/RunRemoteProcess.php b/app/Actions/CoolifyTask/RunRemoteProcess.php index 8ce9aa1f2..e0dacfbec 100644 --- a/app/Actions/CoolifyTask/RunRemoteProcess.php +++ b/app/Actions/CoolifyTask/RunRemoteProcess.php @@ -104,14 +104,11 @@ class RunRemoteProcess $this->activity->save(); if ($this->call_event_on_finish) { try { - if ($this->call_event_data) { - event(resolve("App\\Events\\$this->call_event_on_finish", [ - 'data' => $this->call_event_data, - ])); + $eventClass = "App\\Events\\$this->call_event_on_finish"; + if (! is_null($this->call_event_data)) { + event(new $eventClass($this->call_event_data)); } else { - event(resolve("App\\Events\\$this->call_event_on_finish", [ - 'userId' => $this->activity->causer_id, - ])); + event(new $eventClass($this->activity->causer_id)); } } catch (\Throwable $e) { Log::error('Error calling event: '.$e->getMessage()); diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index c4a40f020..744bbaa50 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -44,6 +44,9 @@ class StartDatabaseProxy }; $configuration_dir = database_proxy_dir($database->uuid); + if (isDev()) { + $configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$database->uuid.'/proxy'; + } $nginxconf = << [ $proxyContainerName => [ - 'build' => [ - 'context' => $configuration_dir, - 'dockerfile' => 'Dockerfile', - ], 'image' => 'nginx:stable-alpine', 'container_name' => $proxyContainerName, 'restart' => RESTART_MODE, @@ -81,6 +75,13 @@ class StartDatabaseProxy 'networks' => [ $network, ], + 'volumes' => [ + [ + 'type' => 'bind', + 'source' => "$configuration_dir/nginx.conf", + 'target' => '/etc/nginx/nginx.conf', + ], + ], 'healthcheck' => [ 'test' => [ 'CMD-SHELL', @@ -103,15 +104,13 @@ class StartDatabaseProxy ]; $dockercompose_base64 = base64_encode(Yaml::dump($docker_compose, 4, 2)); $nginxconf_base64 = base64_encode($nginxconf); - $dockerfile_base64 = base64_encode($dockerfile); instant_remote_process(["docker rm -f $proxyContainerName"], $server, false); instant_remote_process([ "mkdir -p $configuration_dir", - "echo '{$dockerfile_base64}' | base64 -d | tee $configuration_dir/Dockerfile > /dev/null", "echo '{$nginxconf_base64}' | base64 -d | tee $configuration_dir/nginx.conf > /dev/null", "echo '{$dockercompose_base64}' | base64 -d | tee $configuration_dir/docker-compose.yaml > /dev/null", "docker compose --project-directory {$configuration_dir} pull", - "docker compose --project-directory {$configuration_dir} up --build -d", + "docker compose --project-directory {$configuration_dir} up -d", ], $server); } } diff --git a/app/Actions/Database/StopDatabase.php b/app/Actions/Database/StopDatabase.php index 161e7dad7..a03c9269e 100644 --- a/app/Actions/Database/StopDatabase.php +++ b/app/Actions/Database/StopDatabase.php @@ -3,6 +3,7 @@ namespace App\Actions\Database; use App\Actions\Server\CleanupDocker; +use App\Events\ServiceStatusChanged; use App\Models\StandaloneClickhouse; use App\Models\StandaloneDragonfly; use App\Models\StandaloneKeydb; @@ -19,23 +20,29 @@ class StopDatabase public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $database, bool $isDeleteOperation = false, bool $dockerCleanup = true) { - $server = $database->destination->server; - if (! $server->isFunctional()) { - return 'Server is not functional'; - } + try { + $server = $database->destination->server; + if (! $server->isFunctional()) { + return 'Server is not functional'; + } + + $this->stopContainer($database, $database->uuid, 30); - $this->stopContainer($database, $database->uuid, 30); - if ($isDeleteOperation) { if ($dockerCleanup) { CleanupDocker::dispatch($server, true); } + + if ($database->is_public) { + StopDatabaseProxy::run($database); + } + + return 'Database stopped successfully'; + } catch (\Exception $e) { + return 'Database stop failed: '.$e->getMessage(); + } finally { + ServiceStatusChanged::dispatch($database->environment->project->team->id); } - if ($database->is_public) { - StopDatabaseProxy::run($database); - } - - return 'Database stopped successfully'; } private function stopContainer($database, string $containerName, int $timeout = 30): void diff --git a/app/Actions/Docker/GetContainersStatus.php b/app/Actions/Docker/GetContainersStatus.php index 091268043..c3268ec07 100644 --- a/app/Actions/Docker/GetContainersStatus.php +++ b/app/Actions/Docker/GetContainersStatus.php @@ -4,6 +4,7 @@ namespace App\Actions\Docker; use App\Actions\Database\StartDatabaseProxy; use App\Actions\Shared\ComplexStatusCheck; +use App\Events\ServiceChecked; use App\Models\ApplicationPreview; use App\Models\Server; use App\Models\ServiceDatabase; @@ -273,24 +274,13 @@ class GetContainersStatus if (str($application->status)->startsWith('exited')) { continue; } - $application->update(['status' => 'exited']); - $name = data_get($application, 'name'); - $fqdn = data_get($application, 'fqdn'); - - $containerName = $name ? "$name ($fqdn)" : $fqdn; - - $projectUuid = data_get($application, 'environment.project.uuid'); - $applicationUuid = data_get($application, 'uuid'); - $environment = data_get($application, 'environment.name'); - - if ($projectUuid && $applicationUuid && $environment) { - $url = base_url().'/project/'.$projectUuid.'/'.$environment.'/application/'.$applicationUuid; - } else { - $url = null; + // Only protection: If no containers at all, Docker query might have failed + if ($this->containers->isEmpty()) { + continue; } - // $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url)); + $application->update(['status' => 'exited']); } $notRunningApplicationPreviews = $previews->pluck('id')->diff($foundApplicationPreviews); foreach ($notRunningApplicationPreviews as $previewId) { @@ -298,24 +288,13 @@ class GetContainersStatus if (str($preview->status)->startsWith('exited')) { continue; } - $preview->update(['status' => 'exited']); - $name = data_get($preview, 'name'); - $fqdn = data_get($preview, 'fqdn'); - - $containerName = $name ? "$name ($fqdn)" : $fqdn; - - $projectUuid = data_get($preview, 'application.environment.project.uuid'); - $environmentName = data_get($preview, 'application.environment.name'); - $applicationUuid = data_get($preview, 'application.uuid'); - - if ($projectUuid && $applicationUuid && $environmentName) { - $url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/application/'.$applicationUuid; - } else { - $url = null; + // Only protection: If no containers at all, Docker query might have failed + if ($this->containers->isEmpty()) { + continue; } - // $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url)); + $preview->update(['status' => 'exited']); } $notRunningDatabases = $databases->pluck('id')->diff($foundDatabases); foreach ($notRunningDatabases as $database) { @@ -341,5 +320,6 @@ class GetContainersStatus } // $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url)); } + ServiceChecked::dispatch($this->server->team->id); } } diff --git a/app/Actions/Proxy/CheckConfiguration.php b/app/Actions/Proxy/CheckConfiguration.php index bdeafd061..b2d1eb787 100644 --- a/app/Actions/Proxy/CheckConfiguration.php +++ b/app/Actions/Proxy/CheckConfiguration.php @@ -3,6 +3,7 @@ namespace App\Actions\Proxy; use App\Models\Server; +use App\Services\ProxyDashboardCacheService; use Lorisleiva\Actions\Concerns\AsAction; class CheckConfiguration @@ -28,6 +29,8 @@ class CheckConfiguration throw new \Exception('Could not generate proxy configuration'); } + ProxyDashboardCacheService::isTraefikDashboardAvailableFromConfiguration($server, $proxy_configuration); + return $proxy_configuration; } } diff --git a/app/Actions/Proxy/CheckProxy.php b/app/Actions/Proxy/CheckProxy.php index 5a2562073..d4b03ffc1 100644 --- a/app/Actions/Proxy/CheckProxy.php +++ b/app/Actions/Proxy/CheckProxy.php @@ -5,6 +5,7 @@ namespace App\Actions\Proxy; use App\Enums\ProxyTypes; use App\Models\Server; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Process; use Lorisleiva\Actions\Concerns\AsAction; use Symfony\Component\Yaml\Yaml; @@ -67,22 +68,12 @@ class CheckProxy } $portsToCheck = ['80', '443']; - foreach ($portsToCheck as $port) { - // Use the smart port checker that handles dual-stack properly - if ($this->isPortConflict($server, $port, $proxyContainerName)) { - if ($fromUI) { - throw new \Exception("Port $port is in use.
You must stop the process using this port.

Docs: https://coolify.io/docs
Discord: https://coolify.io/discord"); - } else { - return false; - } - } - } try { if ($server->proxyType() !== ProxyTypes::NONE->value) { $proxyCompose = CheckConfiguration::run($server); if (isset($proxyCompose)) { $yaml = Yaml::parse($proxyCompose); - $portsToCheck = []; + $configPorts = []; if ($server->proxyType() === ProxyTypes::TRAEFIK->value) { $ports = data_get($yaml, 'services.traefik.ports'); } elseif ($server->proxyType() === ProxyTypes::CADDY->value) { @@ -90,9 +81,11 @@ class CheckProxy } if (isset($ports)) { foreach ($ports as $port) { - $portsToCheck[] = str($port)->before(':')->value(); + $configPorts[] = str($port)->before(':')->value(); } } + // Combine default ports with config ports + $portsToCheck = array_merge($portsToCheck, $configPorts); } } else { $portsToCheck = []; @@ -103,11 +96,188 @@ class CheckProxy if (count($portsToCheck) === 0) { return false; } + $portsToCheck = array_values(array_unique($portsToCheck)); + // Check port conflicts in parallel + $conflicts = $this->checkPortConflictsInParallel($server, $portsToCheck, $proxyContainerName); + foreach ($conflicts as $port => $conflict) { + if ($conflict) { + if ($fromUI) { + throw new \Exception("Port $port is in use.
You must stop the process using this port.

Docs: https://coolify.io/docs
Discord: https://coolify.io/discord"); + } else { + return false; + } + } + } return true; } } + /** + * Check multiple ports for conflicts in parallel + * Returns an array with port => conflict_status mapping + */ + private function checkPortConflictsInParallel(Server $server, array $ports, string $proxyContainerName): array + { + if (empty($ports)) { + return []; + } + + try { + // Build concurrent port check commands + $results = Process::concurrently(function ($pool) use ($server, $ports, $proxyContainerName) { + foreach ($ports as $port) { + $commands = $this->buildPortCheckCommands($server, $port, $proxyContainerName); + $pool->command($commands['ssh_command'])->timeout(10); + } + }); + + // Process results + $conflicts = []; + + foreach ($ports as $index => $port) { + $result = $results[$index] ?? null; + + if ($result) { + $conflicts[$port] = $this->parsePortCheckResult($result, $port, $proxyContainerName); + } else { + // If process failed, assume no conflict to avoid false positives + $conflicts[$port] = false; + } + } + + return $conflicts; + } catch (\Throwable $e) { + Log::warning('Parallel port checking failed: '.$e->getMessage().'. Falling back to sequential checking.'); + + // Fallback to sequential checking if parallel fails + $conflicts = []; + foreach ($ports as $port) { + $conflicts[$port] = $this->isPortConflict($server, $port, $proxyContainerName); + } + + return $conflicts; + } + } + + /** + * Build the SSH command for checking a specific port + */ + private function buildPortCheckCommands(Server $server, string $port, string $proxyContainerName): array + { + // First check if our own proxy is using this port (which is fine) + $getProxyContainerId = "docker ps -a --filter name=$proxyContainerName --format '{{.ID}}'"; + $checkProxyPortScript = " + CONTAINER_ID=\$($getProxyContainerId); + if [ ! -z \"\$CONTAINER_ID\" ]; then + if docker inspect \$CONTAINER_ID --format '{{json .NetworkSettings.Ports}}' | grep -q '\"$port/tcp\"'; then + echo 'proxy_using_port'; + exit 0; + fi; + fi; + "; + + // Command sets for different ways to check ports, ordered by preference + $portCheckScript = " + $checkProxyPortScript + + # Try ss command first + if command -v ss >/dev/null 2>&1; then + ss_output=\$(ss -Htuln state listening sport = :$port 2>/dev/null); + if [ -z \"\$ss_output\" ]; then + echo 'port_free'; + exit 0; + fi; + count=\$(echo \"\$ss_output\" | grep -c ':$port '); + if [ \$count -eq 0 ]; then + echo 'port_free'; + exit 0; + fi; + # Check for dual-stack or docker processes + if [ \$count -le 2 ] && (echo \"\$ss_output\" | grep -q 'docker\\|coolify'); then + echo 'port_free'; + exit 0; + fi; + echo \"port_conflict|\$ss_output\"; + exit 0; + fi; + + # Try netstat as fallback + if command -v netstat >/dev/null 2>&1; then + netstat_output=\$(netstat -tuln 2>/dev/null | grep ':$port '); + if [ -z \"\$netstat_output\" ]; then + echo 'port_free'; + exit 0; + fi; + count=\$(echo \"\$netstat_output\" | grep -c 'LISTEN'); + if [ \$count -eq 0 ]; then + echo 'port_free'; + exit 0; + fi; + if [ \$count -le 2 ] && (echo \"\$netstat_output\" | grep -q 'docker\\|coolify'); then + echo 'port_free'; + exit 0; + fi; + echo \"port_conflict|\$netstat_output\"; + exit 0; + fi; + + # Final fallback using nc + if nc -z -w1 127.0.0.1 $port >/dev/null 2>&1; then + echo 'port_conflict|nc_detected'; + else + echo 'port_free'; + fi; + "; + + $sshCommand = \App\Helpers\SshMultiplexingHelper::generateSshCommand($server, $portCheckScript); + + return [ + 'ssh_command' => $sshCommand, + 'script' => $portCheckScript, + ]; + } + + /** + * Parse the result from port check command + */ + private function parsePortCheckResult($processResult, string $port, string $proxyContainerName): bool + { + $exitCode = $processResult->exitCode(); + $output = trim($processResult->output()); + $errorOutput = trim($processResult->errorOutput()); + + if ($exitCode !== 0) { + return false; + } + + if ($output === 'proxy_using_port' || $output === 'port_free') { + return false; // No conflict + } + + if (str_starts_with($output, 'port_conflict|')) { + $details = substr($output, strlen('port_conflict|')); + + // Additional logic to detect dual-stack scenarios + if ($details !== 'nc_detected') { + // Check for dual-stack scenario - typically 1-2 listeners (IPv4+IPv6) + $lines = explode("\n", $details); + if (count($lines) <= 2) { + // Look for IPv4 and IPv6 in the listing + if ((strpos($details, '0.0.0.0:'.$port) !== false && strpos($details, ':::'.$port) !== false) || + (strpos($details, '*:'.$port) !== false && preg_match('/\*:'.$port.'.*IPv[46]/', $details))) { + + return false; // This is just a normal dual-stack setup + } + } + } + + return true; // Real port conflict + } + + return false; + } + /** * Smart port checker that handles dual-stack configurations * Returns true only if there's a real port conflict (not just dual-stack) @@ -176,14 +346,11 @@ class CheckProxy // Run the actual check commands $output = instant_remote_process($set['check'], $server, true); - // Parse the output lines $lines = explode("\n", trim($output)); - // Get the detailed output and listener count - $details = trim($lines[0] ?? ''); - $count = intval(trim($lines[1] ?? '0')); - + $details = trim(implode("\n", array_slice($lines, 0, -1))); + $count = intval(trim($lines[count($lines) - 1] ?? '0')); // If no listeners or empty result, port is free if ($count == 0 || empty($details)) { return false; diff --git a/app/Actions/Proxy/StartProxy.php b/app/Actions/Proxy/StartProxy.php index 1fff55861..e7c020ff6 100644 --- a/app/Actions/Proxy/StartProxy.php +++ b/app/Actions/Proxy/StartProxy.php @@ -3,7 +3,8 @@ namespace App\Actions\Proxy; use App\Enums\ProxyTypes; -use App\Events\ProxyStarted; +use App\Events\ProxyStatusChanged; +use App\Events\ProxyStatusChangedUI; use App\Models\Server; use Lorisleiva\Actions\Concerns\AsAction; use Spatie\Activitylog\Models\Activity; @@ -28,6 +29,7 @@ class StartProxy $docker_compose_yml_base64 = base64_encode($configuration); $server->proxy->last_applied_settings = str($docker_compose_yml_base64)->pipe('md5')->value(); $server->save(); + if ($server->isSwarmManager()) { $commands = $commands->merge([ "mkdir -p $proxy_path/dynamic", @@ -57,20 +59,22 @@ class StartProxy " echo 'Successfully stopped and removed existing coolify-proxy.'", 'fi', "echo 'Starting coolify-proxy.'", - 'docker compose up -d', + 'docker compose up -d --wait --remove-orphans', "echo 'Successfully started coolify-proxy.'", ]); $commands = $commands->merge(connectProxyToNetworks($server)); } + $server->proxy->set('status', 'starting'); + $server->save(); + ProxyStatusChangedUI::dispatch($server->team_id); if ($async) { - return remote_process($commands, $server, callEventOnFinish: 'ProxyStarted', callEventData: $server); + return remote_process($commands, $server, callEventOnFinish: 'ProxyStatusChanged', callEventData: $server->id); } else { instant_remote_process($commands, $server); - $server->proxy->set('status', 'running'); $server->proxy->set('type', $proxyType); $server->save(); - ProxyStarted::dispatch($server); + ProxyStatusChanged::dispatch($server->id); return 'OK'; } diff --git a/app/Actions/Proxy/StopProxy.php b/app/Actions/Proxy/StopProxy.php index 75b22d236..29cc63b40 100644 --- a/app/Actions/Proxy/StopProxy.php +++ b/app/Actions/Proxy/StopProxy.php @@ -2,7 +2,10 @@ namespace App\Actions\Proxy; +use App\Events\ProxyStatusChanged; +use App\Events\ProxyStatusChangedUI; use App\Models\Server; +use App\Services\ProxyDashboardCacheService; use Lorisleiva\Actions\Concerns\AsAction; class StopProxy @@ -13,6 +16,9 @@ class StopProxy { try { $containerName = $server->isSwarm() ? 'coolify-proxy_traefik' : 'coolify-proxy'; + $server->proxy->status = 'stopping'; + $server->save(); + ProxyStatusChangedUI::dispatch($server->team_id); instant_remote_process(command: [ "docker stop --time=$timeout $containerName", @@ -24,6 +30,9 @@ class StopProxy $server->save(); } catch (\Throwable $e) { return handleError($e); + } finally { + ProxyDashboardCacheService::clearCache($server); + ProxyStatusChanged::dispatch($server->id); } } } diff --git a/app/Actions/Server/CheckUpdates.php b/app/Actions/Server/CheckUpdates.php new file mode 100644 index 000000000..a8b1be11d --- /dev/null +++ b/app/Actions/Server/CheckUpdates.php @@ -0,0 +1,223 @@ +serverStatus() === false) { + return [ + 'error' => 'Server is not reachable or not ready.', + ]; + } + + // Try first method - using instant_remote_process + $output = instant_remote_process(['cat /etc/os-release'], $server); + + // Parse os-release into an associative array + $osInfo = []; + foreach (explode("\n", $output) as $line) { + if (empty($line)) { + continue; + } + if (strpos($line, '=') === false) { + continue; + } + [$key, $value] = explode('=', $line, 2); + $osInfo[$key] = trim($value, '"'); + } + + // Get the main OS identifier + $osId = $osInfo['ID'] ?? ''; + // $osIdLike = $osInfo['ID_LIKE'] ?? ''; + // $versionId = $osInfo['VERSION_ID'] ?? ''; + + // Normalize OS types based on install.sh logic + switch ($osId) { + case 'manjaro': + case 'manjaro-arm': + case 'endeavouros': + $osType = 'arch'; + break; + case 'pop': + case 'linuxmint': + case 'zorin': + $osType = 'ubuntu'; + break; + case 'fedora-asahi-remix': + $osType = 'fedora'; + break; + default: + $osType = $osId; + } + + // Determine package manager based on OS type + $packageManager = match ($osType) { + 'arch' => 'pacman', + 'alpine' => 'apk', + 'ubuntu', 'debian', 'raspbian' => 'apt', + 'centos', 'fedora', 'rhel', 'ol', 'rocky', 'almalinux', 'amzn' => 'dnf', + 'sles', 'opensuse-leap', 'opensuse-tumbleweed' => 'zypper', + default => null + }; + + switch ($packageManager) { + case 'zypper': + $output = instant_remote_process(['LANG=C zypper -tx list-updates'], $server); + $out = $this->parseZypperOutput($output); + $out['osId'] = $osId; + $out['package_manager'] = $packageManager; + + return $out; + case 'dnf': + $output = instant_remote_process(['LANG=C dnf list -q --updates --refresh'], $server); + $out = $this->parseDnfOutput($output); + $out['osId'] = $osId; + $out['package_manager'] = $packageManager; + + return $out; + case 'apt': + instant_remote_process(['apt-get update -qq'], $server); + $output = instant_remote_process(['LANG=C apt list --upgradable 2>/dev/null'], $server); + + $out = $this->parseAptOutput($output); + $out['osId'] = $osId; + $out['package_manager'] = $packageManager; + + return $out; + default: + return [ + 'osId' => $osId, + 'error' => 'Unsupported package manager', + 'package_manager' => $packageManager, + ]; + } + } catch (\Throwable $e) { + ray('Error:', $e->getMessage()); + + return [ + 'osId' => $osId, + 'package_manager' => $packageManager, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]; + } + } + + private function parseZypperOutput(string $output): array + { + $updates = []; + + try { + $xml = simplexml_load_string($output); + if ($xml === false) { + return [ + 'total_updates' => 0, + 'updates' => [], + 'error' => 'Failed to parse XML output', + ]; + } + + // Navigate to the update-list node + $updateList = $xml->xpath('//update-list/update'); + + foreach ($updateList as $update) { + $updates[] = [ + 'package' => (string) $update['name'], + 'new_version' => (string) $update['edition'], + 'current_version' => (string) $update['edition-old'], + 'architecture' => (string) $update['arch'], + 'repository' => (string) $update->source['alias'], + 'summary' => (string) $update->summary, + 'description' => (string) $update->description, + ]; + } + + return [ + 'total_updates' => count($updates), + 'updates' => $updates, + ]; + } catch (\Throwable $e) { + return [ + 'total_updates' => 0, + 'updates' => [], + 'error' => 'Error parsing zypper output: '.$e->getMessage(), + ]; + } + } + + private function parseDnfOutput(string $output): array + { + $updates = []; + $lines = explode("\n", $output); + + foreach ($lines as $line) { + if (empty($line)) { + continue; + } + + // Split by multiple spaces/tabs and filter out empty elements + $parts = array_values(array_filter(preg_split('/\s+/', $line))); + + if (count($parts) >= 3) { + $package = $parts[0]; + $new_version = $parts[1]; + $repository = $parts[2]; + + // Extract architecture from package name (e.g., "cloud-init.noarch" -> "noarch") + $architecture = str_contains($package, '.') ? explode('.', $package)[1] : 'noarch'; + + $updates[] = [ + 'package' => $package, + 'new_version' => $new_version, + 'repository' => $repository, + 'architecture' => $architecture, + 'current_version' => 'unknown', // DNF doesn't show current version in check-update output + ]; + } + } + + return [ + 'total_updates' => count($updates), + 'updates' => $updates, + ]; + } + + private function parseAptOutput(string $output): array + { + $updates = []; + $lines = explode("\n", $output); + + foreach ($lines as $line) { + // Skip the "Listing... Done" line and empty lines + if (empty($line) || str_contains($line, 'Listing...')) { + continue; + } + + // Example line: package/stable 2.0-1 amd64 [upgradable from: 1.0-1] + if (preg_match('/^(.+?)\/(\S+)\s+(\S+)\s+(\S+)\s+\[upgradable from: (.+?)\]/', $line, $matches)) { + $updates[] = [ + 'package' => $matches[1], + 'repository' => $matches[2], + 'new_version' => $matches[3], + 'architecture' => $matches[4], + 'current_version' => $matches[5], + ]; + } + } + + return [ + 'total_updates' => count($updates), + 'updates' => $updates, + ]; + } +} diff --git a/app/Actions/Server/ConfigureCloudflared.php b/app/Actions/Server/ConfigureCloudflared.php index fc04e67a4..d21622bc5 100644 --- a/app/Actions/Server/ConfigureCloudflared.php +++ b/app/Actions/Server/ConfigureCloudflared.php @@ -2,16 +2,16 @@ namespace App\Actions\Server; -use App\Events\CloudflareTunnelConfigured; use App\Models\Server; use Lorisleiva\Actions\Concerns\AsAction; +use Spatie\Activitylog\Models\Activity; use Symfony\Component\Yaml\Yaml; class ConfigureCloudflared { use AsAction; - public function handle(Server $server, string $cloudflare_token) + public function handle(Server $server, string $cloudflare_token, string $ssh_domain): Activity { try { $config = [ @@ -24,6 +24,13 @@ class ConfigureCloudflared 'command' => 'tunnel run', 'environment' => [ "TUNNEL_TOKEN={$cloudflare_token}", + 'TUNNEL_METRICS=127.0.0.1:60123', + ], + 'healthcheck' => [ + 'test' => ['CMD', 'cloudflared', 'tunnel', '--metrics', '127.0.0.1:60123', 'ready'], + 'interval' => '5s', + 'timeout' => '30s', + 'retries' => 5, ], ], ], @@ -34,22 +41,20 @@ class ConfigureCloudflared 'mkdir -p /tmp/cloudflared', 'cd /tmp/cloudflared', "echo '$docker_compose_yml_base64' | base64 -d | tee docker-compose.yml > /dev/null", + 'echo Pulling latest Cloudflare Tunnel image.', 'docker compose pull', - 'docker compose down -v --remove-orphans > /dev/null 2>&1', - 'docker compose up -d --remove-orphans', + 'echo Stopping existing Cloudflare Tunnel container.', + 'docker rm -f coolify-cloudflared || true', + 'echo Starting new Cloudflare Tunnel container.', + 'docker compose up --wait --wait-timeout 15 --remove-orphans || docker logs coolify-cloudflared', ]); - instant_remote_process($commands, $server); - } catch (\Throwable $e) { - $server->settings->is_cloudflare_tunnel = false; - $server->settings->save(); - throw $e; - } finally { - CloudflareTunnelConfigured::dispatch($server->team_id); - $commands = collect([ - 'rm -fr /tmp/cloudflared', + return remote_process($commands, $server, callEventOnFinish: 'CloudflareTunnelChanged', callEventData: [ + 'server_id' => $server->id, + 'ssh_domain' => $ssh_domain, ]); - instant_remote_process($commands, $server); + } catch (\Throwable $e) { + throw $e; } } } diff --git a/app/Actions/Server/ServerCheck.php b/app/Actions/Server/ServerCheck.php index 41781d7fc..6ac87f1f0 100644 --- a/app/Actions/Server/ServerCheck.php +++ b/app/Actions/Server/ServerCheck.php @@ -104,7 +104,7 @@ class ServerCheck try { $shouldStart = CheckProxy::run($this->server); if ($shouldStart) { - StartProxy::run($this->server, false); + StartProxy::run($this->server, async: false); $this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server)); } } catch (\Throwable $e) { diff --git a/app/Actions/Server/StartSentinel.php b/app/Actions/Server/StartSentinel.php index 2785505c0..1ecf882dc 100644 --- a/app/Actions/Server/StartSentinel.php +++ b/app/Actions/Server/StartSentinel.php @@ -27,7 +27,7 @@ class StartSentinel $mountDir = '/data/coolify/sentinel'; $image = config('constants.coolify.registry_url').'/coollabsio/sentinel:'.$version; if (! $endpoint) { - throw new \Exception('You should set FQDN in Instance Settings.'); + throw new \RuntimeException('You should set FQDN in Instance Settings.'); } $environments = [ 'TOKEN' => $token, diff --git a/app/Actions/Server/UpdatePackage.php b/app/Actions/Server/UpdatePackage.php new file mode 100644 index 000000000..75d931f93 --- /dev/null +++ b/app/Actions/Server/UpdatePackage.php @@ -0,0 +1,52 @@ +serverStatus() === false) { + return [ + 'error' => 'Server is not reachable or not ready.', + ]; + } + switch ($packageManager) { + case 'zypper': + $commandAll = 'zypper update -y'; + $commandInstall = 'zypper install -y '.$package; + break; + case 'dnf': + $commandAll = 'dnf update -y'; + $commandInstall = 'dnf update -y '.$package; + break; + case 'apt': + $commandAll = 'apt update && apt upgrade -y'; + $commandInstall = 'apt install -y '.$package; + break; + default: + return [ + 'error' => 'OS not supported', + ]; + } + if ($all) { + return remote_process([$commandAll], $server); + } + + return remote_process([$commandInstall], $server); + } catch (\Exception $e) { + return [ + 'error' => $e->getMessage(), + ]; + } + } +} diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php index 372ffe397..404e11559 100644 --- a/app/Actions/Service/DeleteService.php +++ b/app/Actions/Service/DeleteService.php @@ -53,7 +53,7 @@ class DeleteService instant_remote_process(["docker rm -f $service->uuid"], $server, throwError: false); } catch (\Exception $e) { - throw new \Exception($e->getMessage()); + throw new \RuntimeException($e->getMessage()); } finally { if ($deleteConfigurations) { $service->deleteConfigurations(); diff --git a/app/Actions/Service/RestartService.php b/app/Actions/Service/RestartService.php index 4151ea947..d38ef54d6 100644 --- a/app/Actions/Service/RestartService.php +++ b/app/Actions/Service/RestartService.php @@ -11,10 +11,10 @@ class RestartService public string $jobQueue = 'high'; - public function handle(Service $service) + public function handle(Service $service, bool $pullLatestImages) { StopService::run($service); - return StartService::run($service); + return StartService::run($service, $pullLatestImages); } } diff --git a/app/Actions/Service/StartService.php b/app/Actions/Service/StartService.php index d48594e62..1e7779a75 100644 --- a/app/Actions/Service/StartService.php +++ b/app/Actions/Service/StartService.php @@ -41,6 +41,6 @@ class StartService } } - return remote_process($commands, $service->server, type_uuid: $service->uuid, callEventOnFinish: 'ServiceStatusChanged'); + return remote_process($commands, $service->server, type_uuid: $service->uuid); } } diff --git a/app/Actions/Service/StopService.php b/app/Actions/Service/StopService.php index 4bc2ecf03..a7fa4b8b2 100644 --- a/app/Actions/Service/StopService.php +++ b/app/Actions/Service/StopService.php @@ -3,6 +3,8 @@ namespace App\Actions\Service; use App\Actions\Server\CleanupDocker; +use App\Events\ServiceStatusChanged; +use App\Models\Server; use App\Models\Service; use Lorisleiva\Actions\Concerns\AsAction; @@ -20,17 +22,44 @@ class StopService return 'Server is not functional'; } - $containersToStop = $service->getContainersToStop(); - $service->stopContainers($containersToStop, $server); + $containersToStop = []; + $applications = $service->applications()->get(); + foreach ($applications as $application) { + $containersToStop[] = "{$application->name}-{$service->uuid}"; + } + $dbs = $service->databases()->get(); + foreach ($dbs as $db) { + $containersToStop[] = "{$db->name}-{$service->uuid}"; + } + + if (! empty($containersToStop)) { + $this->stopContainersInParallel($containersToStop, $server); + } if ($isDeleteOperation) { $service->deleteConnectedNetworks(); - if ($dockerCleanup) { - CleanupDocker::dispatch($server, true); - } + } + if ($dockerCleanup) { + CleanupDocker::dispatch($server, true); } } catch (\Exception $e) { return $e->getMessage(); + } finally { + ServiceStatusChanged::dispatch($service->environment->project->team->id); } } + + private function stopContainersInParallel(array $containersToStop, Server $server): void + { + $timeout = count($containersToStop) > 5 ? 10 : 30; + $commands = []; + $containerList = implode(' ', $containersToStop); + $commands[] = "docker stop --time=$timeout $containerList"; + $commands[] = "docker rm -f $containerList"; + instant_remote_process( + command: $commands, + server: $server, + throwError: false + ); + } } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 1c5d3e70b..372a6c119 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -12,6 +12,7 @@ use App\Jobs\PullTemplatesFromCDN; use App\Jobs\RegenerateSslCertJob; use App\Jobs\ScheduledTaskJob; use App\Jobs\ServerCheckJob; +use App\Jobs\ServerPatchCheckJob; use App\Jobs\ServerStorageCheckJob; use App\Jobs\UpdateCoolifyJob; use App\Models\InstanceSettings; @@ -51,7 +52,7 @@ class Kernel extends ConsoleKernel } // $this->scheduleInstance->job(new CleanupStaleMultiplexedConnections)->hourly(); - $this->scheduleInstance->command('cleanup:redis')->everyTenMinutes(); + $this->scheduleInstance->command('cleanup:redis')->hourly(); if (isDev()) { // Instance Jobs @@ -175,6 +176,9 @@ class Kernel extends ConsoleKernel } $this->scheduleInstance->job(new DockerCleanupJob($server))->cron($dockerCleanupFrequency)->timezone($serverTimezone)->onOneServer(); + // Server patch check - weekly + $this->scheduleInstance->job(new ServerPatchCheckJob($server))->weekly()->timezone($serverTimezone)->onOneServer(); + // Cleanup multiplexed connections every hour // $this->scheduleInstance->job(new ServerCleanupMux($server))->hourly()->onOneServer(); diff --git a/app/Events/ProxyStarted.php b/app/Events/CloudflareTunnelChanged.php similarity index 90% rename from app/Events/ProxyStarted.php rename to app/Events/CloudflareTunnelChanged.php index 64d562e0a..afa848cc2 100644 --- a/app/Events/ProxyStarted.php +++ b/app/Events/CloudflareTunnelChanged.php @@ -6,7 +6,7 @@ use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; -class ProxyStarted +class CloudflareTunnelChanged { use Dispatchable, InteractsWithSockets, SerializesModels; diff --git a/app/Events/ProxyStatusChanged.php b/app/Events/ProxyStatusChanged.php index 6099d25ef..0cb775eb3 100644 --- a/app/Events/ProxyStatusChanged.php +++ b/app/Events/ProxyStatusChanged.php @@ -3,33 +3,12 @@ namespace App\Events; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; -use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; -class ProxyStatusChanged implements ShouldBroadcast +class ProxyStatusChanged { use Dispatchable, InteractsWithSockets, SerializesModels; - public ?int $teamId = null; - - public function __construct($teamId = null) - { - if (is_null($teamId) && auth()->check() && auth()->user()->currentTeam()) { - $teamId = auth()->user()->currentTeam()->id; - } - $this->teamId = $teamId; - } - - public function broadcastOn(): array - { - if (is_null($this->teamId)) { - return []; - } - - return [ - new PrivateChannel("team.{$this->teamId}"), - ]; - } + public function __construct(public $data) {} } diff --git a/app/Events/ProxyStatusChangedUI.php b/app/Events/ProxyStatusChangedUI.php new file mode 100644 index 000000000..bd99a0f3c --- /dev/null +++ b/app/Events/ProxyStatusChangedUI.php @@ -0,0 +1,35 @@ +check() && auth()->user()->currentTeam()) { + $teamId = auth()->user()->currentTeam()->id; + } + $this->teamId = $teamId; + } + + public function broadcastOn(): array + { + if (is_null($this->teamId)) { + return []; + } + + return [ + new PrivateChannel("team.{$this->teamId}"), + ]; + } +} diff --git a/app/Events/ServerPackageUpdated.php b/app/Events/ServerPackageUpdated.php new file mode 100644 index 000000000..4bde14068 --- /dev/null +++ b/app/Events/ServerPackageUpdated.php @@ -0,0 +1,35 @@ +check() && auth()->user()->currentTeam()) { + $teamId = auth()->user()->currentTeam()->id; + } + $this->teamId = $teamId; + } + + public function broadcastOn(): array + { + if (is_null($this->teamId)) { + return []; + } + + return [ + new PrivateChannel("team.{$this->teamId}"), + ]; + } +} diff --git a/app/Events/ServiceChecked.php b/app/Events/ServiceChecked.php new file mode 100644 index 000000000..3f130a0fb --- /dev/null +++ b/app/Events/ServiceChecked.php @@ -0,0 +1,35 @@ +check() && auth()->user()->currentTeam()) { + $teamId = auth()->user()->currentTeam()->id; + } + $this->teamId = $teamId; + } + + public function broadcastOn(): array + { + if (is_null($this->teamId)) { + return []; + } + + return [ + new PrivateChannel("team.{$this->teamId}"), + ]; + } +} diff --git a/app/Events/ServiceStatusChanged.php b/app/Events/ServiceStatusChanged.php index f5a30e874..97ca4b0f8 100644 --- a/app/Events/ServiceStatusChanged.php +++ b/app/Events/ServiceStatusChanged.php @@ -13,24 +13,22 @@ class ServiceStatusChanged implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; - public int|string|null $userId = null; - - public function __construct($userId = null) - { - if (is_null($userId)) { - $userId = Auth::id() ?? null; + public function __construct( + public ?int $teamId = null + ) { + if (is_null($this->teamId) && Auth::check() && Auth::user()->currentTeam()) { + $this->teamId = Auth::user()->currentTeam()->id; } - $this->userId = $userId; } - public function broadcastOn(): ?array + public function broadcastOn(): array { - if (is_null($this->userId)) { + if (is_null($this->teamId)) { return []; } return [ - new PrivateChannel("user.{$this->userId}"), + new PrivateChannel("team.{$this->teamId}"), ]; } } diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index 3e0627b21..0860c7133 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -187,6 +187,7 @@ class ApplicationsController extends Controller 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], + 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], ], ) ), @@ -306,6 +307,7 @@ class ApplicationsController extends Controller 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], + 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], ], ) ), @@ -425,6 +427,7 @@ class ApplicationsController extends Controller 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], + 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], ], ) ), @@ -528,6 +531,7 @@ class ApplicationsController extends Controller 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], + 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], ], ) ), @@ -628,6 +632,7 @@ class ApplicationsController extends Controller 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], + 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], ], ) ), @@ -691,6 +696,7 @@ class ApplicationsController extends Controller 'description' => ['type' => 'string', 'description' => 'The application description.'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'], 'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'], + 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], ], ) ), @@ -736,7 +742,7 @@ class ApplicationsController extends Controller if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } - $allowedFields = ['project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'private_key_uuid', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'redirect', 'github_app_uuid', 'instant_deploy', 'dockerfile', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'watch_paths', 'use_build_server', 'static_image', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password']; + $allowedFields = ['project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'private_key_uuid', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'redirect', 'github_app_uuid', 'instant_deploy', 'dockerfile', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'watch_paths', 'use_build_server', 'static_image', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password', 'connect_to_docker_network']; $validator = customApiValidator($request->all(), [ 'name' => 'string|max:255', @@ -777,6 +783,7 @@ class ApplicationsController extends Controller $githubAppUuid = $request->github_app_uuid; $useBuildServer = $request->use_build_server; $isStatic = $request->is_static; + $connectToDockerNetwork = $request->connect_to_docker_network; $customNginxConfiguration = $request->custom_nginx_configuration; if (! is_null($customNginxConfiguration)) { @@ -886,6 +893,10 @@ class ApplicationsController extends Controller $application->settings->is_static = $isStatic; $application->settings->save(); } + if (isset($connectToDockerNetwork)) { + $application->settings->connect_to_docker_network = $connectToDockerNetwork; + $application->settings->save(); + } if (isset($useBuildServer)) { $application->settings->is_build_server_enabled = $useBuildServer; $application->settings->save(); @@ -989,7 +1000,33 @@ class ApplicationsController extends Controller $dockerComposeDomainsJson = collect(); if ($request->has('docker_compose_domains')) { - $yaml = Yaml::parse($application->docker_compose_raw); + if (! $request->has('docker_compose_raw')) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => [ + 'docker_compose_raw' => 'The base64 encoded docker_compose_raw is required.', + ], + ], 422); + } + + if (! isBase64Encoded($request->docker_compose_raw)) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => [ + 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', + ], + ], 422); + } + $dockerComposeRaw = base64_decode($request->docker_compose_raw); + if (mb_detect_encoding($dockerComposeRaw, 'ASCII', true) === false) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => [ + 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', + ], + ], 422); + } + $yaml = Yaml::parse($dockerComposeRaw); $services = data_get($yaml, 'services'); $dockerComposeDomains = collect($request->docker_compose_domains); if ($dockerComposeDomains->count() > 0) { @@ -1095,7 +1132,34 @@ class ApplicationsController extends Controller $dockerComposeDomainsJson = collect(); if ($request->has('docker_compose_domains')) { - $yaml = Yaml::parse($application->docker_compose_raw); + if (! $request->has('docker_compose_raw')) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => [ + 'docker_compose_raw' => 'The base64 encoded docker_compose_raw is required.', + ], + ], 422); + } + + if (! isBase64Encoded($request->docker_compose_raw)) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => [ + 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', + ], + ], 422); + } + $dockerComposeRaw = base64_decode($request->docker_compose_raw); + if (mb_detect_encoding($dockerComposeRaw, 'ASCII', true) === false) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => [ + 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', + ], + ], 422); + } + $dockerComposeRaw = base64_decode($request->docker_compose_raw); + $yaml = Yaml::parse($dockerComposeRaw); $services = data_get($yaml, 'services'); $dockerComposeDomains = collect($request->docker_compose_domains); if ($dockerComposeDomains->count() > 0) { @@ -1737,6 +1801,7 @@ class ApplicationsController extends Controller 'docker_compose_domains' => ['type' => 'array', 'description' => 'The Docker Compose domains.'], 'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'], 'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'], + 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], ], ) ), @@ -1790,7 +1855,7 @@ class ApplicationsController extends Controller ], 404); } $server = $application->destination->server; - $allowedFields = ['name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'static_image', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'watch_paths', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'redirect', 'instant_deploy', 'use_build_server', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password']; + $allowedFields = ['name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'static_image', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'watch_paths', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'redirect', 'instant_deploy', 'use_build_server', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password', 'connect_to_docker_network']; $validationRules = [ 'name' => 'string|max:255', @@ -1918,7 +1983,34 @@ class ApplicationsController extends Controller $dockerComposeDomainsJson = collect(); if ($request->has('docker_compose_domains')) { - $yaml = Yaml::parse($application->docker_compose_raw); + if (! $request->has('docker_compose_raw')) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => [ + 'docker_compose_raw' => 'The base64 encoded docker_compose_raw is required.', + ], + ], 422); + } + + if (! isBase64Encoded($request->docker_compose_raw)) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => [ + 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', + ], + ], 422); + } + $dockerComposeRaw = base64_decode($request->docker_compose_raw); + if (mb_detect_encoding($dockerComposeRaw, 'ASCII', true) === false) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => [ + 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', + ], + ], 422); + } + $dockerComposeRaw = base64_decode($request->docker_compose_raw); + $yaml = Yaml::parse($dockerComposeRaw); $services = data_get($yaml, 'services'); $dockerComposeDomains = collect($request->docker_compose_domains); if ($dockerComposeDomains->count() > 0) { @@ -1933,6 +2025,7 @@ class ApplicationsController extends Controller } $instantDeploy = $request->instant_deploy; $isStatic = $request->is_static; + $connectToDockerNetwork = $request->connect_to_docker_network; $useBuildServer = $request->use_build_server; if (isset($useBuildServer)) { @@ -1945,6 +2038,11 @@ class ApplicationsController extends Controller $application->settings->save(); } + if (isset($connectToDockerNetwork)) { + $application->settings->connect_to_docker_network = $connectToDockerNetwork; + $application->settings->save(); + } + removeUnnecessaryFieldsFromRequest($request); $data = $request->all(); diff --git a/app/Http/Controllers/Api/DeployController.php b/app/Http/Controllers/Api/DeployController.php index 46606e24a..5c7f20902 100644 --- a/app/Http/Controllers/Api/DeployController.php +++ b/app/Http/Controllers/Api/DeployController.php @@ -319,9 +319,10 @@ class DeployController extends Controller default: // Database resource StartDatabase::dispatch($resource); - $resource->update([ - 'started_at' => now(), - ]); + + $resource->started_at ??= now(); + $resource->save(); + $message = "Database {$resource->name} started."; break; } diff --git a/app/Http/Controllers/Api/ServicesController.php b/app/Http/Controllers/Api/ServicesController.php index e792779e1..542be83de 100644 --- a/app/Http/Controllers/Api/ServicesController.php +++ b/app/Http/Controllers/Api/ServicesController.php @@ -1428,6 +1428,15 @@ class ServicesController extends Controller format: 'uuid', ) ), + new OA\Parameter( + name: 'latest', + in: 'query', + description: 'Pull latest images.', + schema: new OA\Schema( + type: 'boolean', + default: false, + ) + ), ], responses: [ new OA\Response( @@ -1473,7 +1482,8 @@ class ServicesController extends Controller if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } - RestartService::dispatch($service); + $pullLatest = $request->boolean('latest'); + RestartService::dispatch($service, $pullLatest); return response()->json( [ diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index bebec64cf..eb7686c06 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -5,7 +5,7 @@ namespace App\Jobs; use App\Actions\Docker\GetContainersStatus; use App\Enums\ApplicationDeploymentStatus; use App\Enums\ProcessStatus; -use App\Events\ApplicationStatusChanged; +use App\Events\ServiceStatusChanged; use App\Models\Application; use App\Models\ApplicationDeploymentQueue; use App\Models\ApplicationPreview; @@ -331,7 +331,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue $this->application_deployment_queue->addLogEntry("Gracefully shutting down build container: {$this->deployment_uuid}"); $this->graceful_shutdown_container($this->deployment_uuid); - ApplicationStatusChanged::dispatch(data_get($this->application, 'environment.project.team.id')); + ServiceStatusChanged::dispatch(data_get($this->application, 'environment.project.team.id')); } } @@ -361,9 +361,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue private function post_deployment() { - if ($this->server->isProxyShouldRun()) { - GetContainersStatus::dispatch($this->server); - } + GetContainersStatus::dispatch($this->server); $this->next(ApplicationDeploymentStatus::FINISHED->value); if ($this->pull_request_id !== 0) { if ($this->application->is_github_based()) { @@ -507,7 +505,11 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue if ($this->env_filename) { $command .= " --env-file {$this->workdir}/{$this->env_filename}"; } - $command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build --pull"; + if ($this->force_rebuild) { + $command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build --pull --no-cache"; + } else { + $command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build --pull"; + } $this->execute_remote_command( [executeInDocker($this->deployment_uuid, $command), 'hidden' => true], ); @@ -1590,13 +1592,19 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue } } if ($this->application->environment_variables_preview->where('key', 'COOLIFY_FQDN')->isEmpty()) { - $coolify_envs->put('COOLIFY_FQDN', $this->preview->fqdn); - $coolify_envs->put('COOLIFY_DOMAIN_URL', $this->preview->fqdn); + if ((int) $this->application->compose_parsing_version >= 3) { + $coolify_envs->put('COOLIFY_URL', $this->preview->fqdn); + } else { + $coolify_envs->put('COOLIFY_FQDN', $this->preview->fqdn); + } } if ($this->application->environment_variables_preview->where('key', 'COOLIFY_URL')->isEmpty()) { $url = str($this->preview->fqdn)->replace('http://', '')->replace('https://', ''); - $coolify_envs->put('COOLIFY_URL', $url); - $coolify_envs->put('COOLIFY_DOMAIN_FQDN', $url); + if ((int) $this->application->compose_parsing_version >= 3) { + $coolify_envs->put('COOLIFY_FQDN', $url); + } else { + $coolify_envs->put('COOLIFY_URL', $url); + } } if ($this->application->build_pack !== 'dockercompose' || $this->application->compose_parsing_version === '1' || $this->application->compose_parsing_version === '2') { if ($this->application->environment_variables_preview->where('key', 'COOLIFY_BRANCH')->isEmpty()) { @@ -2428,8 +2436,12 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); queue_next_deployment($this->application); // Never allow changing status from FAILED or CANCELLED_BY_USER to anything else - if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::FAILED->value || - $this->application_deployment_queue->status === ApplicationDeploymentStatus::CANCELLED_BY_USER->value) { + if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::FAILED->value) { + $this->application->environment->project->team?->notify(new DeploymentFailed($this->application, $this->deployment_uuid, $this->preview)); + + return; + } + if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::CANCELLED_BY_USER->value) { return; } @@ -2437,12 +2449,6 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); 'status' => $status, ]); - if ($status === ApplicationDeploymentStatus::FAILED->value) { - $this->application->environment->project->team?->notify(new DeploymentFailed($this->application, $this->deployment_uuid, $this->preview)); - - return; - } - if ($status === ApplicationDeploymentStatus::FINISHED->value) { if (! $this->only_this_server) { $this->deploy_to_additional_destinations(); diff --git a/app/Jobs/DatabaseBackupJob.php b/app/Jobs/DatabaseBackupJob.php index 5e8dc581a..a6c423cac 100644 --- a/app/Jobs/DatabaseBackupJob.php +++ b/app/Jobs/DatabaseBackupJob.php @@ -54,6 +54,10 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue public ?string $postgres_password = null; + public ?string $mongo_root_username = null; + + public ?string $mongo_root_password = null; + public ?S3Storage $s3 = null; public function __construct(public ScheduledDatabaseBackup $backup) @@ -189,6 +193,40 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue throw new \Exception('MARIADB_DATABASE or MYSQL_DATABASE not found'); } } + } elseif (str($databaseType)->contains('mongo')) { + $databasesToBackup = ['*']; + $this->container_name = "{$this->database->name}-$serviceUuid"; + $this->directory_name = $serviceName.'-'.$this->container_name; + + // Try to extract MongoDB credentials from environment variables + try { + $commands = []; + $commands[] = "docker exec $this->container_name env | grep MONGO_INITDB_"; + $envs = instant_remote_process($commands, $this->server); + + if (filled($envs)) { + $envs = str($envs)->explode("\n"); + $rootPassword = $envs->filter(function ($env) { + return str($env)->startsWith('MONGO_INITDB_ROOT_PASSWORD='); + })->first(); + if ($rootPassword) { + $this->mongo_root_password = str($rootPassword)->after('MONGO_INITDB_ROOT_PASSWORD=')->value(); + } + $rootUsername = $envs->filter(function ($env) { + return str($env)->startsWith('MONGO_INITDB_ROOT_USERNAME='); + })->first(); + if ($rootUsername) { + $this->mongo_root_username = str($rootUsername)->after('MONGO_INITDB_ROOT_USERNAME=')->value(); + } + } + \Log::info('MongoDB credentials extracted from environment', [ + 'has_username' => filled($this->mongo_root_username), + 'has_password' => filled($this->mongo_root_password), + ]); + } catch (\Throwable $e) { + \Log::warning('Failed to extract MongoDB environment variables', ['error' => $e->getMessage()]); + // Continue without env vars - will be handled in backup_standalone_mongodb method + } } } else { $databaseName = str($this->database->name)->slug()->value(); @@ -200,7 +238,7 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue if (blank($databasesToBackup)) { if (str($databaseType)->contains('postgres')) { $databasesToBackup = [$this->database->postgres_db]; - } elseif (str($databaseType)->contains('mongodb')) { + } elseif (str($databaseType)->contains('mongo')) { $databasesToBackup = ['*']; } elseif (str($databaseType)->contains('mysql')) { $databasesToBackup = [$this->database->mysql_database]; @@ -214,10 +252,13 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue // Format: db1,db2,db3 $databasesToBackup = explode(',', $databasesToBackup); $databasesToBackup = array_map('trim', $databasesToBackup); - } elseif (str($databaseType)->contains('mongodb')) { + } elseif (str($databaseType)->contains('mongo')) { // Format: db1:collection1,collection2|db2:collection3,collection4 - $databasesToBackup = explode('|', $databasesToBackup); - $databasesToBackup = array_map('trim', $databasesToBackup); + // Only explode if it's a string, not if it's already an array + if (is_string($databasesToBackup)) { + $databasesToBackup = explode('|', $databasesToBackup); + $databasesToBackup = array_map('trim', $databasesToBackup); + } } elseif (str($databaseType)->contains('mysql')) { // Format: db1,db2,db3 $databasesToBackup = explode(',', $databasesToBackup); @@ -252,7 +293,7 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue 'scheduled_database_backup_id' => $this->backup->id, ]); $this->backup_standalone_postgresql($database); - } elseif (str($databaseType)->contains('mongodb')) { + } elseif (str($databaseType)->contains('mongo')) { if ($database === '*') { $database = 'all'; $databaseName = 'all'; @@ -343,6 +384,17 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue { try { $url = $this->database->internal_db_url; + if (blank($url)) { + // For service-based MongoDB, try to build URL from environment variables + if (filled($this->mongo_root_username) && filled($this->mongo_root_password)) { + // Use container name instead of server IP for service-based MongoDB + $url = "mongodb://{$this->mongo_root_username}:{$this->mongo_root_password}@{$this->container_name}:27017"; + } else { + // If no environment variables are available, throw an exception + throw new \Exception('MongoDB credentials not found. Ensure MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD environment variables are available in the container.'); + } + } + \Log::info('MongoDB backup URL configured', ['has_url' => filled($url), 'using_env_vars' => blank($this->database->internal_db_url)]); if ($databaseWithCollections === 'all') { $commands[] = 'mkdir -p '.$this->backup_dir; if (str($this->database->image)->startsWith('mongo:4')) { diff --git a/app/Jobs/DockerCleanupJob.php b/app/Jobs/DockerCleanupJob.php index 05a4aa8de..00dfd150a 100644 --- a/app/Jobs/DockerCleanupJob.php +++ b/app/Jobs/DockerCleanupJob.php @@ -31,7 +31,7 @@ class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue public function middleware(): array { - return [(new WithoutOverlapping($this->server->uuid))->dontRelease()]; + return [(new WithoutOverlapping('docker-cleanup-'.$this->server->uuid))->dontRelease()]; } public function __construct(public Server $server, public bool $manualCleanup = false) {} diff --git a/app/Jobs/PushServerUpdateJob.php b/app/Jobs/PushServerUpdateJob.php index 93b203fcb..65c72c8c9 100644 --- a/app/Jobs/PushServerUpdateJob.php +++ b/app/Jobs/PushServerUpdateJob.php @@ -9,7 +9,6 @@ use App\Actions\Proxy\StartProxy; use App\Actions\Server\StartLogDrain; use App\Actions\Shared\ComplexStatusCheck; use App\Models\Application; -use App\Models\ApplicationPreview; use App\Models\Server; use App\Models\ServiceApplication; use App\Models\ServiceDatabase; @@ -71,7 +70,7 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue public function middleware(): array { - return [(new WithoutOverlapping($this->server->uuid))->dontRelease()]; + return [(new WithoutOverlapping('push-server-update-'.$this->server->uuid))->dontRelease()]; } public function backoff(): int @@ -122,7 +121,9 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue $this->allApplicationsWithAdditionalServers = $this->applications->filter(function ($application) { return $application->additional_servers->count() > 0; }); - $this->allApplicationPreviewsIds = $this->previews->pluck('id'); + $this->allApplicationPreviewsIds = $this->previews->map(function ($preview) { + return $preview->application_id.':'.$preview->pull_request_id; + }); $this->allDatabaseUuids = $this->databases->pluck('uuid'); $this->allTcpProxyUuids = $this->databases->where('is_public', true)->pluck('uuid'); $this->services->each(function ($service) { @@ -147,7 +148,7 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue } if ($labels->has('coolify.applicationId')) { $applicationId = $labels->get('coolify.applicationId'); - $pullRequestId = data_get($labels, 'coolify.pullRequestId', '0'); + $pullRequestId = $labels->get('coolify.pullRequestId', '0'); try { if ($pullRequestId === '0') { if ($this->allApplicationIds->contains($applicationId) && $this->isRunning($containerStatus)) { @@ -155,10 +156,11 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue } $this->updateApplicationStatus($applicationId, $containerStatus); } else { - if ($this->allApplicationPreviewsIds->contains($applicationId) && $this->isRunning($containerStatus)) { - $this->foundApplicationPreviewsIds->push($applicationId); + $previewKey = $applicationId.':'.$pullRequestId; + if ($this->allApplicationPreviewsIds->contains($previewKey) && $this->isRunning($containerStatus)) { + $this->foundApplicationPreviewsIds->push($previewKey); } - $this->updateApplicationPreviewStatus($applicationId, $containerStatus); + $this->updateApplicationPreviewStatus($applicationId, $pullRequestId, $containerStatus); } } catch (\Exception $e) { } @@ -211,18 +213,24 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue if (! $application) { return; } - $application->status = $containerStatus; - $application->save(); + if ($application->status !== $containerStatus) { + $application->status = $containerStatus; + $application->save(); + } } - private function updateApplicationPreviewStatus(string $applicationId, string $containerStatus) + private function updateApplicationPreviewStatus(string $applicationId, string $pullRequestId, string $containerStatus) { - $application = $this->previews->where('id', $applicationId)->first(); + $application = $this->previews->where('application_id', $applicationId) + ->where('pull_request_id', $pullRequestId) + ->first(); if (! $application) { return; } - $application->status = $containerStatus; - $application->save(); + if ($application->status !== $containerStatus) { + $application->status = $containerStatus; + $application->save(); + } } private function updateNotFoundApplicationStatus() @@ -232,8 +240,21 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue $notFoundApplicationIds->each(function ($applicationId) { $application = Application::find($applicationId); if ($application) { - $application->status = 'exited'; - $application->save(); + // Don't mark as exited if already exited + if (str($application->status)->startsWith('exited')) { + return; + } + + // Only protection: Verify we received any container data at all + // If containers collection is completely empty, Sentinel might have failed + if ($this->containers->isEmpty()) { + return; + } + + if ($application->status !== 'exited') { + $application->status = 'exited'; + $application->save(); + } } }); } @@ -243,11 +264,36 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue { $notFoundApplicationPreviewsIds = $this->allApplicationPreviewsIds->diff($this->foundApplicationPreviewsIds); if ($notFoundApplicationPreviewsIds->isNotEmpty()) { - $notFoundApplicationPreviewsIds->each(function ($applicationPreviewId) { - $applicationPreview = ApplicationPreview::find($applicationPreviewId); + $notFoundApplicationPreviewsIds->each(function ($previewKey) { + // Parse the previewKey format "application_id:pull_request_id" + $parts = explode(':', $previewKey); + if (count($parts) !== 2) { + return; + } + + $applicationId = $parts[0]; + $pullRequestId = $parts[1]; + + $applicationPreview = $this->previews->where('application_id', $applicationId) + ->where('pull_request_id', $pullRequestId) + ->first(); + if ($applicationPreview) { - $applicationPreview->status = 'exited'; - $applicationPreview->save(); + // Don't mark as exited if already exited + if (str($applicationPreview->status)->startsWith('exited')) { + return; + } + + // Only protection: Verify we received any container data at all + // If containers collection is completely empty, Sentinel might have failed + if ($this->containers->isEmpty()) { + + return; + } + if ($applicationPreview->status !== 'exited') { + $applicationPreview->status = 'exited'; + $applicationPreview->save(); + } } }); } @@ -260,7 +306,7 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue if ($this->foundProxy === false) { try { if (CheckProxy::run($this->server)) { - StartProxy::run($this->server, false); + StartProxy::run($this->server, async: false); $this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server)); } } catch (\Throwable $e) { @@ -278,8 +324,10 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue if (! $database) { return; } - $database->status = $containerStatus; - $database->save(); + if ($database->status !== $containerStatus) { + $database->status = $containerStatus; + $database->save(); + } if ($this->isRunning($containerStatus) && $tcpProxy) { $tcpProxyContainerFound = $this->containers->filter(function ($value, $key) use ($databaseUuid) { return data_get($value, 'name') === "$databaseUuid-proxy" && data_get($value, 'state') === 'running'; @@ -299,8 +347,10 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue $notFoundDatabaseUuids->each(function ($databaseUuid) { $database = $this->databases->where('uuid', $databaseUuid)->first(); if ($database) { - $database->status = 'exited'; - $database->save(); + if ($database->status !== 'exited') { + $database->status = 'exited'; + $database->save(); + } if ($database->is_public) { StopDatabaseProxy::dispatch($database); } @@ -317,13 +367,20 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue } if ($subType === 'application') { $application = $service->applications()->where('id', $subId)->first(); - $application->status = $containerStatus; - $application->save(); + if ($application) { + if ($application->status !== $containerStatus) { + $application->status = $containerStatus; + $application->save(); + } + } } elseif ($subType === 'database') { $database = $service->databases()->where('id', $subId)->first(); - $database->status = $containerStatus; - $database->save(); - } else { + if ($database) { + if ($database->status !== $containerStatus) { + $database->status = $containerStatus; + $database->save(); + } + } } } @@ -335,8 +392,10 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue $notFoundServiceApplicationIds->each(function ($serviceApplicationId) { $application = ServiceApplication::find($serviceApplicationId); if ($application) { - $application->status = 'exited'; - $application->save(); + if ($application->status !== 'exited') { + $application->status = 'exited'; + $application->save(); + } } }); } @@ -344,8 +403,10 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue $notFoundServiceDatabaseIds->each(function ($serviceDatabaseId) { $database = ServiceDatabase::find($serviceDatabaseId); if ($database) { - $database->status = 'exited'; - $database->save(); + if ($database->status !== 'exited') { + $database->status = 'exited'; + $database->save(); + } } }); } diff --git a/app/Jobs/RestartProxyJob.php b/app/Jobs/RestartProxyJob.php index 7fc716f70..49cfbba53 100644 --- a/app/Jobs/RestartProxyJob.php +++ b/app/Jobs/RestartProxyJob.php @@ -2,7 +2,6 @@ namespace App\Jobs; -use App\Actions\Proxy\CheckProxy; use App\Actions\Proxy\StartProxy; use App\Actions\Proxy\StopProxy; use App\Models\Server; @@ -24,7 +23,7 @@ class RestartProxyJob implements ShouldBeEncrypted, ShouldQueue public function middleware(): array { - return [(new WithoutOverlapping($this->server->uuid))->dontRelease()]; + return [(new WithoutOverlapping('restart-proxy-'.$this->server->uuid))->dontRelease()]; } public function __construct(public Server $server) {} @@ -36,9 +35,9 @@ class RestartProxyJob implements ShouldBeEncrypted, ShouldQueue $this->server->proxy->force_stop = false; $this->server->save(); + StartProxy::run($this->server, force: true); - CheckProxy::run($this->server, true); } catch (\Throwable $e) { return handleError($e); } diff --git a/app/Jobs/ServerCheckJob.php b/app/Jobs/ServerCheckJob.php index 9818d5c6a..dcbac9ac3 100644 --- a/app/Jobs/ServerCheckJob.php +++ b/app/Jobs/ServerCheckJob.php @@ -28,7 +28,7 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue public function middleware(): array { - return [(new WithoutOverlapping($this->server->uuid))->dontRelease()]; + return [(new WithoutOverlapping('server-check-'.$this->server->uuid))->dontRelease()]; } public function __construct(public Server $server) {} @@ -68,7 +68,7 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue try { $shouldStart = CheckProxy::run($this->server); if ($shouldStart) { - StartProxy::run($this->server, false); + StartProxy::run($this->server, async: false); $this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server)); } } catch (\Throwable $e) { diff --git a/app/Jobs/ServerPatchCheckJob.php b/app/Jobs/ServerPatchCheckJob.php new file mode 100644 index 000000000..7d1b853b1 --- /dev/null +++ b/app/Jobs/ServerPatchCheckJob.php @@ -0,0 +1,68 @@ +server->uuid))->dontRelease()]; + } + + public function __construct(public Server $server) {} + + public function handle(): void + { + try { + if ($this->server->serverStatus() === false) { + return; + } + + $team = data_get($this->server, 'team'); + if (! $team) { + return; + } + + // Check for updates + $patchData = CheckUpdates::run($this->server); + + if (isset($patchData['error'])) { + $team->notify(new ServerPatchCheck($this->server, $patchData)); + + return; // Skip if there's an error checking for updates + } + + $totalUpdates = $patchData['total_updates'] ?? 0; + + // Only send notification if there are updates available + if ($totalUpdates > 0) { + $team->notify(new ServerPatchCheck($this->server, $patchData)); + } + } catch (\Throwable $e) { + // Log error but don't fail the job + \Illuminate\Support\Facades\Log::error('ServerPatchCheckJob failed: '.$e->getMessage(), [ + 'server_id' => $this->server->id, + 'server_name' => $this->server->name, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString(), + ]); + } + } +} diff --git a/app/Listeners/CloudflareTunnelChangedNotification.php b/app/Listeners/CloudflareTunnelChangedNotification.php new file mode 100644 index 000000000..34e713f95 --- /dev/null +++ b/app/Listeners/CloudflareTunnelChangedNotification.php @@ -0,0 +1,66 @@ +server = Server::where('id', $server_id)->firstOrFail(); + + // Check if cloudflare tunnel is running (container is healthy) - try 3 times with 5 second intervals + $cloudflareHealthy = false; + $attempts = 3; + + for ($i = 1; $i <= $attempts; $i++) { + \Log::debug("Cloudflare health check attempt {$i}/{$attempts}", ['server_id' => $server_id]); + $result = instant_remote_process_with_timeout(['docker inspect coolify-cloudflared | jq -e ".[0].State.Health.Status == \"healthy\""'], $this->server, false, 10); + + if (blank($result)) { + \Log::debug("Cloudflare Tunnels container not found on attempt {$i}", ['server_id' => $server_id]); + } elseif ($result === 'true') { + \Log::debug("Cloudflare Tunnels container healthy on attempt {$i}", ['server_id' => $server_id]); + $cloudflareHealthy = true; + break; + } else { + \Log::debug("Cloudflare Tunnels container not healthy on attempt {$i}", ['server_id' => $server_id, 'result' => $result]); + } + + // Sleep between attempts (except after the last attempt) + if ($i < $attempts) { + Sleep::for(5)->seconds(); + } + } + + if (! $cloudflareHealthy) { + \Log::error('Cloudflare Tunnels container failed all health checks.', ['server_id' => $server_id, 'attempts' => $attempts]); + + return; + } + $this->server->settings->update([ + 'is_cloudflare_tunnel' => true, + ]); + + // Only update IP if it's not already set to the ssh_domain or if it's empty + if ($this->server->ip !== $ssh_domain && ! empty($ssh_domain)) { + \Log::debug('Cloudflare Tunnels configuration updated - updating IP address.', ['old_ip' => $this->server->ip, 'new_ip' => $ssh_domain]); + $this->server->update(['ip' => $ssh_domain]); + } else { + \Log::debug('Cloudflare Tunnels configuration updated - IP address unchanged.', ['current_ip' => $this->server->ip]); + } + $teamId = $this->server->team_id; + CloudflareTunnelConfigured::dispatch($teamId); + } +} diff --git a/app/Listeners/ProxyStartedNotification.php b/app/Listeners/ProxyStartedNotification.php deleted file mode 100644 index 9045b1e5c..000000000 --- a/app/Listeners/ProxyStartedNotification.php +++ /dev/null @@ -1,22 +0,0 @@ -server = data_get($event, 'data'); - $this->server->setupDefaultRedirect(); - $this->server->setupDynamicProxyConfiguration(); - $this->server->proxy->force_stop = false; - $this->server->save(); - } -} diff --git a/app/Listeners/ProxyStatusChangedNotification.php b/app/Listeners/ProxyStatusChangedNotification.php new file mode 100644 index 000000000..7b23724e2 --- /dev/null +++ b/app/Listeners/ProxyStatusChangedNotification.php @@ -0,0 +1,42 @@ +data; + if (is_null($serverId)) { + return; + } + $server = Server::where('id', $serverId)->first(); + if (is_null($server)) { + return; + } + $proxyContainerName = 'coolify-proxy'; + $status = getContainerStatus($server, $proxyContainerName); + $server->proxy->set('status', $status); + $server->save(); + + ProxyStatusChangedUI::dispatch($server->team_id); + if ($status === 'running') { + $server->setupDefaultRedirect(); + $server->setupDynamicProxyConfiguration(); + $server->proxy->force_stop = false; + $server->save(); + } + if ($status === 'created') { + instant_remote_process([ + 'docker rm -f coolify-proxy', + ], $server); + } + } +} diff --git a/app/Livewire/ActivityMonitor.php b/app/Livewire/ActivityMonitor.php index 024f53c3d..54034ef7a 100644 --- a/app/Livewire/ActivityMonitor.php +++ b/app/Livewire/ActivityMonitor.php @@ -14,20 +14,25 @@ class ActivityMonitor extends Component public $eventToDispatch = 'activityFinished'; + public $eventData = null; + public $isPollingActive = false; public bool $fullHeight = false; - public bool $showWaiting = false; + public $activity; - protected $activity; + public bool $showWaiting = true; + + public static $eventDispatched = false; protected $listeners = ['activityMonitor' => 'newMonitorActivity']; - public function newMonitorActivity($activityId, $eventToDispatch = 'activityFinished') + public function newMonitorActivity($activityId, $eventToDispatch = 'activityFinished', $eventData = null) { $this->activityId = $activityId; $this->eventToDispatch = $eventToDispatch; + $this->eventData = $eventData; $this->hydrateActivity(); @@ -51,15 +56,27 @@ class ActivityMonitor extends Component $causer_id = data_get($this->activity, 'causer_id'); $user = User::find($causer_id); if ($user) { - foreach ($user->teams as $team) { - $teamId = $team->id; - $this->eventToDispatch::dispatch($teamId); + $teamId = $user->currentTeam()->id; + if (! self::$eventDispatched) { + if (filled($this->eventData)) { + $this->eventToDispatch::dispatch($teamId, $this->eventData); + } else { + $this->eventToDispatch::dispatch($teamId); + } + self::$eventDispatched = true; } } return; } - $this->dispatch($this->eventToDispatch); + if (! self::$eventDispatched) { + if (filled($this->eventData)) { + $this->dispatch($this->eventToDispatch, $this->eventData); + } else { + $this->dispatch($this->eventToDispatch); + } + self::$eventDispatched = true; + } } } } diff --git a/app/Livewire/NewActivityMonitor.php b/app/Livewire/NewActivityMonitor.php deleted file mode 100644 index a9334e710..000000000 --- a/app/Livewire/NewActivityMonitor.php +++ /dev/null @@ -1,74 +0,0 @@ - 'newMonitorActivity']; - - public function newMonitorActivity($activityId, $eventToDispatch = 'activityFinished', $eventData = null) - { - $this->activityId = $activityId; - $this->eventToDispatch = $eventToDispatch; - $this->eventData = $eventData; - - $this->hydrateActivity(); - - $this->isPollingActive = true; - } - - public function hydrateActivity() - { - $this->activity = Activity::find($this->activityId); - } - - public function polling() - { - $this->hydrateActivity(); - // $this->setStatus(ProcessStatus::IN_PROGRESS); - $exit_code = data_get($this->activity, 'properties.exitCode'); - if ($exit_code !== null) { - // if ($exit_code === 0) { - // // $this->setStatus(ProcessStatus::FINISHED); - // } else { - // // $this->setStatus(ProcessStatus::ERROR); - // } - $this->isPollingActive = false; - if ($this->eventToDispatch !== null) { - if (str($this->eventToDispatch)->startsWith('App\\Events\\')) { - $causer_id = data_get($this->activity, 'causer_id'); - $user = User::find($causer_id); - if ($user) { - foreach ($user->teams as $team) { - $teamId = $team->id; - $this->eventToDispatch::dispatch($teamId); - } - } - - return; - } - if (! is_null($this->eventData)) { - $this->dispatch($this->eventToDispatch, $this->eventData); - } else { - $this->dispatch($this->eventToDispatch); - } - } - } - } -} diff --git a/app/Livewire/Notifications/Discord.php b/app/Livewire/Notifications/Discord.php index 9489eb128..e0425fa17 100644 --- a/app/Livewire/Notifications/Discord.php +++ b/app/Livewire/Notifications/Discord.php @@ -56,6 +56,9 @@ class Discord extends Component #[Validate(['boolean'])] public bool $serverUnreachableDiscordNotifications = true; + #[Validate(['boolean'])] + public bool $serverPatchDiscordNotifications = false; + #[Validate(['boolean'])] public bool $discordPingEnabled = true; @@ -89,6 +92,7 @@ class Discord extends Component $this->settings->server_disk_usage_discord_notifications = $this->serverDiskUsageDiscordNotifications; $this->settings->server_reachable_discord_notifications = $this->serverReachableDiscordNotifications; $this->settings->server_unreachable_discord_notifications = $this->serverUnreachableDiscordNotifications; + $this->settings->server_patch_discord_notifications = $this->serverPatchDiscordNotifications; $this->settings->discord_ping_enabled = $this->discordPingEnabled; @@ -110,6 +114,7 @@ class Discord extends Component $this->serverDiskUsageDiscordNotifications = $this->settings->server_disk_usage_discord_notifications; $this->serverReachableDiscordNotifications = $this->settings->server_reachable_discord_notifications; $this->serverUnreachableDiscordNotifications = $this->settings->server_unreachable_discord_notifications; + $this->serverPatchDiscordNotifications = $this->settings->server_patch_discord_notifications; $this->discordPingEnabled = $this->settings->discord_ping_enabled; } diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php index c5f518e16..897e6cf06 100644 --- a/app/Livewire/Notifications/Email.php +++ b/app/Livewire/Notifications/Email.php @@ -98,6 +98,9 @@ class Email extends Component #[Validate(['boolean'])] public bool $serverUnreachableEmailNotifications = true; + #[Validate(['boolean'])] + public bool $serverPatchEmailNotifications = false; + #[Validate(['nullable', 'email'])] public ?string $testEmailAddress = null; @@ -146,6 +149,7 @@ class Email extends Component $this->settings->server_disk_usage_email_notifications = $this->serverDiskUsageEmailNotifications; $this->settings->server_reachable_email_notifications = $this->serverReachableEmailNotifications; $this->settings->server_unreachable_email_notifications = $this->serverUnreachableEmailNotifications; + $this->settings->server_patch_email_notifications = $this->serverPatchEmailNotifications; $this->settings->save(); } else { @@ -177,6 +181,7 @@ class Email extends Component $this->serverDiskUsageEmailNotifications = $this->settings->server_disk_usage_email_notifications; $this->serverReachableEmailNotifications = $this->settings->server_reachable_email_notifications; $this->serverUnreachableEmailNotifications = $this->settings->server_unreachable_email_notifications; + $this->serverPatchEmailNotifications = $this->settings->server_patch_email_notifications; } } @@ -320,7 +325,7 @@ class Email extends Component 'test-email:'.$this->team->id, $perMinute = 0, function () { - $this->team?->notify(new Test($this->testEmailAddress, 'email')); + $this->team?->notifyNow(new Test($this->testEmailAddress, 'email')); $this->dispatch('success', 'Test Email sent.'); }, $decaySeconds = 10, diff --git a/app/Livewire/Notifications/Pushover.php b/app/Livewire/Notifications/Pushover.php index f1e4c464d..bd5ab79c8 100644 --- a/app/Livewire/Notifications/Pushover.php +++ b/app/Livewire/Notifications/Pushover.php @@ -64,6 +64,9 @@ class Pushover extends Component #[Validate(['boolean'])] public bool $serverUnreachablePushoverNotifications = true; + #[Validate(['boolean'])] + public bool $serverPatchPushoverNotifications = false; + public function mount() { try { @@ -95,6 +98,7 @@ class Pushover extends Component $this->settings->server_disk_usage_pushover_notifications = $this->serverDiskUsagePushoverNotifications; $this->settings->server_reachable_pushover_notifications = $this->serverReachablePushoverNotifications; $this->settings->server_unreachable_pushover_notifications = $this->serverUnreachablePushoverNotifications; + $this->settings->server_patch_pushover_notifications = $this->serverPatchPushoverNotifications; $this->settings->save(); refreshSession(); @@ -115,6 +119,7 @@ class Pushover extends Component $this->serverDiskUsagePushoverNotifications = $this->settings->server_disk_usage_pushover_notifications; $this->serverReachablePushoverNotifications = $this->settings->server_reachable_pushover_notifications; $this->serverUnreachablePushoverNotifications = $this->settings->server_unreachable_pushover_notifications; + $this->serverPatchPushoverNotifications = $this->settings->server_patch_pushover_notifications; } } diff --git a/app/Livewire/Notifications/Slack.php b/app/Livewire/Notifications/Slack.php index f47ad8a97..9c847ce57 100644 --- a/app/Livewire/Notifications/Slack.php +++ b/app/Livewire/Notifications/Slack.php @@ -61,6 +61,9 @@ class Slack extends Component #[Validate(['boolean'])] public bool $serverUnreachableSlackNotifications = true; + #[Validate(['boolean'])] + public bool $serverPatchSlackNotifications = false; + public function mount() { try { @@ -91,6 +94,7 @@ class Slack extends Component $this->settings->server_disk_usage_slack_notifications = $this->serverDiskUsageSlackNotifications; $this->settings->server_reachable_slack_notifications = $this->serverReachableSlackNotifications; $this->settings->server_unreachable_slack_notifications = $this->serverUnreachableSlackNotifications; + $this->settings->server_patch_slack_notifications = $this->serverPatchSlackNotifications; $this->settings->save(); refreshSession(); @@ -110,6 +114,7 @@ class Slack extends Component $this->serverDiskUsageSlackNotifications = $this->settings->server_disk_usage_slack_notifications; $this->serverReachableSlackNotifications = $this->settings->server_reachable_slack_notifications; $this->serverUnreachableSlackNotifications = $this->settings->server_unreachable_slack_notifications; + $this->serverPatchSlackNotifications = $this->settings->server_patch_slack_notifications; } } diff --git a/app/Livewire/Notifications/Telegram.php b/app/Livewire/Notifications/Telegram.php index 01afb4ac6..07393d4ea 100644 --- a/app/Livewire/Notifications/Telegram.php +++ b/app/Livewire/Notifications/Telegram.php @@ -64,6 +64,9 @@ class Telegram extends Component #[Validate(['boolean'])] public bool $serverUnreachableTelegramNotifications = true; + #[Validate(['boolean'])] + public bool $serverPatchTelegramNotifications = false; + #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsDeploymentSuccessThreadId = null; @@ -100,6 +103,9 @@ class Telegram extends Component #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsServerUnreachableThreadId = null; + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsServerPatchThreadId = null; + public function mount() { try { @@ -131,6 +137,7 @@ class Telegram extends Component $this->settings->server_disk_usage_telegram_notifications = $this->serverDiskUsageTelegramNotifications; $this->settings->server_reachable_telegram_notifications = $this->serverReachableTelegramNotifications; $this->settings->server_unreachable_telegram_notifications = $this->serverUnreachableTelegramNotifications; + $this->settings->server_patch_telegram_notifications = $this->serverPatchTelegramNotifications; $this->settings->telegram_notifications_deployment_success_thread_id = $this->telegramNotificationsDeploymentSuccessThreadId; $this->settings->telegram_notifications_deployment_failure_thread_id = $this->telegramNotificationsDeploymentFailureThreadId; @@ -144,6 +151,7 @@ class Telegram extends Component $this->settings->telegram_notifications_server_disk_usage_thread_id = $this->telegramNotificationsServerDiskUsageThreadId; $this->settings->telegram_notifications_server_reachable_thread_id = $this->telegramNotificationsServerReachableThreadId; $this->settings->telegram_notifications_server_unreachable_thread_id = $this->telegramNotificationsServerUnreachableThreadId; + $this->settings->telegram_notifications_server_patch_thread_id = $this->telegramNotificationsServerPatchThreadId; $this->settings->save(); } else { @@ -163,6 +171,7 @@ class Telegram extends Component $this->serverDiskUsageTelegramNotifications = $this->settings->server_disk_usage_telegram_notifications; $this->serverReachableTelegramNotifications = $this->settings->server_reachable_telegram_notifications; $this->serverUnreachableTelegramNotifications = $this->settings->server_unreachable_telegram_notifications; + $this->serverPatchTelegramNotifications = $this->settings->server_patch_telegram_notifications; $this->telegramNotificationsDeploymentSuccessThreadId = $this->settings->telegram_notifications_deployment_success_thread_id; $this->telegramNotificationsDeploymentFailureThreadId = $this->settings->telegram_notifications_deployment_failure_thread_id; @@ -176,6 +185,7 @@ class Telegram extends Component $this->telegramNotificationsServerDiskUsageThreadId = $this->settings->telegram_notifications_server_disk_usage_thread_id; $this->telegramNotificationsServerReachableThreadId = $this->settings->telegram_notifications_server_reachable_thread_id; $this->telegramNotificationsServerUnreachableThreadId = $this->settings->telegram_notifications_server_unreachable_thread_id; + $this->telegramNotificationsServerPatchThreadId = $this->settings->telegram_notifications_server_patch_thread_id; } } diff --git a/app/Livewire/Project/Application/Configuration.php b/app/Livewire/Project/Application/Configuration.php index 267ca72ad..5d7f3fd31 100644 --- a/app/Livewire/Project/Application/Configuration.php +++ b/app/Livewire/Project/Application/Configuration.php @@ -17,7 +17,17 @@ class Configuration extends Component public $servers; - protected $listeners = ['buildPackUpdated' => '$refresh']; + public function getListeners() + { + $teamId = auth()->user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},ServiceChecked" => '$refresh', + "echo-private:team.{$teamId},ServiceStatusChanged" => '$refresh', + 'buildPackUpdated' => '$refresh', + 'refresh' => '$refresh', + ]; + } public function mount() { @@ -40,6 +50,11 @@ class Configuration extends Component $this->project = $project; $this->environment = $environment; $this->application = $application; + + if ($this->application->deploymentType() === 'deploy_key' && $this->currentRoute === 'project.application.preview-deployments') { + return redirect()->route('project.application.configuration', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]); + } + if ($this->application->build_pack === 'dockercompose' && $this->currentRoute === 'project.application.healthcheck') { return redirect()->route('project.application.configuration', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]); } diff --git a/app/Livewire/Project/Application/Deployment/Index.php b/app/Livewire/Project/Application/Deployment/Index.php index 0567a6e8a..c957615ac 100644 --- a/app/Livewire/Project/Application/Deployment/Index.php +++ b/app/Livewire/Project/Application/Deployment/Index.php @@ -28,6 +28,15 @@ class Index extends Component protected $queryString = ['pull_request_id']; + public function getListeners() + { + $teamId = auth()->user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},ServiceChecked" => '$refresh', + ]; + } + public function mount() { $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); diff --git a/app/Livewire/Project/Application/Deployment/Show.php b/app/Livewire/Project/Application/Deployment/Show.php index 7b2ac09d3..cdac47d3d 100644 --- a/app/Livewire/Project/Application/Deployment/Show.php +++ b/app/Livewire/Project/Application/Deployment/Show.php @@ -18,7 +18,15 @@ class Show extends Component public $isKeepAliveOn = true; - protected $listeners = ['refreshQueue']; + public function getListeners() + { + $teamId = auth()->user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},ServiceChecked" => '$refresh', + 'refreshQueue', + ]; + } public function mount() { diff --git a/app/Livewire/Project/Application/Heading.php b/app/Livewire/Project/Application/Heading.php index 5b0ae12ef..9fd4da68a 100644 --- a/app/Livewire/Project/Application/Heading.php +++ b/app/Livewire/Project/Application/Heading.php @@ -4,7 +4,6 @@ namespace App\Livewire\Project\Application; use App\Actions\Application\StopApplication; use App\Actions\Docker\GetContainersStatus; -use App\Events\ApplicationStatusChanged; use App\Models\Application; use Livewire\Component; use Visus\Cuid2\Cuid2; @@ -28,7 +27,8 @@ class Heading extends Component $teamId = auth()->user()->currentTeam()->id; return [ - "echo-private:team.{$teamId},ApplicationStatusChanged" => 'check_status', + "echo-private:team.{$teamId},ServiceStatusChanged" => 'checkStatus', + "echo-private:team.{$teamId},ServiceChecked" => '$refresh', 'compose_loaded' => '$refresh', 'update_links' => '$refresh', ]; @@ -46,13 +46,12 @@ class Heading extends Component $this->lastDeploymentLink = $this->application->gitCommitLink(data_get($lastDeployment, 'commit')); } - public function check_status($showNotification = false) + public function checkStatus() { if ($this->application->destination->server->isFunctional()) { GetContainersStatus::dispatch($this->application->destination->server); - } - if ($showNotification) { - $this->dispatch('success', 'Success', 'Application status updated.'); + } else { + $this->dispatch('error', 'Server is not functional.'); } } @@ -111,16 +110,8 @@ class Heading extends Component public function stop() { - StopApplication::run($this->application, false, $this->docker_cleanup); - $this->application->status = 'exited'; - $this->application->save(); - if ($this->application->additional_servers->count() > 0) { - $this->application->additional_servers->each(function ($server) { - $server->pivot->status = 'exited:unhealthy'; - $server->pivot->save(); - }); - } - ApplicationStatusChanged::dispatch(data_get($this->application, 'environment.project.team.id')); + $this->dispatch('info', 'Gracefully stopping application.
It could take a while depending on the application.'); + StopApplication::dispatch($this->application, false, $this->docker_cleanup); } public function restart() diff --git a/app/Livewire/Project/Application/Previews.php b/app/Livewire/Project/Application/Previews.php index 193a22280..b2c1cf8e1 100644 --- a/app/Livewire/Project/Application/Previews.php +++ b/app/Livewire/Project/Application/Previews.php @@ -138,13 +138,18 @@ class Previews extends Component } } + public function force_deploy_without_cache(int $pull_request_id, ?string $pull_request_html_url = null) + { + $this->deploy($pull_request_id, $pull_request_html_url, force_rebuild: true); + } + public function add_and_deploy(int $pull_request_id, ?string $pull_request_html_url = null) { $this->add($pull_request_id, $pull_request_html_url); $this->deploy($pull_request_id, $pull_request_html_url); } - public function deploy(int $pull_request_id, ?string $pull_request_html_url = null) + public function deploy(int $pull_request_id, ?string $pull_request_html_url = null, bool $force_rebuild = false) { try { $this->setDeploymentUuid(); @@ -159,7 +164,7 @@ class Previews extends Component $result = queue_application_deployment( application: $this->application, deployment_uuid: $this->deployment_uuid, - force_rebuild: false, + force_rebuild: $force_rebuild, pull_request_id: $pull_request_id, git_type: $found->git_type ?? null, ); @@ -234,12 +239,24 @@ class Previews extends Component private function stopContainers(array $containers, $server, int $timeout = 30) { - foreach ($containers as $container) { - $containerName = str_replace('/', '', $container['Names']); - instant_remote_process(command: [ - "docker stop --time=$timeout $containerName", - "docker rm -f $containerName", - ], server: $server, throwError: false); + if (empty($containers)) { + return; } + $containerNames = []; + foreach ($containers as $container) { + $containerNames[] = str_replace('/', '', $container['Names']); + } + + $containerList = implode(' ', array_map('escapeshellarg', $containerNames)); + $commands = [ + "docker stop --time=$timeout $containerList", + "docker rm -f $containerList", + ]; + + instant_remote_process( + command: $commands, + server: $server, + throwError: false + ); } } diff --git a/app/Livewire/Project/CloneMe.php b/app/Livewire/Project/CloneMe.php index c71f6db64..fefaff4f2 100644 --- a/app/Livewire/Project/CloneMe.php +++ b/app/Livewire/Project/CloneMe.php @@ -54,7 +54,11 @@ class CloneMe extends Component $this->project = Project::where('uuid', $project_uuid)->firstOrFail(); $this->environment = $this->project->environments->where('uuid', $this->environment_uuid)->first(); $this->project_id = $this->project->id; - $this->servers = currentTeam()->servers; + $this->servers = currentTeam() + ->servers() + ->with('destinations') + ->get() + ->reject(fn ($server) => $server->isBuildServer()); $this->newName = str($this->project->name.'-clone-'.(string) new Cuid2)->slug(); } diff --git a/app/Livewire/Project/Database/Configuration.php b/app/Livewire/Project/Database/Configuration.php index 938abba54..6c4d0867e 100644 --- a/app/Livewire/Project/Database/Configuration.php +++ b/app/Livewire/Project/Database/Configuration.php @@ -2,6 +2,7 @@ namespace App\Livewire\Project\Database; +use Auth; use Livewire\Component; class Configuration extends Component @@ -14,6 +15,15 @@ class Configuration extends Component public $environment; + public function getListeners() + { + $teamId = Auth::user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},ServiceChecked" => '$refresh', + ]; + } + public function mount() { $this->currentRoute = request()->route()->getName(); diff --git a/app/Livewire/Project/Database/Heading.php b/app/Livewire/Project/Database/Heading.php index 9ddb1909c..a9783d911 100644 --- a/app/Livewire/Project/Database/Heading.php +++ b/app/Livewire/Project/Database/Heading.php @@ -6,7 +6,7 @@ use App\Actions\Database\RestartDatabase; use App\Actions\Database\StartDatabase; use App\Actions\Database\StopDatabase; use App\Actions\Docker\GetContainersStatus; -use Illuminate\Support\Facades\Auth; +use App\Events\ServiceStatusChanged; use Livewire\Component; class Heading extends Component @@ -19,36 +19,40 @@ class Heading extends Component public function getListeners() { - $userId = Auth::id(); + $teamId = auth()->user()->currentTeam()->id; return [ - "echo-private:user.{$userId},DatabaseStatusChanged" => 'activityFinished', + "echo-private:team.{$teamId},ServiceStatusChanged" => 'checkStatus', + "echo-private:team.{$teamId},ServiceChecked" => 'activityFinished', + 'refresh' => '$refresh', + 'compose_loaded' => '$refresh', + 'update_links' => '$refresh', ]; } public function activityFinished() { - $this->database->update([ - 'started_at' => now(), - ]); - $this->check_status(); + try { + $this->database->started_at ??= now(); + $this->database->save(); - if (is_null($this->database->config_hash) || $this->database->isConfigurationChanged()) { - $this->database->isConfigurationChanged(true); - $this->dispatch('configurationChanged'); - } else { + if (is_null($this->database->config_hash) || $this->database->isConfigurationChanged()) { + $this->database->isConfigurationChanged(true); + } $this->dispatch('configurationChanged'); + } catch (\Exception $e) { + return handleError($e, $this); + } finally { + $this->dispatch('refresh'); } } - public function check_status($showNotification = false) + public function checkStatus() { if ($this->database->destination->server->isFunctional()) { - GetContainersStatus::run($this->database->destination->server); - } - - if ($showNotification) { - $this->dispatch('success', 'Database status updated.'); + GetContainersStatus::dispatch($this->database->destination->server); + } else { + $this->dispatch('error', 'Server is not functional.'); } } @@ -59,23 +63,24 @@ class Heading extends Component public function stop() { - StopDatabase::run($this->database, false, $this->docker_cleanup); - $this->database->status = 'exited'; - $this->database->save(); - $this->check_status(); - $this->dispatch('refresh'); + try { + $this->dispatch('info', 'Gracefully stopping database.'); + StopDatabase::dispatch($this->database, false, $this->docker_cleanup); + } catch (\Exception $e) { + $this->dispatch('error', $e->getMessage()); + } } public function restart() { $activity = RestartDatabase::run($this->database); - $this->dispatch('activityMonitor', $activity->id); + $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); } public function start() { $activity = StartDatabase::run($this->database); - $this->dispatch('activityMonitor', $activity->id); + $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); } public function render() diff --git a/app/Livewire/Project/New/DockerCompose.php b/app/Livewire/Project/New/DockerCompose.php index 3d47ffae5..7c81e810c 100644 --- a/app/Livewire/Project/New/DockerCompose.php +++ b/app/Livewire/Project/New/DockerCompose.php @@ -25,21 +25,7 @@ class DockerCompose extends Component $this->parameters = get_route_parameters(); $this->query = request()->query(); if (isDev()) { - $this->dockerComposeRaw = 'services: - appsmith: - build: - context: . - dockerfile_inline: | - FROM nginx - ARG GIT_COMMIT - ARG GIT_BRANCH - RUN echo "Hello World ${GIT_COMMIT} ${GIT_BRANCH}" - args: - - GIT_COMMIT=cdc3b19 - - GIT_BRANCH=${GIT_BRANCH} - environment: - - APPSMITH_MAIL_ENABLED=${APPSMITH_MAIL_ENABLED} - '; + $this->dockerComposeRaw = file_get_contents(base_path('templates/test-database-detection.yaml')); } } diff --git a/app/Livewire/Project/New/Select.php b/app/Livewire/Project/New/Select.php index 396930c40..4ad3b9b29 100644 --- a/app/Livewire/Project/New/Select.php +++ b/app/Livewire/Project/New/Select.php @@ -57,13 +57,18 @@ class Select extends Component public function mount() { - $this->parameters = get_route_parameters(); - if (isDev()) { - $this->existingPostgresqlUrl = 'postgres://coolify:password@coolify-db:5432'; + try { + $this->parameters = get_route_parameters(); + if (isDev()) { + $this->existingPostgresqlUrl = 'postgres://coolify:password@coolify-db:5432'; + } + $projectUuid = data_get($this->parameters, 'project_uuid'); + $project = Project::whereUuid($projectUuid)->firstOrFail(); + $this->environments = $project->environments; + $this->selectedEnvironment = $this->environments->where('uuid', data_get($this->parameters, 'environment_uuid'))->firstOrFail()->name; + } catch (\Exception $e) { + return handleError($e, $this); } - $projectUuid = data_get($this->parameters, 'project_uuid'); - $this->environments = Project::whereUuid($projectUuid)->first()->environments; - $this->selectedEnvironment = data_get($this->parameters, 'environment_uuid'); } public function render() @@ -73,9 +78,11 @@ class Select extends Component public function updatedSelectedEnvironment() { + $environmentUuid = $this->environments->where('name', $this->selectedEnvironment)->first()->uuid; + return redirect()->route('project.resource.create', [ 'project_uuid' => $this->parameters['project_uuid'], - 'environment_uuid' => $this->selectedEnvironment, + 'environment_uuid' => $environmentUuid, ]); } diff --git a/app/Livewire/Project/Service/Configuration.php b/app/Livewire/Project/Service/Configuration.php index 20067b1f9..8ac74e7de 100644 --- a/app/Livewire/Project/Service/Configuration.php +++ b/app/Livewire/Project/Service/Configuration.php @@ -2,7 +2,6 @@ namespace App\Livewire\Project\Service; -use App\Actions\Docker\GetContainersStatus; use App\Models\Service; use Illuminate\Support\Facades\Auth; use Livewire\Component; @@ -27,13 +26,10 @@ class Configuration extends Component public function getListeners() { - $userId = Auth::id(); + $teamId = Auth::user()->currentTeam()->id; return [ - "echo-private:user.{$userId},ServiceStatusChanged" => 'check_status', - 'refreshStatus' => '$refresh', - 'check_status', - 'refreshServices', + "echo-private:team.{$teamId},ServiceChecked" => 'serviceChecked', ]; } @@ -97,19 +93,15 @@ class Configuration extends Component } } - public function check_status() + public function serviceChecked() { try { - if ($this->service->server->isFunctional()) { - GetContainersStatus::dispatch($this->service->server); - } $this->service->applications->each(function ($application) { $application->refresh(); }); $this->service->databases->each(function ($database) { $database->refresh(); }); - $this->dispatch('refreshStatus'); } catch (\Exception $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Service/EditDomain.php b/app/Livewire/Project/Service/EditDomain.php index fb1c05255..b7f73159e 100644 --- a/app/Livewire/Project/Service/EditDomain.php +++ b/app/Livewire/Project/Service/EditDomain.php @@ -47,7 +47,6 @@ class EditDomain extends Component $this->application->service->parse(); $this->dispatch('refresh'); $this->dispatch('configurationChanged'); - $this->dispatch('refreshStatus'); } catch (\Throwable $e) { $originalFqdn = $this->application->getOriginal('fqdn'); if ($originalFqdn !== $this->application->fqdn) { diff --git a/app/Livewire/Project/Service/Navbar.php b/app/Livewire/Project/Service/Heading.php similarity index 62% rename from app/Livewire/Project/Service/Navbar.php rename to app/Livewire/Project/Service/Heading.php index 5da425cbd..eb7f469a8 100644 --- a/app/Livewire/Project/Service/Navbar.php +++ b/app/Livewire/Project/Service/Heading.php @@ -2,6 +2,7 @@ namespace App\Livewire\Project\Service; +use App\Actions\Docker\GetContainersStatus; use App\Actions\Service\StartService; use App\Actions\Service\StopService; use App\Enums\ProcessStatus; @@ -11,7 +12,7 @@ use Illuminate\Support\Facades\Auth; use Livewire\Component; use Spatie\Activitylog\Models\Activity; -class Navbar extends Component +class Heading extends Component { public Service $service; @@ -35,35 +36,44 @@ class Navbar extends Component public function getListeners() { - $userId = Auth::id(); + $teamId = Auth::user()->currentTeam()->id; return [ - "echo-private:user.{$userId},ServiceStatusChanged" => 'serviceStarted', + "echo-private:team.{$teamId},ServiceStatusChanged" => 'checkStatus', + "echo-private:team.{$teamId},ServiceChecked" => 'serviceChecked', + 'refresh' => '$refresh', 'envsUpdated' => '$refresh', - 'refreshStatus' => '$refresh', ]; } - public function serviceStarted() + public function checkStatus() { - // $this->dispatch('success', 'Service status changed.'); - if (is_null($this->service->config_hash) || $this->service->isConfigurationChanged()) { - $this->service->isConfigurationChanged(true); - $this->dispatch('configurationChanged'); + if ($this->service->server->isFunctional()) { + GetContainersStatus::dispatch($this->service->server); } else { - $this->dispatch('configurationChanged'); + $this->dispatch('error', 'Server is not functional.'); } } - public function check_status_without_notification() + public function serviceChecked() { - $this->dispatch('check_status'); - } + try { + $this->service->applications->each(function ($application) { + $application->refresh(); + }); + $this->service->databases->each(function ($database) { + $database->refresh(); + }); + if (is_null($this->service->config_hash) || $this->service->isConfigurationChanged()) { + $this->service->isConfigurationChanged(true); + } + $this->dispatch('configurationChanged'); + } catch (\Exception $e) { + return handleError($e, $this); + } finally { + $this->dispatch('refresh')->self(); + } - public function check_status() - { - $this->dispatch('check_status'); - $this->dispatch('success', 'Service status updated.'); } public function checkDeployments() @@ -86,34 +96,32 @@ class Navbar extends Component public function start() { $activity = StartService::run($this->service, pullLatestImages: true); - $this->dispatch('activityMonitor', $activity->id); + $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); } public function forceDeploy() { try { - $activities = Activity::where('properties->type_uuid', $this->service->uuid)->where('properties->status', ProcessStatus::IN_PROGRESS->value)->orWhere('properties->status', ProcessStatus::QUEUED->value)->get(); + $activities = Activity::where('properties->type_uuid', $this->service->uuid) + ->where(function ($q) { + $q->where('properties->status', ProcessStatus::IN_PROGRESS->value) + ->orWhere('properties->status', ProcessStatus::QUEUED->value); + })->get(); foreach ($activities as $activity) { $activity->properties->status = ProcessStatus::ERROR->value; $activity->save(); } $activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true); - $this->dispatch('activityMonitor', $activity->id); + $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } } - public function stop($cleanupContainers = false) + public function stop() { try { - StopService::run($this->service, false, $this->docker_cleanup); - ServiceStatusChanged::dispatch(); - if ($cleanupContainers) { - $this->dispatch('success', 'Containers cleaned up.'); - } else { - $this->dispatch('success', 'Service stopped.'); - } + StopService::dispatch($this->service, false, $this->docker_cleanup); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } @@ -128,7 +136,7 @@ class Navbar extends Component return; } $activity = StartService::run($this->service, stopBeforeStart: true); - $this->dispatch('activityMonitor', $activity->id); + $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); } public function pullAndRestartEvent() @@ -140,12 +148,12 @@ class Navbar extends Component return; } $activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true); - $this->dispatch('activityMonitor', $activity->id); + $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); } public function render() { - return view('livewire.project.service.navbar', [ + return view('livewire.project.service.heading', [ 'checkboxes' => [ ['id' => 'docker_cleanup', 'label' => __('resource.docker_cleanup')], ], diff --git a/app/Livewire/Project/Shared/Destination.php b/app/Livewire/Project/Shared/Destination.php index 71a913add..40291d2b0 100644 --- a/app/Livewire/Project/Shared/Destination.php +++ b/app/Livewire/Project/Shared/Destination.php @@ -26,6 +26,8 @@ class Destination extends Component return [ "echo-private:team.{$teamId},ApplicationStatusChanged" => 'loadData', + "echo-private:team.{$teamId},ServiceStatusChanged" => 'mount', + 'refresh' => 'mount', ]; } @@ -114,22 +116,20 @@ class Destination extends Component $this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]); $this->resource->additional_networks()->attach($main_destination->id, ['server_id' => $main_destination->server->id]); $this->refreshServers(); + $this->resource->refresh(); } public function refreshServers() { GetContainersStatus::run($this->resource->destination->server); - // ContainerStatusJob::dispatchSync($this->resource->destination->server); $this->loadData(); $this->dispatch('refresh'); - ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id')); } public function addServer(int $network_id, int $server_id) { $this->resource->additional_networks()->attach($network_id, ['server_id' => $server_id]); - $this->loadData(); - ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id')); + $this->dispatch('refresh'); } public function removeServer(int $network_id, int $server_id, $password) @@ -144,7 +144,7 @@ class Destination extends Component } if ($this->resource->destination->server->id == $server_id && $this->resource->destination->id == $network_id) { - $this->dispatch('error', 'You cannot remove this destination server.', 'You are trying to remove the main server.'); + $this->dispatch('error', 'You are trying to remove the main server.'); return; } @@ -152,6 +152,7 @@ class Destination extends Component StopApplicationOneServer::run($this->resource, $server); $this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]); $this->loadData(); + $this->dispatch('refresh'); ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id')); } catch (\Exception $e) { return handleError($e, $this); diff --git a/app/Livewire/Project/Shared/EnvironmentVariable/All.php b/app/Livewire/Project/Shared/EnvironmentVariable/All.php index 699dca187..3b6d8b937 100644 --- a/app/Livewire/Project/Shared/EnvironmentVariable/All.php +++ b/app/Livewire/Project/Shared/EnvironmentVariable/All.php @@ -178,16 +178,6 @@ class All extends Component } } - // Debug information - \Log::info('Environment variables update status', [ - 'deletedCount' => $deletedCount, - 'updatedCount' => $updatedCount, - 'deletedPreviewCount' => $deletedPreviewCount ?? 0, - 'updatedPreviewCount' => $updatedPreviewCount ?? 0, - 'changesMade' => $changesMade, - 'errorOccurred' => $errorOccurred, - ]); - // Only show success message if changes were actually made and no errors occurred if ($changesMade && ! $errorOccurred) { $this->dispatch('success', 'Environment variables updated.'); diff --git a/app/Livewire/Project/Shared/ExecuteContainerCommand.php b/app/Livewire/Project/Shared/ExecuteContainerCommand.php index 98289c536..ca1597d4f 100644 --- a/app/Livewire/Project/Shared/ExecuteContainerCommand.php +++ b/app/Livewire/Project/Shared/ExecuteContainerCommand.php @@ -13,8 +13,6 @@ class ExecuteContainerCommand extends Component { public $selected_container = 'default'; - public $container; - public Collection $containers; public $parameters; @@ -23,11 +21,9 @@ class ExecuteContainerCommand extends Component public string $type; - public Server $server; - public Collection $servers; - public bool $hasShell = true; + public bool $isConnecting = false; protected $rules = [ 'server' => 'required', @@ -76,8 +72,9 @@ class ExecuteContainerCommand extends Component } elseif (data_get($this->parameters, 'server_uuid')) { $this->type = 'server'; $this->resource = Server::where('uuid', $this->parameters['server_uuid'])->firstOrFail(); - $this->server = $this->resource; + $this->servers = $this->servers->push($this->resource); } + $this->servers = $this->servers->sortByDesc(fn ($server) => $server->isTerminalEnabled()); } public function loadContainers() @@ -95,7 +92,7 @@ class ExecuteContainerCommand extends Component } foreach ($containers as $container) { // if container state is running - if (data_get($container, 'State') === 'running') { + if (data_get($container, 'State') === 'running' && $server->isTerminalEnabled()) { $payload = [ 'server' => $server, 'container' => $container, @@ -104,7 +101,7 @@ class ExecuteContainerCommand extends Component } } } elseif (data_get($this->parameters, 'database_uuid')) { - if ($this->resource->isRunning()) { + if ($this->resource->isRunning() && $server->isTerminalEnabled()) { $this->containers = $this->containers->push([ 'server' => $server, 'container' => [ @@ -114,7 +111,7 @@ class ExecuteContainerCommand extends Component } } elseif (data_get($this->parameters, 'service_uuid')) { $this->resource->applications()->get()->each(function ($application) { - if ($application->isRunning()) { + if ($application->isRunning() && $this->resource->server->isTerminalEnabled()) { $this->containers->push([ 'server' => $this->resource->server, 'container' => [ @@ -135,45 +132,29 @@ class ExecuteContainerCommand extends Component }); } } - if ($this->containers->count() > 0) { - $this->container = $this->containers->first(); - } if ($this->containers->count() === 1) { $this->selected_container = data_get($this->containers->first(), 'container.Names'); } } - private function checkShellAvailability(Server $server, string $container): bool - { - $escapedContainer = escapeshellarg($container); - try { - instant_remote_process([ - "docker exec {$escapedContainer} bash -c 'exit 0' 2>/dev/null || ". - "docker exec {$escapedContainer} sh -c 'exit 0' 2>/dev/null", - ], $server); - - return true; - } catch (\Throwable) { - return false; - } - } - #[On('connectToServer')] public function connectToServer() { try { - if ($this->server->isForceDisabled()) { + $server = $this->servers->first(); + if ($server->isForceDisabled()) { throw new \RuntimeException('Server is disabled.'); } - $this->hasShell = true; $this->dispatch( 'send-terminal-command', false, - data_get($this->server, 'name'), - data_get($this->server, 'uuid') + data_get($server, 'name'), + data_get($server, 'uuid') ); } catch (\Throwable $e) { return handleError($e, $this); + } finally { + $this->isConnecting = false; } } @@ -219,11 +200,6 @@ class ExecuteContainerCommand extends Component throw new \RuntimeException('Server ownership verification failed.'); } - $this->hasShell = $this->checkShellAvailability($server, data_get($container, 'container.Names')); - if (! $this->hasShell) { - return; - } - $this->dispatch( 'send-terminal-command', true, @@ -232,6 +208,8 @@ class ExecuteContainerCommand extends Component ); } catch (\Throwable $e) { return handleError($e, $this); + } finally { + $this->isConnecting = false; } } diff --git a/app/Livewire/Project/Shared/Logs.php b/app/Livewire/Project/Shared/Logs.php index 12022b1ee..6c4aadd39 100644 --- a/app/Livewire/Project/Shared/Logs.php +++ b/app/Livewire/Project/Shared/Logs.php @@ -25,6 +25,8 @@ class Logs extends Component public Collection $containers; + public array $serverContainers = []; + public $container = []; public $parameters; @@ -37,25 +39,60 @@ class Logs extends Component public $cpu; - public function loadContainers($server_id) + public bool $containersLoaded = false; + + public function getListeners() + { + $teamId = auth()->user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},ServiceChecked" => '$refresh', + ]; + } + + public function loadAllContainers() { try { - $server = $this->servers->firstWhere('id', $server_id); - if (! $server->isFunctional()) { - return; + foreach ($this->servers as $server) { + $this->serverContainers[$server->id] = $this->getContainersForServer($server); } + $this->containersLoaded = true; + } catch (\Exception $e) { + $this->containersLoaded = true; // Set to true to stop loading spinner + + return handleError($e, $this); + } + } + + private function getContainersForServer($server) + { + if (! $server->isFunctional()) { + return []; + } + + try { if ($server->isSwarm()) { $containers = collect([ [ + 'ID' => $this->resource->uuid, 'Names' => $this->resource->uuid.'_'.$this->resource->uuid, ], ]); + + return $containers->toArray(); } else { $containers = getCurrentApplicationContainerStatus($server, $this->resource->id, includePullrequests: true); + if ($containers && $containers->count() > 0) { + return $containers->sort()->toArray(); + } + + return []; } - $server->containers = $containers->sort(); } catch (\Exception $e) { - return handleError($e, $this); + // Log error but don't fail the entire operation + ray("Error loading containers for server {$server->name}: ".$e->getMessage()); + + return []; } } @@ -64,6 +101,7 @@ class Logs extends Component try { $this->containers = collect(); $this->servers = collect(); + $this->serverContainers = []; $this->parameters = get_route_parameters(); $this->query = request()->query(); if (data_get($this->parameters, 'application_uuid')) { @@ -71,7 +109,8 @@ class Logs extends Component $this->resource = Application::where('uuid', $this->parameters['application_uuid'])->firstOrFail(); $this->status = $this->resource->status; if ($this->resource->destination->server->isFunctional()) { - $this->servers = $this->servers->push($this->resource->destination->server); + $server = $this->resource->destination->server; + $this->servers = $this->servers->push($server); } foreach ($this->resource->additional_servers as $server) { if ($server->isFunctional()) { @@ -87,7 +126,8 @@ class Logs extends Component $this->resource = $resource; $this->status = $this->resource->status; if ($this->resource->destination->server->isFunctional()) { - $this->servers = $this->servers->push($this->resource->destination->server); + $server = $this->resource->destination->server; + $this->servers = $this->servers->push($server); } $this->container = $this->resource->uuid; $this->containers->push($this->container); @@ -101,7 +141,8 @@ class Logs extends Component $this->containers->push(data_get($database, 'name').'-'.data_get($this->resource, 'uuid')); }); if ($this->resource->server->isFunctional()) { - $this->servers = $this->servers->push($this->resource->server); + $server = $this->resource->server; + $this->servers = $this->servers->push($server); } } $this->containers = $this->containers->sort(); diff --git a/app/Livewire/Project/Shared/ResourceOperations.php b/app/Livewire/Project/Shared/ResourceOperations.php index e19f1272d..fb19acb55 100644 --- a/app/Livewire/Project/Shared/ResourceOperations.php +++ b/app/Livewire/Project/Shared/ResourceOperations.php @@ -35,7 +35,7 @@ class ResourceOperations extends Component $this->projectUuid = data_get($parameters, 'project_uuid'); $this->environmentUuid = data_get($parameters, 'environment_uuid'); $this->projects = Project::ownedByCurrentTeam()->get(); - $this->servers = currentTeam()->servers; + $this->servers = currentTeam()->servers->filter(fn ($server) => ! $server->isBuildServer()); } public function toggleVolumeCloning(bool $value) diff --git a/app/Livewire/Project/Shared/ScheduledTask/Show.php b/app/Livewire/Project/Shared/ScheduledTask/Show.php index 6d9c6982a..fe6e36d5c 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Show.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Show.php @@ -46,6 +46,15 @@ class Show extends Component #[Locked] public string $task_uuid; + public function getListeners() + { + $teamId = auth()->user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},ServiceChecked" => '$refresh', + ]; + } + public function mount(string $task_uuid, string $project_uuid, string $environment_uuid, ?string $application_uuid = null, ?string $service_uuid = null) { try { diff --git a/app/Livewire/Project/Shared/Terminal.php b/app/Livewire/Project/Shared/Terminal.php index a3d1aa10f..819d364e2 100644 --- a/app/Livewire/Project/Shared/Terminal.php +++ b/app/Livewire/Project/Shared/Terminal.php @@ -44,6 +44,9 @@ class Terminal extends Component public function sendTerminalCommand($isContainer, $identifier, $serverUuid) { $server = Server::ownedByCurrentTeam()->whereUuid($serverUuid)->firstOrFail(); + if (! $server->isTerminalEnabled() || $server->isForceDisabled()) { + abort(403, 'Terminal access is disabled on this server.'); + } if ($isContainer) { // Validate container identifier format (alphanumeric, dashes, and underscores only) diff --git a/app/Livewire/Server/Advanced.php b/app/Livewire/Server/Advanced.php index b2b8b1518..1bf8cf4c9 100644 --- a/app/Livewire/Server/Advanced.php +++ b/app/Livewire/Server/Advanced.php @@ -2,11 +2,10 @@ namespace App\Livewire\Server; -use App\Helpers\SslHelper; -use App\Jobs\RegenerateSslCertJob; +use App\Models\InstanceSettings; use App\Models\Server; -use App\Models\SslCertificate; -use Carbon\Carbon; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Hash; use Livewire\Attributes\Validate; use Livewire\Component; @@ -14,14 +13,6 @@ class Advanced extends Component { public Server $server; - public ?SslCertificate $caCertificate = null; - - public $showCertificate = false; - - public $certificateContent = ''; - - public ?Carbon $certificateValidUntil = null; - public array $parameters = []; #[Validate(['string'])] @@ -36,105 +27,52 @@ class Advanced extends Component #[Validate(['integer', 'min:1'])] public int $dynamicTimeout = 1; + #[Validate(['boolean'])] + public bool $isTerminalEnabled = false; + public function mount(string $server_uuid) { try { $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->parameters = get_route_parameters(); $this->syncData(); - $this->loadCaCertificate(); + } catch (\Throwable) { return redirect()->route('server.index'); } } - public function loadCaCertificate() - { - $this->caCertificate = SslCertificate::where('server_id', $this->server->id)->where('is_ca_certificate', true)->first(); - - if ($this->caCertificate) { - $this->certificateContent = $this->caCertificate->ssl_certificate; - $this->certificateValidUntil = $this->caCertificate->valid_until; - } - } - - public function toggleCertificate() - { - $this->showCertificate = ! $this->showCertificate; - } - - public function saveCaCertificate() + public function toggleTerminal($password) { try { - if (! $this->certificateContent) { - throw new \Exception('Certificate content cannot be empty.'); + // Check if user is admin or owner + if (! auth()->user()->isAdmin()) { + throw new \Exception('Only team administrators and owners can modify terminal access.'); } - if (! openssl_x509_read($this->certificateContent)) { - throw new \Exception('Invalid certificate format.'); + // Verify password unless two-step confirmation is disabled + if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) { + if (! Hash::check($password, Auth::user()->password)) { + $this->addError('password', 'The provided password is incorrect.'); + + return; + } } - if ($this->caCertificate) { - $this->caCertificate->ssl_certificate = $this->certificateContent; - $this->caCertificate->save(); + // Toggle the terminal setting + $this->server->settings->is_terminal_enabled = ! $this->server->settings->is_terminal_enabled; + $this->server->settings->save(); - $this->loadCaCertificate(); + // Update the local property + $this->isTerminalEnabled = $this->server->settings->is_terminal_enabled; - $this->writeCertificateToServer(); - - dispatch(new RegenerateSslCertJob( - server_id: $this->server->id, - force_regeneration: true - )); - } - $this->dispatch('success', 'CA Certificate saved successfully.'); + $status = $this->isTerminalEnabled ? 'enabled' : 'disabled'; + $this->dispatch('success', "Terminal access has been {$status}."); } catch (\Throwable $e) { return handleError($e, $this); } } - public function regenerateCaCertificate() - { - try { - SslHelper::generateSslCertificate( - commonName: 'Coolify CA Certificate', - serverId: $this->server->id, - isCaCertificate: true, - validityDays: 10 * 365 - ); - - $this->loadCaCertificate(); - - $this->writeCertificateToServer(); - - dispatch(new RegenerateSslCertJob( - server_id: $this->server->id, - force_regeneration: true - )); - - $this->loadCaCertificate(); - $this->dispatch('success', 'CA Certificate regenerated successfully.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - private function writeCertificateToServer() - { - $caCertPath = config('constants.coolify.base_config_path').'/ssl/'; - - $commands = collect([ - "mkdir -p $caCertPath", - "chown -R 9999:root $caCertPath", - "chmod -R 700 $caCertPath", - "rm -rf $caCertPath/coolify-ca.crt", - "echo '{$this->certificateContent}' > $caCertPath/coolify-ca.crt", - "chmod 644 $caCertPath/coolify-ca.crt", - ]); - - remote_process($commands, $this->server); - } - public function syncData(bool $toModel = false) { if ($toModel) { @@ -149,6 +87,7 @@ class Advanced extends Component $this->dynamicTimeout = $this->server->settings->dynamic_timeout; $this->serverDiskUsageNotificationThreshold = $this->server->settings->server_disk_usage_notification_threshold; $this->serverDiskUsageCheckFrequency = $this->server->settings->server_disk_usage_check_frequency; + $this->isTerminalEnabled = $this->server->settings->is_terminal_enabled; } } diff --git a/app/Livewire/Server/CaCertificate/Show.php b/app/Livewire/Server/CaCertificate/Show.php new file mode 100644 index 000000000..750ed9f81 --- /dev/null +++ b/app/Livewire/Server/CaCertificate/Show.php @@ -0,0 +1,128 @@ +server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + $this->loadCaCertificate(); + } catch (\Throwable $e) { + return redirect()->route('server.index'); + } + + } + + public function loadCaCertificate() + { + $this->caCertificate = SslCertificate::where('server_id', $this->server->id)->where('is_ca_certificate', true)->first(); + + if ($this->caCertificate) { + $this->certificateContent = $this->caCertificate->ssl_certificate; + $this->certificateValidUntil = $this->caCertificate->valid_until; + } + } + + public function toggleCertificate() + { + $this->showCertificate = ! $this->showCertificate; + } + + public function saveCaCertificate() + { + try { + if (! $this->certificateContent) { + throw new \Exception('Certificate content cannot be empty.'); + } + + if (! openssl_x509_read($this->certificateContent)) { + throw new \Exception('Invalid certificate format.'); + } + + if ($this->caCertificate) { + $this->caCertificate->ssl_certificate = $this->certificateContent; + $this->caCertificate->save(); + + $this->loadCaCertificate(); + + $this->writeCertificateToServer(); + + dispatch(new RegenerateSslCertJob( + server_id: $this->server->id, + force_regeneration: true + )); + } + $this->dispatch('success', 'CA Certificate saved successfully.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function regenerateCaCertificate() + { + try { + SslHelper::generateSslCertificate( + commonName: 'Coolify CA Certificate', + serverId: $this->server->id, + isCaCertificate: true, + validityDays: 10 * 365 + ); + + $this->loadCaCertificate(); + + $this->writeCertificateToServer(); + + dispatch(new RegenerateSslCertJob( + server_id: $this->server->id, + force_regeneration: true + )); + + $this->loadCaCertificate(); + $this->dispatch('success', 'CA Certificate regenerated successfully.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + private function writeCertificateToServer() + { + $caCertPath = config('constants.coolify.base_config_path').'/ssl/'; + + $commands = collect([ + "mkdir -p $caCertPath", + "chown -R 9999:root $caCertPath", + "chmod -R 700 $caCertPath", + "rm -rf $caCertPath/coolify-ca.crt", + "echo '{$this->certificateContent}' > $caCertPath/coolify-ca.crt", + "chmod 644 $caCertPath/coolify-ca.crt", + ]); + + remote_process($commands, $this->server); + } + + public function render() + { + return view('livewire.server.ca-certificate.show'); + } +} diff --git a/app/Livewire/Server/CloudflareTunnel.php b/app/Livewire/Server/CloudflareTunnel.php new file mode 100644 index 000000000..b2ffa003f --- /dev/null +++ b/app/Livewire/Server/CloudflareTunnel.php @@ -0,0 +1,96 @@ +user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},CloudflareTunnelConfigured" => 'refresh', + ]; + } + + public function refresh() + { + $this->server->refresh(); + $this->isCloudflareTunnelsEnabled = $this->server->settings->is_cloudflare_tunnel; + } + + public function mount(string $server_uuid) + { + try { + $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + if ($this->server->isLocalhost()) { + return redirect()->route('server.show', ['server_uuid' => $server_uuid]); + } + $this->isCloudflareTunnelsEnabled = $this->server->settings->is_cloudflare_tunnel; + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function toggleCloudflareTunnels() + { + try { + remote_process(['docker rm -f coolify-cloudflared'], $this->server, false, 10); + $this->isCloudflareTunnelsEnabled = false; + $this->server->settings->is_cloudflare_tunnel = false; + $this->server->settings->save(); + if ($this->server->ip_previous) { + $this->server->update(['ip' => $this->server->ip_previous]); + $this->dispatch('success', 'Cloudflare Tunnel disabled.

Manually updated the server IP address to its previous IP address.'); + } else { + $this->dispatch('warning', 'Cloudflare Tunnel disabled. Action required: Update the server IP address to its real IP address in the Advanced settings.'); + } + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function manualCloudflareConfig() + { + $this->isCloudflareTunnelsEnabled = true; + $this->server->settings->is_cloudflare_tunnel = true; + $this->server->settings->save(); + $this->server->refresh(); + $this->dispatch('success', 'Cloudflare Tunnel enabled.'); + } + + public function automatedCloudflareConfig() + { + try { + if (str($this->ssh_domain)->contains('https://')) { + $this->ssh_domain = str($this->ssh_domain)->replace('https://', '')->replace('http://', '')->trim(); + $this->ssh_domain = str($this->ssh_domain)->replace('/', ''); + } + $activity = ConfigureCloudflared::run($this->server, $this->cloudflare_token, $this->ssh_domain); + $this->dispatch('activityMonitor', $activity->id); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function render() + { + return view('livewire.server.cloudflare-tunnel'); + } +} diff --git a/app/Livewire/Server/CloudflareTunnels.php b/app/Livewire/Server/CloudflareTunnels.php deleted file mode 100644 index f69fc8655..000000000 --- a/app/Livewire/Server/CloudflareTunnels.php +++ /dev/null @@ -1,54 +0,0 @@ -server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); - if ($this->server->isLocalhost()) { - return redirect()->route('server.show', ['server_uuid' => $server_uuid]); - } - $this->isCloudflareTunnelsEnabled = $this->server->settings->is_cloudflare_tunnel; - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function instantSave() - { - try { - $this->validate(); - $this->server->settings->is_cloudflare_tunnel = $this->isCloudflareTunnelsEnabled; - $this->server->settings->save(); - $this->dispatch('success', 'Server updated.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function manualCloudflareConfig() - { - $this->isCloudflareTunnelsEnabled = true; - $this->server->settings->is_cloudflare_tunnel = true; - $this->server->settings->save(); - $this->server->refresh(); - $this->dispatch('success', 'Cloudflare Tunnels enabled.'); - } - - public function render() - { - return view('livewire.server.cloudflare-tunnels'); - } -} diff --git a/app/Livewire/Server/ConfigureCloudflareTunnels.php b/app/Livewire/Server/ConfigureCloudflareTunnels.php deleted file mode 100644 index f27614aa4..000000000 --- a/app/Livewire/Server/ConfigureCloudflareTunnels.php +++ /dev/null @@ -1,54 +0,0 @@ -where('id', $this->server_id)->firstOrFail(); - $server->settings->is_cloudflare_tunnel = true; - $server->settings->save(); - $this->dispatch('success', 'Cloudflare Tunnels configured successfully.'); - $this->dispatch('refreshServerShow'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function submit() - { - try { - if (str($this->ssh_domain)->contains('https://')) { - $this->ssh_domain = str($this->ssh_domain)->replace('https://', '')->replace('http://', '')->trim(); - // remove / from the end - $this->ssh_domain = str($this->ssh_domain)->replace('/', ''); - } - $server = Server::ownedByCurrentTeam()->where('id', $this->server_id)->firstOrFail(); - ConfigureCloudflared::dispatch($server, $this->cloudflare_token); - $server->settings->is_cloudflare_tunnel = true; - $server->ip = $this->ssh_domain; - $server->save(); - $server->settings->save(); - $this->dispatch('info', 'Cloudflare Tunnels configuration started.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function render() - { - return view('livewire.server.configure-cloudflare-tunnels'); - } -} diff --git a/app/Livewire/Server/Navbar.php b/app/Livewire/Server/Navbar.php new file mode 100644 index 000000000..5381d1e19 --- /dev/null +++ b/app/Livewire/Server/Navbar.php @@ -0,0 +1,134 @@ +user()->currentTeam()->id; + + return [ + 'refreshServerShow' => '$refresh', + "echo-private:team.{$teamId},ProxyStatusChangedUI" => 'showNotification', + ]; + } + + public function mount(Server $server) + { + $this->server = $server; + $this->currentRoute = request()->route()->getName(); + $this->serverIp = $this->server->id === 0 ? base_ip() : $this->server->ip; + $this->proxyStatus = $this->server->proxy->status ?? 'unknown'; + $this->loadProxyConfiguration(); + } + + public function loadProxyConfiguration() + { + try { + if ($this->proxyStatus === 'running') { + $this->traefikDashboardAvailable = ProxyDashboardCacheService::isTraefikDashboardAvailableFromCache($this->server); + } + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function restart() + { + try { + RestartProxyJob::dispatch($this->server); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function checkProxy() + { + try { + CheckProxy::run($this->server, true); + $this->dispatch('startProxy')->self(); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function startProxy() + { + try { + $activity = StartProxy::run($this->server, force: true); + $this->dispatch('activityMonitor', $activity->id); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function stop(bool $forceStop = true) + { + try { + StopProxy::dispatch($this->server, $forceStop); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function checkProxyStatus() + { + if ($this->isChecking) { + return; + } + + try { + $this->isChecking = true; + CheckProxy::run($this->server, true); + } catch (\Throwable $e) { + return handleError($e, $this); + } finally { + $this->isChecking = false; + $this->showNotification(); + } + } + + public function showNotification() + { + $this->proxyStatus = $this->server->proxy->status ?? 'unknown'; + $forceStop = $this->server->proxy->force_stop ?? false; + + switch ($this->proxyStatus) { + case 'running': + $this->loadProxyConfiguration(); + break; + case 'restarting': + $this->dispatch('info', 'Initiating proxy restart.'); + break; + default: + break; + } + + } + + public function render() + { + return view('livewire.server.navbar'); + } +} diff --git a/app/Livewire/Server/Proxy.php b/app/Livewire/Server/Proxy.php index 4e325c1ff..9332c2517 100644 --- a/app/Livewire/Server/Proxy.php +++ b/app/Livewire/Server/Proxy.php @@ -19,7 +19,7 @@ class Proxy extends Component public ?string $redirect_url = null; - protected $listeners = ['proxyStatusUpdated', 'saveConfiguration' => 'submit']; + protected $listeners = ['saveConfiguration' => 'submit']; protected $rules = [ 'server.settings.generate_exact_labels' => 'required|boolean', @@ -32,15 +32,16 @@ class Proxy extends Component $this->redirect_url = data_get($this->server, 'proxy.redirect_url'); } - public function proxyStatusUpdated() - { - $this->dispatch('refresh')->self(); - } + // public function proxyStatusUpdated() + // { + // $this->dispatch('refresh')->self(); + // } public function changeProxy() { $this->server->proxy = null; $this->server->save(); + $this->dispatch('reloadWindow'); } @@ -49,6 +50,7 @@ class Proxy extends Component try { $this->server->changeProxy($proxy_type, async: false); $this->selectedProxy = $this->server->proxy->type; + $this->dispatch('reloadWindow'); } catch (\Throwable $e) { return handleError($e, $this); @@ -107,11 +109,6 @@ class Proxy extends Component { try { $this->proxy_settings = CheckConfiguration::run($this->server); - if (str($this->proxy_settings)->contains('--api.dashboard=true') && str($this->proxy_settings)->contains('--api.insecure=true')) { - $this->dispatch('traefikDashboardAvailable', true); - } else { - $this->dispatch('traefikDashboardAvailable', false); - } } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Server/Proxy/Deploy.php b/app/Livewire/Server/Proxy/Deploy.php deleted file mode 100644 index 48eede4e5..000000000 --- a/app/Livewire/Server/Proxy/Deploy.php +++ /dev/null @@ -1,106 +0,0 @@ -user()->currentTeam()->id; - - return [ - "echo-private:team.{$teamId},ProxyStatusChanged" => 'proxyStarted', - 'proxyStatusUpdated', - 'traefikDashboardAvailable', - 'serverRefresh' => 'proxyStatusUpdated', - 'checkProxy', - 'startProxy', - 'proxyChanged' => 'proxyStatusUpdated', - ]; - } - - public function mount() - { - if ($this->server->id === 0) { - $this->serverIp = base_ip(); - } else { - $this->serverIp = $this->server->ip; - } - $this->currentRoute = request()->route()->getName(); - } - - public function traefikDashboardAvailable(bool $data) - { - $this->traefikDashboardAvailable = $data; - } - - public function proxyStarted() - { - CheckProxy::run($this->server, true); - $this->dispatch('proxyStatusUpdated'); - } - - public function proxyStatusUpdated() - { - $this->server->refresh(); - } - - public function restart() - { - try { - RestartProxyJob::dispatch($this->server); - $this->dispatch('checkProxy'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function checkProxy() - { - try { - CheckProxy::run($this->server, true); - $this->dispatch('startProxyPolling'); - $this->dispatch('proxyChecked'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function startProxy() - { - try { - $this->server->proxy->force_stop = false; - $this->server->save(); - $activity = StartProxy::run($this->server, force: true); - $this->dispatch('activityMonitor', $activity->id, ProxyStatusChanged::class); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function stop(bool $forceStop = true) - { - try { - StopProxy::run($this->server, $forceStop); - $this->dispatch('proxyStatusUpdated'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } -} diff --git a/app/Livewire/Server/Proxy/DynamicConfigurations.php b/app/Livewire/Server/Proxy/DynamicConfigurations.php index 7db890638..6ea9e7c3d 100644 --- a/app/Livewire/Server/Proxy/DynamicConfigurations.php +++ b/app/Livewire/Server/Proxy/DynamicConfigurations.php @@ -19,7 +19,7 @@ class DynamicConfigurations extends Component $teamId = auth()->user()->currentTeam()->id; return [ - "echo-private:team.{$teamId},ProxyStatusChanged" => 'loadDynamicConfigurations', + "echo-private:team.{$teamId},ProxyStatusChangedUI" => 'loadDynamicConfigurations', 'loadDynamicConfigurations', ]; } @@ -28,6 +28,11 @@ class DynamicConfigurations extends Component 'contents.*' => 'nullable|string', ]; + public function initLoadDynamicConfigurations() + { + $this->loadDynamicConfigurations(); + } + public function loadDynamicConfigurations() { $proxy_path = $this->server->proxyPath(); @@ -43,6 +48,7 @@ class DynamicConfigurations extends Component } $this->contents = $contents; $this->dispatch('$refresh'); + $this->dispatch('success', 'Dynamic configurations loaded.'); } public function mount() diff --git a/app/Livewire/Server/Proxy/Show.php b/app/Livewire/Server/Proxy/Show.php index 5ecb56a69..fea7a98bb 100644 --- a/app/Livewire/Server/Proxy/Show.php +++ b/app/Livewire/Server/Proxy/Show.php @@ -11,13 +11,6 @@ class Show extends Component public $parameters = []; - protected $listeners = ['proxyStatusUpdated', 'proxyChanged' => 'proxyStatusUpdated']; - - public function proxyStatusUpdated() - { - $this->server->refresh(); - } - public function mount() { $this->parameters = get_route_parameters(); diff --git a/app/Livewire/Server/Proxy/Status.php b/app/Livewire/Server/Proxy/Status.php deleted file mode 100644 index f4f18381f..000000000 --- a/app/Livewire/Server/Proxy/Status.php +++ /dev/null @@ -1,77 +0,0 @@ -checkProxy(); - } - - public function proxyStatusUpdated() - { - $this->server->refresh(); - } - - public function checkProxy(bool $notification = false) - { - try { - if ($this->polling) { - if ($this->numberOfPolls >= 10) { - $this->polling = false; - $this->numberOfPolls = 0; - $notification && $this->dispatch('error', 'Proxy is not running.'); - - return; - } - $this->numberOfPolls++; - } - $shouldStart = CheckProxy::run($this->server, true); - if ($shouldStart) { - StartProxy::run($this->server, false); - } - $this->dispatch('proxyStatusUpdated'); - if ($this->server->proxy->status === 'running') { - $this->polling = false; - $notification && $this->dispatch('success', 'Proxy is running.'); - } elseif ($this->server->proxy->status === 'exited' and ! $this->server->proxy->force_stop) { - $notification && $this->dispatch('error', 'Proxy has exited.'); - } elseif ($this->server->proxy->force_stop) { - $notification && $this->dispatch('error', 'Proxy is stopped manually.'); - } else { - $notification && $this->dispatch('error', 'Proxy is not running.'); - } - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function getProxyStatus() - { - try { - GetContainersStatus::run($this->server); - // dispatch_sync(new ContainerStatusJob($this->server)); - $this->dispatch('proxyStatusUpdated'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } -} diff --git a/app/Livewire/Server/Security/Patches.php b/app/Livewire/Server/Security/Patches.php new file mode 100644 index 000000000..9392fc351 --- /dev/null +++ b/app/Livewire/Server/Security/Patches.php @@ -0,0 +1,102 @@ +user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},ServerPackageUpdated" => 'checkForUpdatesDispatch', + ]; + } + + public function mount() + { + if (! auth()->user()->isAdmin()) { + abort(403); + } + $this->parameters = get_route_parameters(); + $this->server = Server::ownedByCurrentTeam()->whereUuid($this->parameters['server_uuid'])->firstOrFail(); + } + + public function checkForUpdatesDispatch() + { + $this->totalUpdates = null; + $this->updates = null; + $this->error = null; + $this->osId = null; + $this->packageManager = null; + $this->dispatch('checkForUpdatesDispatch'); + } + + public function checkForUpdates() + { + $job = CheckUpdates::run($this->server); + if (isset($job['error'])) { + $this->error = data_get($job, 'error', 'Something went wrong.'); + } else { + $this->totalUpdates = data_get($job, 'total_updates', 0); + $this->updates = data_get($job, 'updates', []); + $this->osId = data_get($job, 'osId', null); + $this->packageManager = data_get($job, 'package_manager', null); + } + } + + public function updateAllPackages() + { + if (! $this->packageManager || ! $this->osId) { + $this->dispatch('error', message: 'Run โ€œCheck for updatesโ€ first.'); + return; + } + + try { + $activity = UpdatePackage::run( + server: $this->server, + packageManager: $this->packageManager, + osId: $this->osId, + all: true + ); + $this->dispatch('activityMonitor', $activity->id, ServerPackageUpdated::class); + } catch (\Exception $e) { + $this->dispatch('error', message: $e->getMessage()); + } + } + + public function updatePackage($package) + { + try { + $activity = UpdatePackage::run(server: $this->server, packageManager: $this->packageManager, osId: $this->osId, package: $package); + $this->dispatch('activityMonitor', $activity->id, ServerPackageUpdated::class); + } catch (\Exception $e) { + $this->dispatch('error', message: $e->getMessage()); + } + } + + public function render() + { + return view('livewire.server.security.patches'); + } +} diff --git a/app/Livewire/Server/Show.php b/app/Livewire/Server/Show.php index b0e6d8858..d53f10d74 100644 --- a/app/Livewire/Server/Show.php +++ b/app/Livewire/Server/Show.php @@ -86,10 +86,7 @@ class Show extends Component public function getListeners() { - $teamId = auth()->user()->currentTeam()->id; - return [ - "echo-private:team.{$teamId},CloudflareTunnelConfigured" => 'refresh', 'refreshServerShow' => 'refresh', ]; } @@ -179,7 +176,7 @@ class Show extends Component $this->sentinelCustomUrl = $this->server->settings->sentinel_custom_url; $this->isSentinelEnabled = $this->server->settings->is_sentinel_enabled; $this->isSentinelDebugEnabled = $this->server->settings->is_sentinel_debug_enabled; - $this->sentinelUpdatedAt = $this->server->settings->updated_at; + $this->sentinelUpdatedAt = $this->server->sentinel_updated_at; $this->serverTimezone = $this->server->settings->server_timezone; } } @@ -187,7 +184,6 @@ class Show extends Component public function refresh() { $this->syncData(); - $this->dispatch('$refresh'); } public function validateServer($install = true) @@ -211,7 +207,6 @@ class Show extends Component $this->server->settings->is_usable = $this->isUsable = true; $this->server->settings->save(); ServerReachabilityChanged::dispatch($this->server); - $this->dispatch('proxyStatusUpdated'); } else { $this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.

Check this documentation for further help.

Error: '.$error); diff --git a/app/Livewire/Server/ValidateAndInstall.php b/app/Livewire/Server/ValidateAndInstall.php index 791ef9350..479fdef22 100644 --- a/app/Livewire/Server/ValidateAndInstall.php +++ b/app/Livewire/Server/ValidateAndInstall.php @@ -27,8 +27,6 @@ class ValidateAndInstall extends Component public $docker_version = null; - public $proxy_started = false; - public $error = null; public bool $ask = false; @@ -39,7 +37,6 @@ class ValidateAndInstall extends Component 'validateOS', 'validateDockerEngine', 'validateDockerVersion', - 'startProxy', 'refresh' => '$refresh', ]; @@ -50,7 +47,6 @@ class ValidateAndInstall extends Component $this->docker_installed = null; $this->docker_version = null; $this->docker_compose_installed = null; - $this->proxy_started = null; $this->error = null; $this->number_of_tries = $data; if (! $this->ask) { @@ -64,25 +60,6 @@ class ValidateAndInstall extends Component $this->init(); } - public function startProxy() - { - try { - $shouldStart = CheckProxy::run($this->server); - if ($shouldStart) { - $proxy = StartProxy::run($this->server, false); - if ($proxy === 'OK') { - $this->proxy_started = true; - } else { - throw new \Exception('Proxy could not be started.'); - } - } else { - $this->proxy_started = true; - } - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - public function validateConnection() { ['uptime' => $this->uptime, 'error' => $error] = $this->server->validateConnection(); @@ -128,7 +105,7 @@ class ValidateAndInstall extends Component if ($this->number_of_tries <= $this->max_tries) { $activity = $this->server->installDocker(); $this->number_of_tries++; - $this->dispatch('newActivityMonitor', $activity->id, 'init', $this->number_of_tries); + $this->dispatch('activityMonitor', $activity->id, 'init', $this->number_of_tries); } return; @@ -157,7 +134,12 @@ class ValidateAndInstall extends Component if ($this->docker_version) { $this->dispatch('refreshServerShow'); $this->dispatch('refreshBoardingIndex'); - $this->dispatch('success', 'Server validated.'); + $this->dispatch('success', 'Server validated, proxy is starting in a moment.'); + $proxyShouldRun = CheckProxy::run($this->server, true); + if (! $proxyShouldRun) { + return; + } + StartProxy::dispatch($this->server); } else { $requiredDockerVersion = str(config('constants.docker.minimum_required_version'))->before('.'); $this->error = 'Minimum Docker Engine version '.$requiredDockerVersion.' is not instaled. Please install Docker manually before continuing: documentation.'; @@ -172,7 +154,6 @@ class ValidateAndInstall extends Component if ($this->server->isBuildServer()) { return; } - $this->dispatch('startProxy'); } public function render() diff --git a/app/Livewire/SettingsEmail.php b/app/Livewire/SettingsEmail.php index 73e8c7398..ca48e9b16 100644 --- a/app/Livewire/SettingsEmail.php +++ b/app/Livewire/SettingsEmail.php @@ -225,7 +225,7 @@ class SettingsEmail extends Component 'test-email:'.$this->team->id, $perMinute = 0, function () { - $this->team?->notify(new Test($this->testEmailAddress)); + $this->team?->notifyNow(new Test($this->testEmailAddress)); $this->dispatch('success', 'Test Email sent.'); }, $decaySeconds = 10, diff --git a/app/Livewire/Terminal/Index.php b/app/Livewire/Terminal/Index.php index a24a237c5..10084a991 100644 --- a/app/Livewire/Terminal/Index.php +++ b/app/Livewire/Terminal/Index.php @@ -21,7 +21,9 @@ class Index extends Component if (! auth()->user()->isAdmin()) { abort(403); } - $this->servers = Server::isReachable()->get(); + $this->servers = Server::isReachable()->get()->filter(function ($server) { + return $server->isTerminalEnabled(); + }); } public function loadContainers() diff --git a/app/Models/Application.php b/app/Models/Application.php index 94bd5c75b..f3f063d19 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -259,25 +259,15 @@ class Application extends BaseModel return Application::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } - public function getContainersToStop(bool $previewDeployments = false): array + public function getContainersToStop(Server $server, bool $previewDeployments = false): array { $containers = $previewDeployments - ? getCurrentApplicationContainerStatus($this->destination->server, $this->id, includePullrequests: true) - : getCurrentApplicationContainerStatus($this->destination->server, $this->id, 0); + ? getCurrentApplicationContainerStatus($server, $this->id, includePullrequests: true) + : getCurrentApplicationContainerStatus($server, $this->id, 0); return $containers->pluck('Names')->toArray(); } - public function stopContainers(array $containerNames, $server, int $timeout = 30) - { - foreach ($containerNames as $containerName) { - instant_remote_process(command: [ - "docker stop --time=$timeout $containerName", - "docker rm -f $containerName", - ], server: $server, throwError: false); - } - } - public function deleteConfigurations() { $server = data_get($this, 'destination.server'); @@ -1299,7 +1289,7 @@ class Application extends BaseModel try { $yaml = Yaml::parse($this->docker_compose_raw); } catch (\Exception $e) { - throw new \Exception($e->getMessage()); + throw new \RuntimeException($e->getMessage()); } $services = data_get($yaml, 'services'); diff --git a/app/Models/DiscordNotificationSettings.php b/app/Models/DiscordNotificationSettings.php index 1ba16ccd8..34adfc997 100644 --- a/app/Models/DiscordNotificationSettings.php +++ b/app/Models/DiscordNotificationSettings.php @@ -28,6 +28,7 @@ class DiscordNotificationSettings extends Model 'server_disk_usage_discord_notifications', 'server_reachable_discord_notifications', 'server_unreachable_discord_notifications', + 'server_patch_discord_notifications', 'discord_ping_enabled', ]; @@ -46,6 +47,7 @@ class DiscordNotificationSettings extends Model 'server_disk_usage_discord_notifications' => 'boolean', 'server_reachable_discord_notifications' => 'boolean', 'server_unreachable_discord_notifications' => 'boolean', + 'server_patch_discord_notifications' => 'boolean', 'discord_ping_enabled' => 'boolean', ]; diff --git a/app/Models/EmailNotificationSettings.php b/app/Models/EmailNotificationSettings.php index 445987619..39617b4cf 100644 --- a/app/Models/EmailNotificationSettings.php +++ b/app/Models/EmailNotificationSettings.php @@ -35,6 +35,7 @@ class EmailNotificationSettings extends Model 'scheduled_task_success_email_notifications', 'scheduled_task_failure_email_notifications', 'server_disk_usage_email_notifications', + 'server_patch_email_notifications', ]; protected $casts = [ @@ -61,6 +62,7 @@ class EmailNotificationSettings extends Model 'scheduled_task_success_email_notifications' => 'boolean', 'scheduled_task_failure_email_notifications' => 'boolean', 'server_disk_usage_email_notifications' => 'boolean', + 'server_patch_email_notifications' => 'boolean', ]; public function team() diff --git a/app/Models/EnvironmentVariable.php b/app/Models/EnvironmentVariable.php index 5f686de60..04081fce0 100644 --- a/app/Models/EnvironmentVariable.php +++ b/app/Models/EnvironmentVariable.php @@ -57,7 +57,7 @@ class EnvironmentVariable extends BaseModel if (! $found) { $application = Application::find($environment_variable->resourceable_id); - if ($application && $application->build_pack !== 'dockerfile') { + if ($application) { ModelsEnvironmentVariable::create([ 'key' => $environment_variable->key, 'value' => $environment_variable->value, diff --git a/app/Models/OauthSetting.php b/app/Models/OauthSetting.php index 3d82e89f2..bfd332c87 100644 --- a/app/Models/OauthSetting.php +++ b/app/Models/OauthSetting.php @@ -25,11 +25,11 @@ class OauthSetting extends Model { switch ($this->provider) { case 'azure': - return filled($this->client_id) && filled($this->client_secret) && filled($this->redirect_uri) && filled($this->tenant); + return filled($this->client_id) && filled($this->client_secret) && filled($this->tenant); case 'authentik': - return filled($this->client_id) && filled($this->client_secret) && filled($this->redirect_uri) && filled($this->base_url); + return filled($this->client_id) && filled($this->client_secret) && filled($this->base_url); default: - return filled($this->client_id) && filled($this->client_secret) && filled($this->redirect_uri); + return filled($this->client_id) && filled($this->client_secret); } } } diff --git a/app/Models/PushoverNotificationSettings.php b/app/Models/PushoverNotificationSettings.php index e3191dcc3..a75fd71d7 100644 --- a/app/Models/PushoverNotificationSettings.php +++ b/app/Models/PushoverNotificationSettings.php @@ -29,6 +29,7 @@ class PushoverNotificationSettings extends Model 'server_disk_usage_pushover_notifications', 'server_reachable_pushover_notifications', 'server_unreachable_pushover_notifications', + 'server_patch_pushover_notifications', ]; protected $casts = [ @@ -47,6 +48,7 @@ class PushoverNotificationSettings extends Model 'server_disk_usage_pushover_notifications' => 'boolean', 'server_reachable_pushover_notifications' => 'boolean', 'server_unreachable_pushover_notifications' => 'boolean', + 'server_patch_pushover_notifications' => 'boolean', ]; public function team() diff --git a/app/Models/Server.php b/app/Models/Server.php index fb9be5de7..eac5bbcc1 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -69,6 +69,11 @@ class Server extends BaseModel } if ($server->ip) { $payload['ip'] = str($server->ip)->trim(); + + // Update ip_previous when ip is being changed + if ($server->isDirty('ip') && $server->getOriginal('ip')) { + $payload['ip_previous'] = $server->getOriginal('ip'); + } } $server->forceFill($payload); }); @@ -952,6 +957,11 @@ $schema://$host { } } + public function isTerminalEnabled() + { + return $this->settings->is_terminal_enabled ?? false; + } + public function isSwarm() { return data_get($this, 'settings.is_swarm_manager') || data_get($this, 'settings.is_swarm_worker'); diff --git a/app/Models/ServerSetting.php b/app/Models/ServerSetting.php index f4b776cca..3abd55e9c 100644 --- a/app/Models/ServerSetting.php +++ b/app/Models/ServerSetting.php @@ -28,6 +28,7 @@ use OpenApi\Attributes as OA; 'is_sentinel_enabled' => ['type' => 'boolean'], 'is_swarm_manager' => ['type' => 'boolean'], 'is_swarm_worker' => ['type' => 'boolean'], + 'is_terminal_enabled' => ['type' => 'boolean'], 'is_usable' => ['type' => 'boolean'], 'logdrain_axiom_api_key' => ['type' => 'string'], 'logdrain_axiom_dataset_name' => ['type' => 'string'], @@ -59,6 +60,7 @@ class ServerSetting extends Model 'sentinel_token' => 'encrypted', 'is_reachable' => 'boolean', 'is_usable' => 'boolean', + 'is_terminal_enabled' => 'boolean', ]; protected static function booted() diff --git a/app/Models/Service.php b/app/Models/Service.php index 13e3a89c0..c3c8f3215 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -141,31 +141,6 @@ class Service extends BaseModel return Service::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } - public function getContainersToStop(): array - { - $containersToStop = []; - $applications = $this->applications()->get(); - foreach ($applications as $application) { - $containersToStop[] = "{$application->name}-{$this->uuid}"; - } - $dbs = $this->databases()->get(); - foreach ($dbs as $db) { - $containersToStop[] = "{$db->name}-{$this->uuid}"; - } - - return $containersToStop; - } - - public function stopContainers(array $containerNames, $server, int $timeout = 30) - { - foreach ($containerNames as $containerName) { - instant_remote_process(command: [ - "docker stop --time=$timeout $containerName", - "docker rm -f $containerName", - ], server: $server, throwError: false); - } - } - public function deleteConfigurations() { $server = data_get($this, 'destination.server'); diff --git a/app/Models/SlackNotificationSettings.php b/app/Models/SlackNotificationSettings.php index 48153f2ea..2b52bfd5b 100644 --- a/app/Models/SlackNotificationSettings.php +++ b/app/Models/SlackNotificationSettings.php @@ -28,6 +28,7 @@ class SlackNotificationSettings extends Model 'server_disk_usage_slack_notifications', 'server_reachable_slack_notifications', 'server_unreachable_slack_notifications', + 'server_patch_slack_notifications', ]; protected $casts = [ @@ -45,6 +46,7 @@ class SlackNotificationSettings extends Model 'server_disk_usage_slack_notifications' => 'boolean', 'server_reachable_slack_notifications' => 'boolean', 'server_unreachable_slack_notifications' => 'boolean', + 'server_patch_slack_notifications' => 'boolean', ]; public function team() diff --git a/app/Models/TelegramNotificationSettings.php b/app/Models/TelegramNotificationSettings.php index 78bd841bd..94315ee30 100644 --- a/app/Models/TelegramNotificationSettings.php +++ b/app/Models/TelegramNotificationSettings.php @@ -29,6 +29,7 @@ class TelegramNotificationSettings extends Model 'server_disk_usage_telegram_notifications', 'server_reachable_telegram_notifications', 'server_unreachable_telegram_notifications', + 'server_patch_telegram_notifications', 'telegram_notifications_deployment_success_thread_id', 'telegram_notifications_deployment_failure_thread_id', @@ -41,6 +42,7 @@ class TelegramNotificationSettings extends Model 'telegram_notifications_server_disk_usage_thread_id', 'telegram_notifications_server_reachable_thread_id', 'telegram_notifications_server_unreachable_thread_id', + 'telegram_notifications_server_patch_thread_id', ]; protected $casts = [ @@ -59,6 +61,7 @@ class TelegramNotificationSettings extends Model 'server_disk_usage_telegram_notifications' => 'boolean', 'server_reachable_telegram_notifications' => 'boolean', 'server_unreachable_telegram_notifications' => 'boolean', + 'server_patch_telegram_notifications' => 'boolean', 'telegram_notifications_deployment_success_thread_id' => 'encrypted', 'telegram_notifications_deployment_failure_thread_id' => 'encrypted', @@ -71,6 +74,7 @@ class TelegramNotificationSettings extends Model 'telegram_notifications_server_disk_usage_thread_id' => 'encrypted', 'telegram_notifications_server_reachable_thread_id' => 'encrypted', 'telegram_notifications_server_unreachable_thread_id' => 'encrypted', + 'telegram_notifications_server_patch_thread_id' => 'encrypted', ]; public function team() diff --git a/app/Notifications/Channels/TelegramChannel.php b/app/Notifications/Channels/TelegramChannel.php index ea4ab7171..c2fa3ff10 100644 --- a/app/Notifications/Channels/TelegramChannel.php +++ b/app/Notifications/Channels/TelegramChannel.php @@ -34,6 +34,7 @@ class TelegramChannel \App\Notifications\Server\HighDiskUsage::class => $settings->telegram_notifications_server_disk_usage_thread_id, \App\Notifications\Server\Unreachable::class => $settings->telegram_notifications_server_unreachable_thread_id, \App\Notifications\Server\Reachable::class => $settings->telegram_notifications_server_reachable_thread_id, + \App\Notifications\Server\ServerPatchCheck::class => $settings->telegram_notifications_server_patch_thread_id, default => null, }; diff --git a/app/Notifications/Server/ServerPatchCheck.php b/app/Notifications/Server/ServerPatchCheck.php new file mode 100644 index 000000000..1686a6f37 --- /dev/null +++ b/app/Notifications/Server/ServerPatchCheck.php @@ -0,0 +1,348 @@ +onQueue('high'); + $this->serverUrl = route('server.security.patches', ['server_uuid' => $this->server->uuid]); + if (isDev()) { + $this->serverUrl = 'https://staging-but-dev.coolify.io/server/'.$this->server->uuid.'/security/patches'; + } + } + + public function via(object $notifiable): array + { + return $notifiable->getEnabledChannels('server_patch'); + } + + public function toMail($notifiable = null): MailMessage + { + $mail = new MailMessage; + + // Handle error case + if (isset($this->patchData['error'])) { + $mail->subject("Coolify: [ERROR] Failed to check patches on {$this->server->name}"); + $mail->view('emails.server-patches-error', [ + 'name' => $this->server->name, + 'error' => $this->patchData['error'], + 'osId' => $this->patchData['osId'] ?? 'unknown', + 'package_manager' => $this->patchData['package_manager'] ?? 'unknown', + 'server_url' => $this->serverUrl, + ]); + + return $mail; + } + + $totalUpdates = $this->patchData['total_updates'] ?? 0; + $mail->subject("Coolify: [ACTION REQUIRED] {$totalUpdates} server patches available on {$this->server->name}"); + $mail->view('emails.server-patches', [ + 'name' => $this->server->name, + 'total_updates' => $totalUpdates, + 'updates' => $this->patchData['updates'] ?? [], + 'osId' => $this->patchData['osId'] ?? 'unknown', + 'package_manager' => $this->patchData['package_manager'] ?? 'unknown', + 'server_url' => $this->serverUrl, + ]); + + return $mail; + } + + public function toDiscord(): DiscordMessage + { + // Handle error case + if (isset($this->patchData['error'])) { + $osId = $this->patchData['osId'] ?? 'unknown'; + $packageManager = $this->patchData['package_manager'] ?? 'unknown'; + $error = $this->patchData['error']; + + $description = "**Failed to check for updates** on server {$this->server->name}\n\n"; + $description .= "**Error Details:**\n"; + $description .= 'โ€ข OS: '.ucfirst($osId)."\n"; + $description .= "โ€ข Package Manager: {$packageManager}\n"; + $description .= "โ€ข Error: {$error}\n\n"; + $description .= "[Manage Server]($this->serverUrl)"; + + return new DiscordMessage( + title: ':x: Coolify: [ERROR] Failed to check patches on '.$this->server->name, + description: $description, + color: DiscordMessage::errorColor(), + ); + } + + $totalUpdates = $this->patchData['total_updates'] ?? 0; + $updates = $this->patchData['updates'] ?? []; + $osId = $this->patchData['osId'] ?? 'unknown'; + $packageManager = $this->patchData['package_manager'] ?? 'unknown'; + + $description = "**{$totalUpdates} package updates** available for server {$this->server->name}\n\n"; + $description .= "**Summary:**\n"; + $description .= 'โ€ข OS: '.ucfirst($osId)."\n"; + $description .= "โ€ข Package Manager: {$packageManager}\n"; + $description .= "โ€ข Total Updates: {$totalUpdates}\n\n"; + + // Show first few packages + if (count($updates) > 0) { + $description .= "**Sample Updates:**\n"; + $sampleUpdates = array_slice($updates, 0, 5); + foreach ($sampleUpdates as $update) { + $description .= "โ€ข {$update['package']}: {$update['current_version']} โ†’ {$update['new_version']}\n"; + } + if (count($updates) > 5) { + $description .= 'โ€ข ... and '.(count($updates) - 5)." more packages\n"; + } + + // Check for critical packages + $criticalPackages = collect($updates)->filter(function ($update) { + return str_contains(strtolower($update['package']), 'docker') || + str_contains(strtolower($update['package']), 'kernel') || + str_contains(strtolower($update['package']), 'openssh') || + str_contains(strtolower($update['package']), 'ssl'); + }); + + if ($criticalPackages->count() > 0) { + $description .= "\n **Critical packages detected** ({$criticalPackages->count()} packages may require restarts)"; + } + $description .= "\n [Manage Server Patches]($this->serverUrl)"; + } + + return new DiscordMessage( + title: ':warning: Coolify: [ACTION REQUIRED] Server patches available on '.$this->server->name, + description: $description, + color: DiscordMessage::errorColor(), + ); + + } + + public function toTelegram(): array + { + // Handle error case + if (isset($this->patchData['error'])) { + $osId = $this->patchData['osId'] ?? 'unknown'; + $packageManager = $this->patchData['package_manager'] ?? 'unknown'; + $error = $this->patchData['error']; + + $message = "โŒ Coolify: [ERROR] Failed to check patches on {$this->server->name}!\n\n"; + $message .= "๐Ÿ“Š Error Details:\n"; + $message .= 'โ€ข OS: '.ucfirst($osId)."\n"; + $message .= "โ€ข Package Manager: {$packageManager}\n"; + $message .= "โ€ข Error: {$error}\n\n"; + + return [ + 'message' => $message, + 'buttons' => [ + [ + 'text' => 'Manage Server', + 'url' => $this->serverUrl, + ], + ], + ]; + } + + $totalUpdates = $this->patchData['total_updates'] ?? 0; + $updates = $this->patchData['updates'] ?? []; + $osId = $this->patchData['osId'] ?? 'unknown'; + $packageManager = $this->patchData['package_manager'] ?? 'unknown'; + + $message = "๐Ÿ”ง Coolify: [ACTION REQUIRED] {$totalUpdates} server patches available on {$this->server->name}!\n\n"; + $message .= "๐Ÿ“Š Summary:\n"; + $message .= 'โ€ข OS: '.ucfirst($osId)."\n"; + $message .= "โ€ข Package Manager: {$packageManager}\n"; + $message .= "โ€ข Total Updates: {$totalUpdates}\n\n"; + + if (count($updates) > 0) { + $message .= "๐Ÿ“ฆ Sample Updates:\n"; + $sampleUpdates = array_slice($updates, 0, 5); + foreach ($sampleUpdates as $update) { + $message .= "โ€ข {$update['package']}: {$update['current_version']} โ†’ {$update['new_version']}\n"; + } + if (count($updates) > 5) { + $message .= 'โ€ข ... and '.(count($updates) - 5)." more packages\n"; + } + + // Check for critical packages + $criticalPackages = collect($updates)->filter(function ($update) { + return str_contains(strtolower($update['package']), 'docker') || + str_contains(strtolower($update['package']), 'kernel') || + str_contains(strtolower($update['package']), 'openssh') || + str_contains(strtolower($update['package']), 'ssl'); + }); + + if ($criticalPackages->count() > 0) { + $message .= "\nโš ๏ธ Critical packages detected: {$criticalPackages->count()} packages may require restarts\n"; + foreach ($criticalPackages->take(3) as $package) { + $message .= "โ€ข {$package['package']}: {$package['current_version']} โ†’ {$package['new_version']}\n"; + } + if ($criticalPackages->count() > 3) { + $message .= 'โ€ข ... and '.($criticalPackages->count() - 3)." more critical packages\n"; + } + } + } + + return [ + 'message' => $message, + 'buttons' => [ + [ + 'text' => 'Manage Server Patches', + 'url' => $this->serverUrl, + ], + ], + ]; + } + + public function toPushover(): PushoverMessage + { + // Handle error case + if (isset($this->patchData['error'])) { + $osId = $this->patchData['osId'] ?? 'unknown'; + $packageManager = $this->patchData['package_manager'] ?? 'unknown'; + $error = $this->patchData['error']; + + $message = "[ERROR] Failed to check patches on {$this->server->name}!\n\n"; + $message .= "Error Details:\n"; + $message .= 'โ€ข OS: '.ucfirst($osId)."\n"; + $message .= "โ€ข Package Manager: {$packageManager}\n"; + $message .= "โ€ข Error: {$error}\n\n"; + + return new PushoverMessage( + title: 'Server patch check failed', + level: 'error', + message: $message, + buttons: [ + [ + 'text' => 'Manage Server', + 'url' => $this->serverUrl, + ], + ], + ); + } + + $totalUpdates = $this->patchData['total_updates'] ?? 0; + $updates = $this->patchData['updates'] ?? []; + $osId = $this->patchData['osId'] ?? 'unknown'; + $packageManager = $this->patchData['package_manager'] ?? 'unknown'; + + $message = "[ACTION REQUIRED] {$totalUpdates} server patches available on {$this->server->name}!\n\n"; + $message .= "Summary:\n"; + $message .= 'โ€ข OS: '.ucfirst($osId)."\n"; + $message .= "โ€ข Package Manager: {$packageManager}\n"; + $message .= "โ€ข Total Updates: {$totalUpdates}\n\n"; + + if (count($updates) > 0) { + $message .= "Sample Updates:\n"; + $sampleUpdates = array_slice($updates, 0, 3); + foreach ($sampleUpdates as $update) { + $message .= "โ€ข {$update['package']}: {$update['current_version']} โ†’ {$update['new_version']}\n"; + } + if (count($updates) > 3) { + $message .= 'โ€ข ... and '.(count($updates) - 3)." more packages\n"; + } + + // Check for critical packages + $criticalPackages = collect($updates)->filter(function ($update) { + return str_contains(strtolower($update['package']), 'docker') || + str_contains(strtolower($update['package']), 'kernel') || + str_contains(strtolower($update['package']), 'openssh') || + str_contains(strtolower($update['package']), 'ssl'); + }); + + if ($criticalPackages->count() > 0) { + $message .= "\nCritical packages detected: {$criticalPackages->count()} may require restarts"; + } + } + + return new PushoverMessage( + title: 'Server patches available', + level: 'error', + message: $message, + buttons: [ + [ + 'text' => 'Manage Server Patches', + 'url' => $this->serverUrl, + ], + ], + ); + } + + public function toSlack(): SlackMessage + { + // Handle error case + if (isset($this->patchData['error'])) { + $osId = $this->patchData['osId'] ?? 'unknown'; + $packageManager = $this->patchData['package_manager'] ?? 'unknown'; + $error = $this->patchData['error']; + + $description = "Failed to check patches on '{$this->server->name}'!\n\n"; + $description .= "*Error Details:*\n"; + $description .= 'โ€ข OS: '.ucfirst($osId)."\n"; + $description .= "โ€ข Package Manager: {$packageManager}\n"; + $description .= "โ€ข Error: `{$error}`\n\n"; + $description .= "\n:link: <{$this->serverUrl}|Manage Server>"; + + return new SlackMessage( + title: 'Coolify: [ERROR] Server patch check failed', + description: $description, + color: SlackMessage::errorColor() + ); + } + + $totalUpdates = $this->patchData['total_updates'] ?? 0; + $updates = $this->patchData['updates'] ?? []; + $osId = $this->patchData['osId'] ?? 'unknown'; + $packageManager = $this->patchData['package_manager'] ?? 'unknown'; + + $description = "{$totalUpdates} server patches available on '{$this->server->name}'!\n\n"; + $description .= "*Summary:*\n"; + $description .= 'โ€ข OS: '.ucfirst($osId)."\n"; + $description .= "โ€ข Package Manager: {$packageManager}\n"; + $description .= "โ€ข Total Updates: {$totalUpdates}\n\n"; + + if (count($updates) > 0) { + $description .= "*Sample Updates:*\n"; + $sampleUpdates = array_slice($updates, 0, 5); + foreach ($sampleUpdates as $update) { + $description .= "โ€ข `{$update['package']}`: {$update['current_version']} โ†’ {$update['new_version']}\n"; + } + if (count($updates) > 5) { + $description .= 'โ€ข ... and '.(count($updates) - 5)." more packages\n"; + } + + // Check for critical packages + $criticalPackages = collect($updates)->filter(function ($update) { + return str_contains(strtolower($update['package']), 'docker') || + str_contains(strtolower($update['package']), 'kernel') || + str_contains(strtolower($update['package']), 'openssh') || + str_contains(strtolower($update['package']), 'ssl'); + }); + + if ($criticalPackages->count() > 0) { + $description .= "\n:warning: *Critical packages detected:* {$criticalPackages->count()} packages may require restarts\n"; + foreach ($criticalPackages->take(3) as $package) { + $description .= "โ€ข `{$package['package']}`: {$package['current_version']} โ†’ {$package['new_version']}\n"; + } + if ($criticalPackages->count() > 3) { + $description .= 'โ€ข ... and '.($criticalPackages->count() - 3)." more critical packages\n"; + } + } + } + + $description .= "\n:link: <{$this->serverUrl}|Manage Server Patches>"; + + return new SlackMessage( + title: 'Coolify: [ACTION REQUIRED] Server patches available', + description: $description, + color: SlackMessage::errorColor() + ); + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index d76ec3037..b960dd8e3 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -2,10 +2,8 @@ namespace App\Providers; -use App\Events\ProxyStarted; use App\Listeners\MaintenanceModeDisabledNotification; use App\Listeners\MaintenanceModeEnabledNotification; -use App\Listeners\ProxyStartedNotification; use Illuminate\Foundation\Events\MaintenanceModeDisabled; use Illuminate\Foundation\Events\MaintenanceModeEnabled; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; @@ -30,9 +28,6 @@ class EventServiceProvider extends ServiceProvider GoogleExtendSocialite::class.'@handle', InfomaniakExtendSocialite::class.'@handle', ], - ProxyStarted::class => [ - ProxyStartedNotification::class, - ], ]; public function boot(): void @@ -42,6 +37,6 @@ class EventServiceProvider extends ServiceProvider public function shouldDiscoverEvents(): bool { - return false; + return true; } } diff --git a/app/Services/ProxyDashboardCacheService.php b/app/Services/ProxyDashboardCacheService.php new file mode 100644 index 000000000..5d31f9b08 --- /dev/null +++ b/app/Services/ProxyDashboardCacheService.php @@ -0,0 +1,57 @@ +id}:traefik:dashboard_available"; + } + + /** + * Check if Traefik dashboard is available from configuration + */ + public static function isTraefikDashboardAvailableFromConfiguration(Server $server, string $proxy_configuration): void + { + $cacheKey = static::getCacheKey($server); + $dashboardAvailable = str($proxy_configuration)->contains('--api.dashboard=true') && + str($proxy_configuration)->contains('--api.insecure=true'); + Cache::forever($cacheKey, $dashboardAvailable); + } + + /** + * Check if Traefik dashboard is available (from cache or compute) + */ + public static function isTraefikDashboardAvailableFromCache(Server $server): bool + { + $cacheKey = static::getCacheKey($server); + + return Cache::get($cacheKey) ?? false; + } + + /** + * Clear Traefik dashboard cache for a server + */ + public static function clearCache(Server $server): void + { + Cache::forget(static::getCacheKey($server)); + } + + /** + * Clear Traefik dashboard cache for multiple servers + */ + public static function clearCacheForServers(array $serverIds): void + { + foreach ($serverIds as $serverId) { + $cacheKey = "server:{$serverId}:traefik:dashboard_available"; + Cache::forget($cacheKey); + } + } +} diff --git a/app/Traits/ExecuteRemoteCommand.php b/app/Traits/ExecuteRemoteCommand.php index f8ccee9db..a228a5d10 100644 --- a/app/Traits/ExecuteRemoteCommand.php +++ b/app/Traits/ExecuteRemoteCommand.php @@ -49,9 +49,13 @@ trait ExecuteRemoteCommand if ($output->startsWith('โ•”')) { $output = "\n".$output; } + + // Sanitize output to ensure valid UTF-8 encoding before JSON encoding + $sanitized_output = sanitize_utf8_text($output); + $new_log_entry = [ 'command' => remove_iip($command), - 'output' => remove_iip($output), + 'output' => remove_iip($sanitized_output), 'type' => $customType ?? $type === 'err' ? 'stderr' : 'stdout', 'timestamp' => Carbon::now('UTC'), 'hidden' => $hidden, @@ -60,11 +64,29 @@ trait ExecuteRemoteCommand if (! $this->application_deployment_queue->logs) { $new_log_entry['order'] = 1; } else { - $previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR); - $new_log_entry['order'] = count($previous_logs) + 1; + try { + $previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR); + } catch (\JsonException $e) { + // If existing logs are corrupted, start fresh + $previous_logs = []; + $new_log_entry['order'] = 1; + } + if (is_array($previous_logs)) { + $new_log_entry['order'] = count($previous_logs) + 1; + } else { + $previous_logs = []; + $new_log_entry['order'] = 1; + } } $previous_logs[] = $new_log_entry; - $this->application_deployment_queue->logs = json_encode($previous_logs, flags: JSON_THROW_ON_ERROR); + + try { + $this->application_deployment_queue->logs = json_encode($previous_logs, flags: JSON_THROW_ON_ERROR); + } catch (\JsonException $e) { + // If JSON encoding still fails, use fallback with invalid sequences replacement + $this->application_deployment_queue->logs = json_encode($previous_logs, flags: JSON_INVALID_UTF8_SUBSTITUTE); + } + $this->application_deployment_queue->save(); if ($this->save) { @@ -72,10 +94,10 @@ trait ExecuteRemoteCommand data_set($this->saved_outputs, $this->save, str()); } if ($append) { - $this->saved_outputs[$this->save] .= str($output)->trim(); + $this->saved_outputs[$this->save] .= str($sanitized_output)->trim(); $this->saved_outputs[$this->save] = str($this->saved_outputs[$this->save]); } else { - $this->saved_outputs[$this->save] = str($output)->trim(); + $this->saved_outputs[$this->save] = str($sanitized_output)->trim(); } } }); diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index bade67eb8..930f95041 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -99,7 +99,7 @@ function format_docker_envs_to_json($rawOutput) $outputLines = json_decode($rawOutput, true, flags: JSON_THROW_ON_ERROR); return collect(data_get($outputLines[0], 'Config.Env', []))->mapWithKeys(function ($env) { - $env = explode('=', $env); + $env = explode('=', $env, 2); return [$env[0] => $env[1]]; }); @@ -724,11 +724,12 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview return $labels->all(); } -function isDatabaseImage(?string $image = null) +function isDatabaseImage(?string $image = null, ?array $serviceConfig = null) { if (is_null($image)) { return false; } + $image = str($image); if ($image->contains(':')) { $image = str($image); @@ -736,13 +737,170 @@ function isDatabaseImage(?string $image = null) $image = str($image)->append(':latest'); } $imageName = $image->before(':'); + + // First check if it's a known database image + $isKnownDatabase = false; foreach (DATABASE_DOCKER_IMAGES as $database_docker_image) { if (str($imageName)->contains($database_docker_image)) { - return true; + $isKnownDatabase = true; + break; } } - return false; + // If no database pattern found, it's definitely not a database + if (! $isKnownDatabase) { + return false; + } + + // If we have service configuration, use additional context to make better decisions + if (! is_null($serviceConfig)) { + return isDatabaseImageWithContext($imageName, $serviceConfig); + } + + // Fallback to original behavior for backward compatibility + return $isKnownDatabase; +} + +function isDatabaseImageWithContext(string $imageName, array $serviceConfig): bool +{ + // Known application images that contain database names but are not databases + $knownApplicationPatterns = [ + // SuperTokens authentication + 'supertokens/supertokens-mysql', + 'supertokens/supertokens-postgresql', + 'supertokens/supertokens-mongodb', + 'registry.supertokens.io/supertokens/supertokens-mysql', + 'registry.supertokens.io/supertokens/supertokens-postgresql', + 'registry.supertokens.io/supertokens/supertokens-mongodb', + 'registry.supertokens.io/supertokens', + + // Analytics and BI tools + 'metabase/metabase', // Uses databases but is not a database + 'amancevice/superset', // Uses databases but is not a database + 'nocodb/nocodb', // Uses databases but is not a database + 'ghcr.io/umami-software/umami', // Web analytics with postgresql variant + + // Secret management + 'infisical/infisical', // Secret management with postgres variant + + // Development tools + 'postgrest/postgrest', // REST API for PostgreSQL + 'supabase/postgres-meta', // PostgreSQL metadata API + 'bluewaveuptime/uptime_redis', // Uptime monitoring with Redis + ]; + + foreach ($knownApplicationPatterns as $pattern) { + if (str($imageName)->contains($pattern)) { + return false; + } + } + + // Check for database-like ports (common database ports indicate it's likely a database) + $databasePorts = ['3306', '5432', '27017', '6379', '8086', '9200', '7687', '8123']; + $ports = data_get($serviceConfig, 'ports', []); + $hasStandardDbPort = false; + + if (is_array($ports)) { + foreach ($ports as $port) { + $portStr = is_string($port) ? $port : (string) $port; + foreach ($databasePorts as $dbPort) { + if (str($portStr)->contains($dbPort)) { + $hasStandardDbPort = true; + break 2; + } + } + } + } + + // Check environment variables for database-specific patterns + $environment = data_get($serviceConfig, 'environment', []); + $hasDbEnvVars = false; + $hasAppEnvVars = false; + + if (is_array($environment)) { + foreach ($environment as $env) { + $envStr = is_string($env) ? $env : (string) $env; + $envUpper = strtoupper($envStr); + + // Database-specific environment variables + if (str($envUpper)->contains(['MYSQL_ROOT_PASSWORD', 'POSTGRES_PASSWORD', 'MONGO_INITDB_ROOT_PASSWORD', 'REDIS_PASSWORD'])) { + $hasDbEnvVars = true; + } + + // Application-specific environment variables + if (str($envUpper)->contains(['SERVICE_FQDN', 'API_KEYS', 'APP_', 'APPLICATION_'])) { + $hasAppEnvVars = true; + } + } + } + + // Check healthcheck patterns + $healthcheck = data_get($serviceConfig, 'healthcheck.test', []); + $hasDbHealthcheck = false; + $hasAppHealthcheck = false; + + if (is_array($healthcheck)) { + $healthcheckStr = implode(' ', $healthcheck); + } else { + $healthcheckStr = is_string($healthcheck) ? $healthcheck : ''; + } + + if (! empty($healthcheckStr)) { + $healthcheckUpper = strtoupper($healthcheckStr); + + // Database-specific healthcheck patterns + if (str($healthcheckUpper)->contains(['PG_ISREADY', 'MYSQLADMIN PING', 'MONGO', 'REDIS-CLI PING'])) { + $hasDbHealthcheck = true; + } + + // Application-specific healthcheck patterns (HTTP endpoints) + if (str($healthcheckUpper)->contains(['CURL', 'WGET', 'HTTP://', 'HTTPS://', '/HEALTH', '/API/', '/HELLO'])) { + $hasAppHealthcheck = true; + } + } + + // Check if service depends on other database services + $dependsOn = data_get($serviceConfig, 'depends_on', []); + $dependsOnDatabases = false; + + if (is_array($dependsOn)) { + foreach ($dependsOn as $serviceName => $config) { + $serviceNameStr = is_string($serviceName) ? $serviceName : (string) $serviceName; + if (str($serviceNameStr)->contains(['mysql', 'postgres', 'mongo', 'redis', 'mariadb'])) { + $dependsOnDatabases = true; + break; + } + } + } + + // Decision logic: + // 1. If it has app-specific patterns and depends on databases, it's likely an application + if ($hasAppEnvVars && $dependsOnDatabases) { + return false; + } + + // 2. If it has HTTP healthchecks, it's likely an application + if ($hasAppHealthcheck) { + return false; + } + + // 3. If it has standard database ports AND database healthchecks, it's likely a database + if ($hasStandardDbPort && $hasDbHealthcheck) { + return true; + } + + // 4. If it has database environment variables, it's likely a database + if ($hasDbEnvVars) { + return true; + } + + // 5. Default: if it depends on databases but doesn't have database characteristics, it's an application + if ($dependsOnDatabases) { + return false; + } + + // 6. Fallback: assume it's a database if we can't determine otherwise + return true; } function convertDockerRunToCompose(?string $custom_docker_run_options = null) diff --git a/bootstrap/helpers/proxy.php b/bootstrap/helpers/proxy.php index 714358e37..cabdabaa7 100644 --- a/bootstrap/helpers/proxy.php +++ b/bootstrap/helpers/proxy.php @@ -91,21 +91,17 @@ function connectProxyToNetworks(Server $server) if ($server->isSwarm()) { $commands = $networks->map(function ($network) { return [ - "echo 'Connecting coolify-proxy to $network network...'", "docker network ls --format '{{.Name}}' | grep '^$network$' >/dev/null || docker network create --driver overlay --attachable $network >/dev/null", "docker network connect $network coolify-proxy >/dev/null 2>&1 || true", "echo 'Successfully connected coolify-proxy to $network network.'", - "echo 'Proxy started and configured successfully!'", ]; }); } else { $commands = $networks->map(function ($network) { return [ - "echo 'Connecting coolify-proxy to $network network...'", "docker network ls --format '{{.Name}}' | grep '^$network$' >/dev/null || docker network create --attachable $network >/dev/null", "docker network connect $network coolify-proxy >/dev/null 2>&1 || true", "echo 'Successfully connected coolify-proxy to $network network.'", - "echo 'Proxy started and configured successfully!'", ]; }); } diff --git a/bootstrap/helpers/remoteProcess.php b/bootstrap/helpers/remoteProcess.php index d1cb93d9a..6c1e2beab 100644 --- a/bootstrap/helpers/remoteProcess.php +++ b/bootstrap/helpers/remoteProcess.php @@ -94,8 +94,12 @@ function instant_remote_process_with_timeout(Collection|array $command, Server $ return $throwError ? excludeCertainErrors($process->errorOutput(), $exitCode) : null; } - return $output === 'null' ? null : $output; + // Sanitize output to ensure valid UTF-8 encoding + $output = $output === 'null' ? null : sanitize_utf8_text($output); + + return $output; } + function instant_remote_process(Collection|array $command, Server $server, bool $throwError = true, bool $no_sudo = false): ?string { $command = $command instanceof Collection ? $command->toArray() : $command; @@ -119,7 +123,10 @@ function instant_remote_process(Collection|array $command, Server $server, bool return $throwError ? excludeCertainErrors($process->errorOutput(), $exitCode) : null; } - return $output === 'null' ? null : $output; + // Sanitize output to ensure valid UTF-8 encoding + $output = $output === 'null' ? null : sanitize_utf8_text($output); + + return $output; } function excludeCertainErrors(string $errorOutput, ?int $exitCode = null) @@ -143,15 +150,38 @@ function decode_remote_command_output(?ApplicationDeploymentQueue $application_d } $application = Application::find(data_get($application_deployment_queue, 'application_id')); $is_debug_enabled = data_get($application, 'settings.is_debug_enabled'); + + $logs = data_get($application_deployment_queue, 'logs'); + if (empty($logs)) { + return collect([]); + } + try { $decoded = json_decode( - data_get($application_deployment_queue, 'logs'), + $logs, associative: true, flags: JSON_THROW_ON_ERROR ); - } catch (\JsonException) { + } catch (\JsonException $e) { + // If JSON decoding fails, try to clean up the logs and retry + try { + // Ensure valid UTF-8 encoding + $cleaned_logs = sanitize_utf8_text($logs); + $decoded = json_decode( + $cleaned_logs, + associative: true, + flags: JSON_THROW_ON_ERROR + ); + } catch (\JsonException $e) { + // If it still fails, return empty collection to prevent crashes + return collect([]); + } + } + + if (! is_array($decoded)) { return collect([]); } + $seenCommands = collect(); $formatted = collect($decoded); if (! $is_debug_enabled) { @@ -204,11 +234,41 @@ function decode_remote_command_output(?ApplicationDeploymentQueue $application_d function remove_iip($text) { + // Ensure the input is valid UTF-8 before processing + $text = sanitize_utf8_text($text); + $text = preg_replace('/x-access-token:.*?(?=@)/', 'x-access-token:'.REDACTED, $text); return preg_replace('/\x1b\[[0-9;]*m/', '', $text); } +/** + * Sanitizes text to ensure it contains valid UTF-8 encoding. + * + * This function is crucial for preventing "Malformed UTF-8 characters" errors + * that can occur when Docker build output contains binary data mixed with text, + * especially during image processing or builds with many assets. + * + * @param string|null $text The text to sanitize + * @return string Valid UTF-8 encoded text + */ +function sanitize_utf8_text(?string $text): string +{ + if (empty($text)) { + return ''; + } + + // Convert to UTF-8, replacing invalid sequences + $sanitized = mb_convert_encoding($text, 'UTF-8', 'UTF-8'); + + // Additional fallback: use SUBSTITUTE flag to replace invalid sequences with substitution character + if (! mb_check_encoding($sanitized, 'UTF-8')) { + $sanitized = mb_convert_encoding($text, 'UTF-8', mb_detect_encoding($text, mb_detect_order(), true) ?: 'UTF-8'); + } + + return $sanitized; +} + function refresh_server_connection(?PrivateKey $private_key = null) { if (is_null($private_key)) { diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 8b2d9fb6a..2f1b934bb 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -478,7 +478,7 @@ function queryDatabaseByUuidWithinTeam(string $uuid, string $teamId) { $postgresql = StandalonePostgresql::whereUuid($uuid)->first(); if ($postgresql && $postgresql->team()->id == $teamId) { - return $postgresql->unsetRelation('environment')->unsetRelation('destination'); + return $postgresql->unsetRelation('environment'); } $redis = StandaloneRedis::whereUuid($uuid)->first(); if ($redis && $redis->team()->id == $teamId) { @@ -599,7 +599,7 @@ function getTopLevelNetworks(Service|Application $resource) try { $yaml = Yaml::parse($resource->docker_compose_raw); } catch (\Exception $e) { - throw new \Exception($e->getMessage()); + throw new \RuntimeException($e->getMessage()); } $services = data_get($yaml, 'services'); $topLevelNetworks = collect(data_get($yaml, 'networks', [])); @@ -653,7 +653,7 @@ function getTopLevelNetworks(Service|Application $resource) try { $yaml = Yaml::parse($resource->docker_compose_raw); } catch (\Exception $e) { - throw new \Exception($e->getMessage()); + throw new \RuntimeException($e->getMessage()); } $server = $resource->destination->server; $topLevelNetworks = collect(data_get($yaml, 'networks', [])); @@ -1435,7 +1435,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal try { $yaml = Yaml::parse($resource->docker_compose_raw); } catch (\Exception $e) { - throw new \Exception($e->getMessage()); + throw new \RuntimeException($e->getMessage()); } $allServices = get_service_templates(); $topLevelVolumes = collect(data_get($yaml, 'volumes', [])); @@ -1506,8 +1506,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $containerName = "$serviceName-{$resource->uuid}"; // Decide if the service is a database - $isDatabase = isDatabaseImage(data_get_str($service, 'image')); $image = data_get_str($service, 'image'); + $isDatabase = isDatabaseImage($image, $service); data_set($service, 'is_database', $isDatabase); // Create new serviceApplication or serviceDatabase @@ -2494,7 +2494,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } // Decide if the service is a database - $isDatabase = isDatabaseImage(data_get_str($service, 'image')); + $image = data_get_str($service, 'image'); + $isDatabase = isDatabaseImage($image, $service); data_set($service, 'is_database', $isDatabase); // Collect/create/update networks @@ -2965,7 +2966,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $environment = collect(data_get($service, 'environment', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); - $isDatabase = isDatabaseImage(data_get_str($service, 'image')); + $isDatabase = isDatabaseImage($image, $service); if ($isService) { $containerName = "$serviceName-{$resource->uuid}"; @@ -3214,7 +3215,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $environment = convertToKeyValueCollection($environment); $coolifyEnvironments = collect([]); - $isDatabase = isDatabaseImage(data_get_str($service, 'image')); + $isDatabase = isDatabaseImage($image, $service); $volumesParsed = collect([]); if ($isApplication) { diff --git a/bootstrap/helpers/socialite.php b/bootstrap/helpers/socialite.php index 16870e33d..fe19752cb 100644 --- a/bootstrap/helpers/socialite.php +++ b/bootstrap/helpers/socialite.php @@ -7,6 +7,10 @@ function get_socialite_provider(string $provider) { $oauth_setting = OauthSetting::firstWhere('provider', $provider); + if (! filled($oauth_setting->redirect_uri)) { + $oauth_setting->update(['redirect_uri' => route('auth.callback', $provider)]); + } + if ($provider === 'azure') { $azure_config = new \SocialiteProviders\Manager\Config( $oauth_setting->client_id, diff --git a/composer.json b/composer.json index 5b97e76e9..3fb1206ce 100644 --- a/composer.json +++ b/composer.json @@ -12,11 +12,11 @@ ], "require": { "php": "^8.4", - "danharrin/livewire-rate-limiting": "2.1.0", + "danharrin/livewire-rate-limiting": "^2.1.0", "doctrine/dbal": "^4.2.2", "guzzlehttp/guzzle": "^7.9.2", "laravel/fortify": "^1.25.4", - "laravel/framework": "12.4.1", + "laravel/framework": "^12.4.1", "laravel/horizon": "^5.30.3", "laravel/pail": "^1.2.2", "laravel/prompts": "^0.3.5|^0.3.5|^0.3.5", @@ -124,4 +124,4 @@ "@php artisan key:generate --ansi" ] } -} +} \ No newline at end of file diff --git a/composer.lock b/composer.lock index 939178d38..14ae57fcb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f0ef990aa6e05ab48d61fcc22c0c1ca2", + "content-hash": "ae74a752b941c9b981288c2934479eb8", "packages": [ { "name": "amphp/amp", @@ -870,16 +870,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.342.17", + "version": "3.343.20", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "110ca44672e59ec3255c693e9e761001f2706b53" + "reference": "bf40b00d2e1cbd2a5d8c903743073440d8ebb5dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/110ca44672e59ec3255c693e9e761001f2706b53", - "reference": "110ca44672e59ec3255c693e9e761001f2706b53", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/bf40b00d2e1cbd2a5d8c903743073440d8ebb5dc", + "reference": "bf40b00d2e1cbd2a5d8c903743073440d8ebb5dc", "shasum": "" }, "require": { @@ -961,9 +961,9 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.342.17" + "source": "https://github.com/aws/aws-sdk-php/tree/3.343.20" }, - "time": "2025-03-31T18:16:40+00:00" + "time": "2025-05-28T18:10:03+00:00" }, { "name": "bacon/bacon-qr-code", @@ -1479,26 +1479,29 @@ }, { "name": "doctrine/deprecations", - "version": "1.1.4", + "version": "1.1.5", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9" + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/31610dbb31faa98e6b5447b62340826f54fbc4e9", - "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, "require-dev": { - "doctrine/coding-standard": "^9 || ^12", - "phpstan/phpstan": "1.4.10 || 2.0.3", + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", "phpstan/phpstan-phpunit": "^1.0 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", "psr/log": "^1 || ^2 || ^3" }, "suggest": { @@ -1518,9 +1521,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.4" + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" }, - "time": "2024-12-07T21:18:45+00:00" + "time": "2025-04-07T20:06:18+00:00" }, { "name": "doctrine/inflector", @@ -1885,16 +1888,16 @@ }, { "name": "firebase/php-jwt", - "version": "v6.11.0", + "version": "v6.11.1", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "8f718f4dfc9c5d5f0c994cdfd103921b43592712" + "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/8f718f4dfc9c5d5f0c994cdfd103921b43592712", - "reference": "8f718f4dfc9c5d5f0c994cdfd103921b43592712", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d1e91ecf8c598d073d0995afa8cd5c75c6e19e66", + "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66", "shasum": "" }, "require": { @@ -1942,9 +1945,9 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.11.0" + "source": "https://github.com/firebase/php-jwt/tree/v6.11.1" }, - "time": "2025-01-23T05:11:06+00:00" + "time": "2025-04-09T20:32:01+00:00" }, { "name": "fruitcake/php-cors", @@ -2675,16 +2678,16 @@ }, { "name": "laravel/framework", - "version": "v12.4.1", + "version": "v12.16.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "cdefd852ecb459a65392cd6ccb578c92a15b8e2b" + "reference": "293bb1c70224faebfd3d4328e201c37115da055f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/cdefd852ecb459a65392cd6ccb578c92a15b8e2b", - "reference": "cdefd852ecb459a65392cd6ccb578c92a15b8e2b", + "url": "https://api.github.com/repos/laravel/framework/zipball/293bb1c70224faebfd3d4328e201c37115da055f", + "reference": "293bb1c70224faebfd3d4328e201c37115da055f", "shasum": "" }, "require": { @@ -2705,7 +2708,7 @@ "guzzlehttp/uri-template": "^1.0", "laravel/prompts": "^0.3.0", "laravel/serializable-closure": "^1.3|^2.0", - "league/commonmark": "^2.6", + "league/commonmark": "^2.7", "league/flysystem": "^3.25.1", "league/flysystem-local": "^3.25.1", "league/uri": "^7.5.1", @@ -2793,11 +2796,11 @@ "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", "orchestra/testbench-core": "^10.0.0", - "pda/pheanstalk": "^5.0.6", + "pda/pheanstalk": "^5.0.6|^7.0.0", "php-http/discovery": "^1.15", "phpstan/phpstan": "^2.0", "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", - "predis/predis": "^2.3", + "predis/predis": "^2.3|^3.0", "resend/resend-php": "^0.10.0", "symfony/cache": "^7.2.0", "symfony/http-client": "^7.2.0", @@ -2829,7 +2832,7 @@ "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1).", - "predis/predis": "Required to use the predis connector (^2.3).", + "predis/predis": "Required to use the predis connector (^2.3|^3.0).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", @@ -2886,20 +2889,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-30T16:27:26+00:00" + "time": "2025-05-27T15:49:44+00:00" }, { "name": "laravel/horizon", - "version": "v5.31.0", + "version": "v5.32.1", "source": { "type": "git", "url": "https://github.com/laravel/horizon.git", - "reference": "a21e7d64784b24eaf3bf873f82affbf67707a72a" + "reference": "e78d9689d85b3d4769dc64def5eb6d94e5776beb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/horizon/zipball/a21e7d64784b24eaf3bf873f82affbf67707a72a", - "reference": "a21e7d64784b24eaf3bf873f82affbf67707a72a", + "url": "https://api.github.com/repos/laravel/horizon/zipball/e78d9689d85b3d4769dc64def5eb6d94e5776beb", + "reference": "e78d9689d85b3d4769dc64def5eb6d94e5776beb", "shasum": "" }, "require": { @@ -2939,7 +2942,7 @@ ] }, "branch-alias": { - "dev-master": "5.x-dev" + "dev-master": "6.x-dev" } }, "autoload": { @@ -2964,9 +2967,9 @@ ], "support": { "issues": "https://github.com/laravel/horizon/issues", - "source": "https://github.com/laravel/horizon/tree/v5.31.0" + "source": "https://github.com/laravel/horizon/tree/v5.32.1" }, - "time": "2025-03-04T14:56:42+00:00" + "time": "2025-05-19T13:13:30+00:00" }, { "name": "laravel/pail", @@ -3107,16 +3110,16 @@ }, { "name": "laravel/sanctum", - "version": "v4.0.8", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "ec1dd9ddb2ab370f79dfe724a101856e0963f43c" + "reference": "a360a6a1fd2400ead4eb9b6a9c1bb272939194f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/ec1dd9ddb2ab370f79dfe724a101856e0963f43c", - "reference": "ec1dd9ddb2ab370f79dfe724a101856e0963f43c", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/a360a6a1fd2400ead4eb9b6a9c1bb272939194f5", + "reference": "a360a6a1fd2400ead4eb9b6a9c1bb272939194f5", "shasum": "" }, "require": { @@ -3167,7 +3170,7 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2025-01-26T19:34:36+00:00" + "time": "2025-04-23T13:03:38+00:00" }, { "name": "laravel/serializable-closure", @@ -3232,16 +3235,16 @@ }, { "name": "laravel/socialite", - "version": "v5.18.0", + "version": "v5.21.0", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "7809dc71250e074cd42970f0f803f2cddc04c5de" + "reference": "d83639499ad14985c9a6a9713b70073300ce998d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/7809dc71250e074cd42970f0f803f2cddc04c5de", - "reference": "7809dc71250e074cd42970f0f803f2cddc04c5de", + "url": "https://api.github.com/repos/laravel/socialite/zipball/d83639499ad14985c9a6a9713b70073300ce998d", + "reference": "d83639499ad14985c9a6a9713b70073300ce998d", "shasum": "" }, "require": { @@ -3258,7 +3261,7 @@ "require-dev": { "mockery/mockery": "^1.0", "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.0|^10.0", - "phpstan/phpstan": "^1.10", + "phpstan/phpstan": "^1.12.23", "phpunit/phpunit": "^8.0|^9.3|^10.4|^11.5" }, "type": "library", @@ -3300,7 +3303,7 @@ "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" }, - "time": "2025-02-11T13:38:19+00:00" + "time": "2025-05-19T12:56:37+00:00" }, { "name": "laravel/tinker", @@ -3506,16 +3509,16 @@ }, { "name": "league/commonmark", - "version": "2.6.1", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "d990688c91cedfb69753ffc2512727ec646df2ad" + "reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d990688c91cedfb69753ffc2512727ec646df2ad", - "reference": "d990688c91cedfb69753ffc2512727ec646df2ad", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6fbb36d44824ed4091adbcf4c7d4a3923cdb3405", + "reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405", "shasum": "" }, "require": { @@ -3552,7 +3555,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.7-dev" + "dev-main": "2.8-dev" } }, "autoload": { @@ -3609,7 +3612,7 @@ "type": "tidelift" } ], - "time": "2024-12-29T14:10:59+00:00" + "time": "2025-05-05T12:20:28+00:00" }, { "name": "league/config", @@ -4237,16 +4240,16 @@ }, { "name": "livewire/livewire", - "version": "v3.6.2", + "version": "v3.6.3", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "8f8914731f5eb43b6bb145d87c8d5a9edfc89313" + "reference": "56aa1bb63a46e06181c56fa64717a7287e19115e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/8f8914731f5eb43b6bb145d87c8d5a9edfc89313", - "reference": "8f8914731f5eb43b6bb145d87c8d5a9edfc89313", + "url": "https://api.github.com/repos/livewire/livewire/zipball/56aa1bb63a46e06181c56fa64717a7287e19115e", + "reference": "56aa1bb63a46e06181c56fa64717a7287e19115e", "shasum": "" }, "require": { @@ -4301,7 +4304,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.6.2" + "source": "https://github.com/livewire/livewire/tree/v3.6.3" }, "funding": [ { @@ -4309,7 +4312,7 @@ "type": "github" } ], - "time": "2025-03-12T20:24:15+00:00" + "time": "2025-04-12T22:26:52+00:00" }, { "name": "log1x/laravel-webfonts", @@ -4692,16 +4695,16 @@ }, { "name": "nesbot/carbon", - "version": "3.8.6", + "version": "3.9.1", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd" + "reference": "ced71f79398ece168e24f7f7710462f462310d4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ff2f20cf83bd4d503720632ce8a426dc747bf7fd", - "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ced71f79398ece168e24f7f7710462f462310d4d", + "reference": "ced71f79398ece168e24f7f7710462f462310d4d", "shasum": "" }, "require": { @@ -4794,7 +4797,7 @@ "type": "tidelift" } ], - "time": "2025-02-20T17:33:38+00:00" + "time": "2025-05-01T19:51:51+00:00" }, { "name": "nette/schema", @@ -5057,31 +5060,31 @@ }, { "name": "nunomaduro/termwind", - "version": "v2.3.0", + "version": "v2.3.1", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda" + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda", - "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.1.8" + "symfony/console": "^7.2.6" }, "require-dev": { - "illuminate/console": "^11.33.2", - "laravel/pint": "^1.18.2", + "illuminate/console": "^11.44.7", + "laravel/pint": "^1.22.0", "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0", - "phpstan/phpstan": "^1.12.11", - "phpstan/phpstan-strict-rules": "^1.6.1", - "symfony/var-dumper": "^7.1.8", + "pestphp/pest": "^2.36.0 || ^3.8.2", + "phpstan/phpstan": "^1.12.25", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.2.6", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -5124,7 +5127,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.0" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" }, "funding": [ { @@ -5140,7 +5143,7 @@ "type": "github" } ], - "time": "2024-11-21T10:39:51+00:00" + "time": "2025-05-08T08:14:37+00:00" }, { "name": "nyholm/psr7", @@ -5485,16 +5488,16 @@ }, { "name": "php-di/php-di", - "version": "7.0.9", + "version": "7.0.10", "source": { "type": "git", "url": "https://github.com/PHP-DI/PHP-DI.git", - "reference": "d8480267f5cf239650debba704f3ecd15b638cde" + "reference": "0d1ed64126577e9a095b3204dcaee58cf76432c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/d8480267f5cf239650debba704f3ecd15b638cde", - "reference": "d8480267f5cf239650debba704f3ecd15b638cde", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/0d1ed64126577e9a095b3204dcaee58cf76432c2", + "reference": "0d1ed64126577e9a095b3204dcaee58cf76432c2", "shasum": "" }, "require": { @@ -5510,7 +5513,7 @@ "friendsofphp/php-cs-fixer": "^3", "friendsofphp/proxy-manager-lts": "^1", "mnapoli/phpunit-easymock": "^1.3", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^9.6 || ^10 || ^11", "vimeo/psalm": "^5|^6" }, "suggest": { @@ -5542,7 +5545,7 @@ ], "support": { "issues": "https://github.com/PHP-DI/PHP-DI/issues", - "source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.9" + "source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.10" }, "funding": [ { @@ -5554,7 +5557,7 @@ "type": "tidelift" } ], - "time": "2025-02-28T12:46:35+00:00" + "time": "2025-04-22T08:53:15+00:00" }, { "name": "phpdocumentor/reflection", @@ -5678,16 +5681,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.1", + "version": "5.6.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8" + "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8", - "reference": "e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/92dde6a5919e34835c506ac8c523ef095a95ed62", + "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62", "shasum": "" }, "require": { @@ -5736,9 +5739,9 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.1" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.2" }, - "time": "2024-12-07T09:39:29+00:00" + "time": "2025-04-13T19:20:35+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -7253,16 +7256,16 @@ }, { "name": "sentry/sentry", - "version": "4.10.0", + "version": "4.11.1", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "2af937d47d8aadb8dab0b1d7b9557e495dd12856" + "reference": "53dc0bcb6a667cac5b760b46f98d5380e63e02ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/2af937d47d8aadb8dab0b1d7b9557e495dd12856", - "reference": "2af937d47d8aadb8dab0b1d7b9557e495dd12856", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/53dc0bcb6a667cac5b760b46f98d5380e63e02ca", + "reference": "53dc0bcb6a667cac5b760b46f98d5380e63e02ca", "shasum": "" }, "require": { @@ -7326,7 +7329,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/4.10.0" + "source": "https://github.com/getsentry/sentry-php/tree/4.11.1" }, "funding": [ { @@ -7338,7 +7341,7 @@ "type": "custom" } ], - "time": "2024-11-06T07:44:19+00:00" + "time": "2025-05-12T11:30:33+00:00" }, { "name": "sentry/sentry-laravel", @@ -7698,16 +7701,16 @@ }, { "name": "spatie/backtrace", - "version": "1.7.1", + "version": "1.7.4", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "0f2477c520e3729de58e061b8192f161c99f770b" + "reference": "cd37a49fce7137359ac30ecc44ef3e16404cccbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/0f2477c520e3729de58e061b8192f161c99f770b", - "reference": "0f2477c520e3729de58e061b8192f161c99f770b", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/cd37a49fce7137359ac30ecc44ef3e16404cccbe", + "reference": "cd37a49fce7137359ac30ecc44ef3e16404cccbe", "shasum": "" }, "require": { @@ -7745,7 +7748,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.7.1" + "source": "https://github.com/spatie/backtrace/tree/1.7.4" }, "funding": [ { @@ -7757,7 +7760,7 @@ "type": "other" } ], - "time": "2024-12-02T13:28:15+00:00" + "time": "2025-05-08T15:41:09+00:00" }, { "name": "spatie/laravel-activitylog", @@ -7852,16 +7855,16 @@ }, { "name": "spatie/laravel-data", - "version": "4.14.1", + "version": "4.15.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-data.git", - "reference": "edd61b4dca5acdcfd1e3b7f2c19b75e83730f87c" + "reference": "cb97afe6c0dadeb2e76ea1b7220cd04ed33dcca9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-data/zipball/edd61b4dca5acdcfd1e3b7f2c19b75e83730f87c", - "reference": "edd61b4dca5acdcfd1e3b7f2c19b75e83730f87c", + "url": "https://api.github.com/repos/spatie/laravel-data/zipball/cb97afe6c0dadeb2e76ea1b7220cd04ed33dcca9", + "reference": "cb97afe6c0dadeb2e76ea1b7220cd04ed33dcca9", "shasum": "" }, "require": { @@ -7874,6 +7877,7 @@ "require-dev": { "fakerphp/faker": "^1.14", "friendsofphp/php-cs-fixer": "^3.0", + "inertiajs/inertia-laravel": "^2.0", "livewire/livewire": "^3.0", "mockery/mockery": "^1.6", "nesbot/carbon": "^2.63|^3.0", @@ -7922,7 +7926,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-data/issues", - "source": "https://github.com/spatie/laravel-data/tree/4.14.1" + "source": "https://github.com/spatie/laravel-data/tree/4.15.1" }, "funding": [ { @@ -7930,20 +7934,20 @@ "type": "github" } ], - "time": "2025-03-17T13:54:28+00:00" + "time": "2025-04-10T06:06:27+00:00" }, { "name": "spatie/laravel-package-tools", - "version": "1.92.0", + "version": "1.92.4", "source": { "type": "git", "url": "https://github.com/spatie/laravel-package-tools.git", - "reference": "dd46cd0ed74015db28822d88ad2e667f4496a6f6" + "reference": "d20b1969f836d210459b78683d85c9cd5c5f508c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/dd46cd0ed74015db28822d88ad2e667f4496a6f6", - "reference": "dd46cd0ed74015db28822d88ad2e667f4496a6f6", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/d20b1969f836d210459b78683d85c9cd5c5f508c", + "reference": "d20b1969f836d210459b78683d85c9cd5c5f508c", "shasum": "" }, "require": { @@ -7954,6 +7958,7 @@ "mockery/mockery": "^1.5", "orchestra/testbench": "^7.7|^8.0|^9.0|^10.0", "pestphp/pest": "^1.23|^2.1|^3.1", + "phpunit/php-code-coverage": "^9.0|^10.0|^11.0", "phpunit/phpunit": "^9.5.24|^10.5|^11.5", "spatie/pest-plugin-test-time": "^1.1|^2.2" }, @@ -7982,7 +7987,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-package-tools/issues", - "source": "https://github.com/spatie/laravel-package-tools/tree/1.92.0" + "source": "https://github.com/spatie/laravel-package-tools/tree/1.92.4" }, "funding": [ { @@ -7990,7 +7995,7 @@ "type": "github" } ], - "time": "2025-03-27T08:34:10+00:00" + "time": "2025-04-11T15:27:14+00:00" }, { "name": "spatie/laravel-ray", @@ -8287,16 +8292,16 @@ }, { "name": "spatie/ray", - "version": "1.41.6", + "version": "1.42.0", "source": { "type": "git", "url": "https://github.com/spatie/ray.git", - "reference": "ae6e32a54a901544a3d70b12b865900bc240f71c" + "reference": "152250ce7c490bf830349fa30ba5200084e95860" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ray/zipball/ae6e32a54a901544a3d70b12b865900bc240f71c", - "reference": "ae6e32a54a901544a3d70b12b865900bc240f71c", + "url": "https://api.github.com/repos/spatie/ray/zipball/152250ce7c490bf830349fa30ba5200084e95860", + "reference": "152250ce7c490bf830349fa30ba5200084e95860", "shasum": "" }, "require": { @@ -8356,7 +8361,7 @@ ], "support": { "issues": "https://github.com/spatie/ray/issues", - "source": "https://github.com/spatie/ray/tree/1.41.6" + "source": "https://github.com/spatie/ray/tree/1.42.0" }, "funding": [ { @@ -8368,7 +8373,7 @@ "type": "other" } ], - "time": "2025-03-21T08:56:30+00:00" + "time": "2025-04-18T08:17:40+00:00" }, { "name": "spatie/url", @@ -8434,16 +8439,16 @@ }, { "name": "stevebauman/purify", - "version": "v6.3.0", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/stevebauman/purify.git", - "reference": "2e5e6e1bfe072189b6056c6ad4a8c68ba57f3ba1" + "reference": "3acb5e77904f420ce8aad8fa1c7f394e82daa500" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stevebauman/purify/zipball/2e5e6e1bfe072189b6056c6ad4a8c68ba57f3ba1", - "reference": "2e5e6e1bfe072189b6056c6ad4a8c68ba57f3ba1", + "url": "https://api.github.com/repos/stevebauman/purify/zipball/3acb5e77904f420ce8aad8fa1c7f394e82daa500", + "reference": "3acb5e77904f420ce8aad8fa1c7f394e82daa500", "shasum": "" }, "require": { @@ -8494,9 +8499,9 @@ ], "support": { "issues": "https://github.com/stevebauman/purify/issues", - "source": "https://github.com/stevebauman/purify/tree/v6.3.0" + "source": "https://github.com/stevebauman/purify/tree/v6.3.1" }, - "time": "2025-02-18T23:08:15+00:00" + "time": "2025-05-21T16:53:09+00:00" }, { "name": "stripe/stripe-php", @@ -8559,7 +8564,7 @@ }, { "name": "symfony/clock", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", @@ -8613,7 +8618,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.2.0" + "source": "https://github.com/symfony/clock/tree/v7.3.0" }, "funding": [ { @@ -8633,23 +8638,24 @@ }, { "name": "symfony/console", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "e51498ea18570c062e7df29d05a7003585b19b88" + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88", - "reference": "e51498ea18570c062e7df29d05a7003585b19b88", + "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0" + "symfony/string": "^7.2" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -8706,7 +8712,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.5" + "source": "https://github.com/symfony/console/tree/v7.3.0" }, "funding": [ { @@ -8722,11 +8728,11 @@ "type": "tidelift" } ], - "time": "2025-03-12T08:11:12+00:00" + "time": "2025-05-24T10:34:04+00:00" }, { "name": "symfony/css-selector", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -8771,7 +8777,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.2.0" + "source": "https://github.com/symfony/css-selector/tree/v7.3.0" }, "funding": [ { @@ -8791,16 +8797,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -8813,7 +8819,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -8838,7 +8844,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -8854,20 +8860,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/error-handler", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b" + "reference": "cf68d225bc43629de4ff54778029aee6dc191b83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", - "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/cf68d225bc43629de4ff54778029aee6dc191b83", + "reference": "cf68d225bc43629de4ff54778029aee6dc191b83", "shasum": "" }, "require": { @@ -8880,9 +8886,11 @@ "symfony/http-kernel": "<6.4" }, "require-dev": { + "symfony/console": "^6.4|^7.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0" + "symfony/serializer": "^6.4|^7.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -8913,7 +8921,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.2.5" + "source": "https://github.com/symfony/error-handler/tree/v7.3.0" }, "funding": [ { @@ -8929,20 +8937,20 @@ "type": "tidelift" } ], - "time": "2025-03-03T07:12:39+00:00" + "time": "2025-05-29T07:19:49+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", "shasum": "" }, "require": { @@ -8993,7 +9001,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" }, "funding": [ { @@ -9009,20 +9017,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-04-22T09:11:45+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { @@ -9036,7 +9044,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -9069,7 +9077,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -9085,20 +9093,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/finder", - "version": "v7.2.2", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d", "shasum": "" }, "require": { @@ -9133,7 +9141,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.2" + "source": "https://github.com/symfony/finder/tree/v7.3.0" }, "funding": [ { @@ -9149,20 +9157,20 @@ "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2024-12-30T19:00:26+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "371272aeb6286f8135e028ca535f8e4d6f114126" + "reference": "4236baf01609667d53b20371486228231eb135fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/371272aeb6286f8135e028ca535f8e4d6f114126", - "reference": "371272aeb6286f8135e028ca535f8e4d6f114126", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/4236baf01609667d53b20371486228231eb135fd", + "reference": "4236baf01609667d53b20371486228231eb135fd", "shasum": "" }, "require": { @@ -9179,6 +9187,7 @@ "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", "symfony/cache": "^6.4.12|^7.1.5", + "symfony/clock": "^6.4|^7.0", "symfony/dependency-injection": "^6.4|^7.0", "symfony/expression-language": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", @@ -9211,7 +9220,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.2.5" + "source": "https://github.com/symfony/http-foundation/tree/v7.3.0" }, "funding": [ { @@ -9227,20 +9236,20 @@ "type": "tidelift" } ], - "time": "2025-03-25T15:54:33+00:00" + "time": "2025-05-12T14:48:23+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54" + "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b1fe91bc1fa454a806d3f98db4ba826eb9941a54", - "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ac7b8e163e8c83dce3abcc055a502d4486051a9f", + "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f", "shasum": "" }, "require": { @@ -9248,8 +9257,8 @@ "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.3", + "symfony/http-foundation": "^7.3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -9325,7 +9334,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.5" + "source": "https://github.com/symfony/http-kernel/tree/v7.3.0" }, "funding": [ { @@ -9341,20 +9350,20 @@ "type": "tidelift" } ], - "time": "2025-03-28T13:32:50+00:00" + "time": "2025-05-29T07:47:32+00:00" }, { "name": "symfony/mailer", - "version": "v7.2.3", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3" + "reference": "0f375bbbde96ae8c78e4aa3e63aabd486e33364c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/f3871b182c44997cf039f3b462af4a48fb85f9d3", - "reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3", + "url": "https://api.github.com/repos/symfony/mailer/zipball/0f375bbbde96ae8c78e4aa3e63aabd486e33364c", + "reference": "0f375bbbde96ae8c78e4aa3e63aabd486e33364c", "shasum": "" }, "require": { @@ -9405,7 +9414,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.2.3" + "source": "https://github.com/symfony/mailer/tree/v7.3.0" }, "funding": [ { @@ -9421,20 +9430,20 @@ "type": "tidelift" } ], - "time": "2025-01-27T11:08:17+00:00" + "time": "2025-04-04T09:51:09+00:00" }, { "name": "symfony/mime", - "version": "v7.2.4", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "87ca22046b78c3feaff04b337f33b38510fd686b" + "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/87ca22046b78c3feaff04b337f33b38510fd686b", - "reference": "87ca22046b78c3feaff04b337f33b38510fd686b", + "url": "https://api.github.com/repos/symfony/mime/zipball/0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", + "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", "shasum": "" }, "require": { @@ -9489,7 +9498,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.2.4" + "source": "https://github.com/symfony/mime/tree/v7.3.0" }, "funding": [ { @@ -9505,20 +9514,20 @@ "type": "tidelift" } ], - "time": "2025-02-19T08:51:20+00:00" + "time": "2025-02-19T08:51:26+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca", + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca", "shasum": "" }, "require": { @@ -9556,7 +9565,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.3.0" }, "funding": [ { @@ -9572,11 +9581,11 @@ "type": "tidelift" } ], - "time": "2024-11-20T11:17:29+00:00" + "time": "2025-04-04T13:12:05+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -9635,7 +9644,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { @@ -9655,16 +9664,16 @@ }, { "name": "symfony/polyfill-iconv", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "48becf00c920479ca2e910c22a5a39e5d47ca956" + "reference": "5f3b930437ae03ae5dff61269024d8ea1b3774aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/48becf00c920479ca2e910c22a5a39e5d47ca956", - "reference": "48becf00c920479ca2e910c22a5a39e5d47ca956", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/5f3b930437ae03ae5dff61269024d8ea1b3774aa", + "reference": "5f3b930437ae03ae5dff61269024d8ea1b3774aa", "shasum": "" }, "require": { @@ -9715,7 +9724,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-iconv/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.32.0" }, "funding": [ { @@ -9731,11 +9740,11 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-09-17T14:58:18+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", @@ -9793,7 +9802,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -9813,16 +9822,16 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", - "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", "shasum": "" }, "require": { @@ -9876,7 +9885,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" }, "funding": [ { @@ -9892,11 +9901,11 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-09-10T14:38:51+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -9957,7 +9966,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -9977,19 +9986,20 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { + "ext-iconv": "*", "php": ">=7.2" }, "provide": { @@ -10037,7 +10047,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -10053,20 +10063,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { @@ -10117,7 +10127,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" }, "funding": [ { @@ -10133,11 +10143,11 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", @@ -10193,7 +10203,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" }, "funding": [ { @@ -10213,7 +10223,7 @@ }, { "name": "symfony/polyfill-uuid", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", @@ -10272,7 +10282,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0" }, "funding": [ { @@ -10292,16 +10302,16 @@ }, { "name": "symfony/process", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", + "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", "shasum": "" }, "require": { @@ -10333,7 +10343,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.5" + "source": "https://github.com/symfony/process/tree/v7.3.0" }, "funding": [ { @@ -10349,11 +10359,11 @@ "type": "tidelift" } ], - "time": "2025-03-13T12:21:46+00:00" + "time": "2025-04-17T09:11:12+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", @@ -10416,7 +10426,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.2.0" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.3.0" }, "funding": [ { @@ -10436,16 +10446,16 @@ }, { "name": "symfony/routing", - "version": "v7.2.3", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "ee9a67edc6baa33e5fae662f94f91fd262930996" + "reference": "8e213820c5fea844ecea29203d2a308019007c15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/ee9a67edc6baa33e5fae662f94f91fd262930996", - "reference": "ee9a67edc6baa33e5fae662f94f91fd262930996", + "url": "https://api.github.com/repos/symfony/routing/zipball/8e213820c5fea844ecea29203d2a308019007c15", + "reference": "8e213820c5fea844ecea29203d2a308019007c15", "shasum": "" }, "require": { @@ -10497,7 +10507,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.2.3" + "source": "https://github.com/symfony/routing/tree/v7.3.0" }, "funding": [ { @@ -10513,20 +10523,20 @@ "type": "tidelift" } ], - "time": "2025-01-17T10:56:55+00:00" + "time": "2025-05-24T20:43:28+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { @@ -10544,7 +10554,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -10580,7 +10590,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -10596,11 +10606,11 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "symfony/stopwatch", - "version": "v7.2.4", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -10642,7 +10652,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.2.4" + "source": "https://github.com/symfony/stopwatch/tree/v7.3.0" }, "funding": [ { @@ -10662,16 +10672,16 @@ }, { "name": "symfony/string", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", + "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", "shasum": "" }, "require": { @@ -10729,7 +10739,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.0" + "source": "https://github.com/symfony/string/tree/v7.3.0" }, "funding": [ { @@ -10745,20 +10755,20 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:31:26+00:00" + "time": "2025-04-20T20:19:01+00:00" }, { "name": "symfony/translation", - "version": "v7.2.4", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "283856e6981286cc0d800b53bd5703e8e363f05a" + "reference": "4aba29076a29a3aa667e09b791e5f868973a8667" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/283856e6981286cc0d800b53bd5703e8e363f05a", - "reference": "283856e6981286cc0d800b53bd5703e8e363f05a", + "url": "https://api.github.com/repos/symfony/translation/zipball/4aba29076a29a3aa667e09b791e5f868973a8667", + "reference": "4aba29076a29a3aa667e09b791e5f868973a8667", "shasum": "" }, "require": { @@ -10768,6 +10778,7 @@ "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { + "nikic/php-parser": "<5.0", "symfony/config": "<6.4", "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", @@ -10781,7 +10792,7 @@ "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { - "nikic/php-parser": "^4.18|^5.0", + "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", "symfony/config": "^6.4|^7.0", "symfony/console": "^6.4|^7.0", @@ -10824,7 +10835,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.2.4" + "source": "https://github.com/symfony/translation/tree/v7.3.0" }, "funding": [ { @@ -10840,20 +10851,20 @@ "type": "tidelift" } ], - "time": "2025-02-13T10:27:23+00:00" + "time": "2025-05-29T07:19:49+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", "shasum": "" }, "require": { @@ -10866,7 +10877,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -10902,7 +10913,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" }, "funding": [ { @@ -10918,20 +10929,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-27T08:32:26+00:00" }, { "name": "symfony/uid", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "2d294d0c48df244c71c105a169d0190bfb080426" + "reference": "7beeb2b885cd584cd01e126c5777206ae4c3c6a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/2d294d0c48df244c71c105a169d0190bfb080426", - "reference": "2d294d0c48df244c71c105a169d0190bfb080426", + "url": "https://api.github.com/repos/symfony/uid/zipball/7beeb2b885cd584cd01e126c5777206ae4c3c6a3", + "reference": "7beeb2b885cd584cd01e126c5777206ae4c3c6a3", "shasum": "" }, "require": { @@ -10976,7 +10987,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.2.0" + "source": "https://github.com/symfony/uid/tree/v7.3.0" }, "funding": [ { @@ -10992,24 +11003,25 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-05-24T14:28:13+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.2.3", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "82b478c69745d8878eb60f9a049a4d584996f73a" + "reference": "548f6760c54197b1084e1e5c71f6d9d523f2f78e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/82b478c69745d8878eb60f9a049a4d584996f73a", - "reference": "82b478c69745d8878eb60f9a049a4d584996f73a", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/548f6760c54197b1084e1e5c71f6d9d523f2f78e", + "reference": "548f6760c54197b1084e1e5c71f6d9d523f2f78e", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { @@ -11059,7 +11071,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.2.3" + "source": "https://github.com/symfony/var-dumper/tree/v7.3.0" }, "funding": [ { @@ -11075,20 +11087,20 @@ "type": "tidelift" } ], - "time": "2025-01-17T11:39:41+00:00" + "time": "2025-04-27T18:39:23+00:00" }, { "name": "symfony/yaml", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912" + "reference": "cea40a48279d58dc3efee8112634cb90141156c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912", - "reference": "4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912", + "url": "https://api.github.com/repos/symfony/yaml/zipball/cea40a48279d58dc3efee8112634cb90141156c2", + "reference": "cea40a48279d58dc3efee8112634cb90141156c2", "shasum": "" }, "require": { @@ -11131,7 +11143,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.2.5" + "source": "https://github.com/symfony/yaml/tree/v7.3.0" }, "funding": [ { @@ -11147,7 +11159,7 @@ "type": "tidelift" } ], - "time": "2025-03-03T07:12:39+00:00" + "time": "2025-04-04T10:10:33+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -11264,16 +11276,16 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.6.1", + "version": "v5.6.2", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", - "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", "shasum": "" }, "require": { @@ -11332,7 +11344,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" }, "funding": [ { @@ -11344,7 +11356,7 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:52:34+00:00" + "time": "2025-04-30T23:37:27+00:00" }, { "name": "voku/portable-ascii", @@ -11798,16 +11810,16 @@ }, { "name": "zircote/swagger-php", - "version": "5.0.7", + "version": "5.1.3", "source": { "type": "git", "url": "https://github.com/zircote/swagger-php.git", - "reference": "18457fa71f753cfd4a2b21916baf329864fdfaa6" + "reference": "b8ba6bd99805c0ae09a38d1b26c1c92820509bd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zircote/swagger-php/zipball/18457fa71f753cfd4a2b21916baf329864fdfaa6", - "reference": "18457fa71f753cfd4a2b21916baf329864fdfaa6", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/b8ba6bd99805c0ae09a38d1b26c1c92820509bd0", + "reference": "b8ba6bd99805c0ae09a38d1b26c1c92820509bd0", "shasum": "" }, "require": { @@ -11868,8 +11880,8 @@ "homepage": "https://radebatz.net" } ], - "description": "swagger-php - Generate interactive documentation for your RESTful API using phpdoc annotations", - "homepage": "https://github.com/zircote/swagger-php/", + "description": "Generate interactive documentation for your RESTful API using PHP attributes (preferred) or PHPDoc annotations", + "homepage": "https://github.com/zircote/swagger-php", "keywords": [ "api", "json", @@ -11878,24 +11890,24 @@ ], "support": { "issues": "https://github.com/zircote/swagger-php/issues", - "source": "https://github.com/zircote/swagger-php/tree/5.0.7" + "source": "https://github.com/zircote/swagger-php/tree/5.1.3" }, - "time": "2025-03-19T03:31:11+00:00" + "time": "2025-05-20T03:35:10+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.15.2", + "version": "v3.15.4", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "0bc1e1361e7fffc2be156f46ad1fba6927c01729" + "reference": "c0667ea91f7185f1e074402c5788195e96bf8106" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/0bc1e1361e7fffc2be156f46ad1fba6927c01729", - "reference": "0bc1e1361e7fffc2be156f46ad1fba6927c01729", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/c0667ea91f7185f1e074402c5788195e96bf8106", + "reference": "c0667ea91f7185f1e074402c5788195e96bf8106", "shasum": "" }, "require": { @@ -11906,9 +11918,6 @@ "php-debugbar/php-debugbar": "~2.1.1", "symfony/finder": "^6|^7" }, - "conflict": { - "maximebf/debugbar": "*" - }, "require-dev": { "mockery/mockery": "^1.3.3", "orchestra/testbench-dusk": "^7|^8|^9|^10", @@ -11958,7 +11967,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.15.2" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.15.4" }, "funding": [ { @@ -11970,7 +11979,7 @@ "type": "github" } ], - "time": "2025-02-25T15:25:22+00:00" + "time": "2025-04-16T06:32:06+00:00" }, { "name": "brianium/paratest", @@ -12067,20 +12076,20 @@ }, { "name": "driftingly/rector-laravel", - "version": "2.0.2", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/driftingly/rector-laravel.git", - "reference": "f0e3a9e2c92ff760730d1af34fbdc43f51f3b868" + "reference": "ac61de4f267c23249d175d7fc9149fd01528567d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/f0e3a9e2c92ff760730d1af34fbdc43f51f3b868", - "reference": "f0e3a9e2c92ff760730d1af34fbdc43f51f3b868", + "url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/ac61de4f267c23249d175d7fc9149fd01528567d", + "reference": "ac61de4f267c23249d175d7fc9149fd01528567d", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", + "php": "^7.4 || ^8.0", "rector/rector": "^2.0" }, "type": "rector-extension", @@ -12096,9 +12105,9 @@ "description": "Rector upgrades rules for Laravel Framework", "support": { "issues": "https://github.com/driftingly/rector-laravel/issues", - "source": "https://github.com/driftingly/rector-laravel/tree/2.0.2" + "source": "https://github.com/driftingly/rector-laravel/tree/2.0.5" }, - "time": "2025-01-17T18:07:03+00:00" + "time": "2025-05-14T17:30:41+00:00" }, { "name": "fakerphp/faker", @@ -12297,20 +12306,20 @@ }, { "name": "hamcrest/hamcrest-php", - "version": "v2.0.1", + "version": "v2.1.1", "source": { "type": "git", "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", "shasum": "" }, "require": { - "php": "^5.3|^7.0|^8.0" + "php": "^7.4|^8.0" }, "replace": { "cordoval/hamcrest-php": "*", @@ -12318,8 +12327,8 @@ "kodova/hamcrest-php": "*" }, "require-dev": { - "phpunit/php-file-iterator": "^1.4 || ^2.0", - "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" }, "type": "library", "extra": { @@ -12342,9 +12351,9 @@ ], "support": { "issues": "https://github.com/hamcrest/hamcrest-php/issues", - "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" }, - "time": "2020-07-09T08:09:16+00:00" + "time": "2025-04-30T06:54:44+00:00" }, { "name": "laravel/dusk", @@ -12422,16 +12431,16 @@ }, { "name": "laravel/pint", - "version": "v1.21.2", + "version": "v1.22.1", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "370772e7d9e9da087678a0edf2b11b6960e40558" + "reference": "941d1927c5ca420c22710e98420287169c7bcaf7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/370772e7d9e9da087678a0edf2b11b6960e40558", - "reference": "370772e7d9e9da087678a0edf2b11b6960e40558", + "url": "https://api.github.com/repos/laravel/pint/zipball/941d1927c5ca420c22710e98420287169c7bcaf7", + "reference": "941d1927c5ca420c22710e98420287169c7bcaf7", "shasum": "" }, "require": { @@ -12442,12 +12451,12 @@ "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.72.0", - "illuminate/view": "^11.44.2", - "larastan/larastan": "^3.2.0", + "friendsofphp/php-cs-fixer": "^3.75.0", + "illuminate/view": "^11.44.7", + "larastan/larastan": "^3.4.0", "laravel-zero/framework": "^11.36.1", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^2.3", + "nunomaduro/termwind": "^2.3.1", "pestphp/pest": "^2.36.0" }, "bin": [ @@ -12484,20 +12493,20 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2025-03-14T22:31:42+00:00" + "time": "2025-05-08T08:38:12+00:00" }, { "name": "laravel/telescope", - "version": "v5.6.0", + "version": "v5.8.0", "source": { "type": "git", "url": "https://github.com/laravel/telescope.git", - "reference": "352dc633c2fe500c169e3401a10a7efae4fc3327" + "reference": "9be1b8851b8ffe67689e7960135f8b32a966f23d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/telescope/zipball/352dc633c2fe500c169e3401a10a7efae4fc3327", - "reference": "352dc633c2fe500c169e3401a10a7efae4fc3327", + "url": "https://api.github.com/repos/laravel/telescope/zipball/9be1b8851b8ffe67689e7960135f8b32a966f23d", + "reference": "9be1b8851b8ffe67689e7960135f8b32a966f23d", "shasum": "" }, "require": { @@ -12551,9 +12560,9 @@ ], "support": { "issues": "https://github.com/laravel/telescope/issues", - "source": "https://github.com/laravel/telescope/tree/v5.6.0" + "source": "https://github.com/laravel/telescope/tree/v5.8.0" }, - "time": "2025-03-17T20:24:10+00:00" + "time": "2025-05-26T17:22:18+00:00" }, { "name": "mockery/mockery", @@ -12640,16 +12649,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.0", + "version": "1.13.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414" + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", "shasum": "" }, "require": { @@ -12688,7 +12697,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" }, "funding": [ { @@ -12696,42 +12705,43 @@ "type": "tidelift" } ], - "time": "2025-02-12T12:17:51+00:00" + "time": "2025-04-29T12:36:36+00:00" }, { "name": "nunomaduro/collision", - "version": "v8.7.0", + "version": "v8.8.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "586cb8181a257a2152b6a855ca8d9598878a1a26" + "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/586cb8181a257a2152b6a855ca8d9598878a1a26", - "reference": "586cb8181a257a2152b6a855ca8d9598878a1a26", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/4cf9f3b47afff38b139fb79ce54fc71799022ce8", + "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8", "shasum": "" }, "require": { - "filp/whoops": "^2.17.0", + "filp/whoops": "^2.18.0", "nunomaduro/termwind": "^2.3.0", "php": "^8.2.0", - "symfony/console": "^7.2.1" + "symfony/console": "^7.2.5" }, "conflict": { - "laravel/framework": "<11.39.1 || >=13.0.0", - "phpunit/phpunit": "<11.5.3 || >=12.0.0" + "laravel/framework": "<11.44.2 || >=13.0.0", + "phpunit/phpunit": "<11.5.15 || >=13.0.0" }, "require-dev": { - "larastan/larastan": "^2.10.0", - "laravel/framework": "^11.44.2", + "brianium/paratest": "^7.8.3", + "larastan/larastan": "^3.2", + "laravel/framework": "^11.44.2 || ^12.6", "laravel/pint": "^1.21.2", "laravel/sail": "^1.41.0", "laravel/sanctum": "^4.0.8", "laravel/tinker": "^2.10.1", - "orchestra/testbench-core": "^9.12.0", - "pestphp/pest": "^3.7.4", - "sebastian/environment": "^6.1.0 || ^7.2.0" + "orchestra/testbench-core": "^9.12.0 || ^10.1", + "pestphp/pest": "^3.8.0", + "sebastian/environment": "^7.2.0 || ^8.0" }, "type": "library", "extra": { @@ -12794,25 +12804,25 @@ "type": "patreon" } ], - "time": "2025-03-14T22:37:40+00:00" + "time": "2025-04-03T14:33:09+00:00" }, { "name": "pestphp/pest", - "version": "v3.8.0", + "version": "v3.8.2", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "42e1b9f17fc2b2036701f4b968158264bde542d4" + "reference": "c6244a8712968dbac88eb998e7ff3b5caa556b0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/42e1b9f17fc2b2036701f4b968158264bde542d4", - "reference": "42e1b9f17fc2b2036701f4b968158264bde542d4", + "url": "https://api.github.com/repos/pestphp/pest/zipball/c6244a8712968dbac88eb998e7ff3b5caa556b0d", + "reference": "c6244a8712968dbac88eb998e7ff3b5caa556b0d", "shasum": "" }, "require": { "brianium/paratest": "^7.8.3", - "nunomaduro/collision": "^8.7.0", + "nunomaduro/collision": "^8.8.0", "nunomaduro/termwind": "^2.3.0", "pestphp/pest-plugin": "^3.0.0", "pestphp/pest-plugin-arch": "^3.1.0", @@ -12894,7 +12904,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v3.8.0" + "source": "https://github.com/pestphp/pest/tree/v3.8.2" }, "funding": [ { @@ -12906,7 +12916,7 @@ "type": "github" } ], - "time": "2025-03-30T17:49:10+00:00" + "time": "2025-04-17T10:53:02+00:00" }, { "name": "pestphp/pest-plugin", @@ -12980,16 +12990,16 @@ }, { "name": "pestphp/pest-plugin-arch", - "version": "v3.1.0", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin-arch.git", - "reference": "ebec636b97ee73936ee8485e15a59c3f5a4c21b2" + "reference": "db7bd9cb1612b223e16618d85475c6f63b9c8daa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/ebec636b97ee73936ee8485e15a59c3f5a4c21b2", - "reference": "ebec636b97ee73936ee8485e15a59c3f5a4c21b2", + "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/db7bd9cb1612b223e16618d85475c6f63b9c8daa", + "reference": "db7bd9cb1612b223e16618d85475c6f63b9c8daa", "shasum": "" }, "require": { @@ -12998,7 +13008,7 @@ "ta-tikoma/phpunit-architecture-test": "^0.8.4" }, "require-dev": { - "pestphp/pest": "^3.7.5", + "pestphp/pest": "^3.8.1", "pestphp/pest-dev-tools": "^3.4.0" }, "type": "library", @@ -13034,7 +13044,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-arch/tree/v3.1.0" + "source": "https://github.com/pestphp/pest-plugin-arch/tree/v3.1.1" }, "funding": [ { @@ -13046,7 +13056,7 @@ "type": "github" } ], - "time": "2025-03-30T17:28:50+00:00" + "time": "2025-04-16T22:59:48+00:00" }, { "name": "pestphp/pest-plugin-mutate", @@ -13376,16 +13386,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.11", + "version": "2.1.17", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "8ca5f79a8f63c49b2359065832a654e1ec70ac30" + "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8ca5f79a8f63c49b2359065832a654e1ec70ac30", - "reference": "8ca5f79a8f63c49b2359065832a654e1ec70ac30", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053", + "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053", "shasum": "" }, "require": { @@ -13430,7 +13440,7 @@ "type": "github" } ], - "time": "2025-03-24T13:45:00+00:00" + "time": "2025-05-21T20:55:28+00:00" }, { "name": "phpunit/php-code-coverage", @@ -13858,21 +13868,21 @@ }, { "name": "rector/rector", - "version": "2.0.11", + "version": "2.0.16", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "059b827cc648929711606e9824337e41e2f9ed92" + "reference": "f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/059b827cc648929711606e9824337e41e2f9ed92", - "reference": "059b827cc648929711606e9824337e41e2f9ed92", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2", + "reference": "f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2", "shasum": "" }, "require": { "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.9" + "phpstan/phpstan": "^2.1.14" }, "conflict": { "rector/rector-doctrine": "*", @@ -13905,7 +13915,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.0.11" + "source": "https://github.com/rectorphp/rector/tree/2.0.16" }, "funding": [ { @@ -13913,7 +13923,7 @@ "type": "github" } ], - "time": "2025-03-28T10:25:17+00:00" + "time": "2025-05-12T16:37:16+00:00" }, { "name": "sebastian/cli-parser", @@ -14292,23 +14302,23 @@ }, { "name": "sebastian/environment", - "version": "7.2.0", + "version": "7.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", - "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.3" }, "suggest": { "ext-posix": "*" @@ -14344,15 +14354,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" } ], - "time": "2024-07-03T04:54:44+00:00" + "time": "2025-05-21T11:55:47+00:00" }, { "name": "sebastian/exporter", @@ -15257,16 +15279,16 @@ }, { "name": "symfony/http-client", - "version": "v7.2.4", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6" + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", - "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", + "url": "https://api.github.com/repos/symfony/http-client/zipball/57e4fb86314015a695a750ace358d07a7e37b8a9", + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9", "shasum": "" }, "require": { @@ -15332,7 +15354,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.4" + "source": "https://github.com/symfony/http-client/tree/v7.3.0" }, "funding": [ { @@ -15348,20 +15370,20 @@ "type": "tidelift" } ], - "time": "2025-02-13T10:27:23+00:00" + "time": "2025-05-02T08:23:16+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.5.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" + "reference": "75d7043853a42837e68111812f4d964b01e5101c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", + "reference": "75d7043853a42837e68111812f4d964b01e5101c", "shasum": "" }, "require": { @@ -15374,7 +15396,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -15410,7 +15432,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.2" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.0" }, "funding": [ { @@ -15426,27 +15448,27 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:49:48+00:00" + "time": "2025-04-29T11:18:49+00:00" }, { "name": "ta-tikoma/phpunit-architecture-test", - "version": "0.8.4", + "version": "0.8.5", "source": { "type": "git", "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git", - "reference": "89f0dea1cb0f0d5744d3ec1764a286af5e006636" + "reference": "cf6fb197b676ba716837c886baca842e4db29005" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/89f0dea1cb0f0d5744d3ec1764a286af5e006636", - "reference": "89f0dea1cb0f0d5744d3ec1764a286af5e006636", + "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/cf6fb197b676ba716837c886baca842e4db29005", + "reference": "cf6fb197b676ba716837c886baca842e4db29005", "shasum": "" }, "require": { "nikic/php-parser": "^4.18.0 || ^5.0.0", "php": "^8.1.0", "phpdocumentor/reflection-docblock": "^5.3.0", - "phpunit/phpunit": "^10.5.5 || ^11.0.0", + "phpunit/phpunit": "^10.5.5 || ^11.0.0 || ^12.0.0", "symfony/finder": "^6.4.0 || ^7.0.0" }, "require-dev": { @@ -15483,9 +15505,9 @@ ], "support": { "issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues", - "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.4" + "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.5" }, - "time": "2024-01-05T14:10:56+00:00" + "time": "2025-04-20T20:23:40+00:00" }, { "name": "theseer/tokenizer", diff --git a/config/constants.php b/config/constants.php index be20736c0..78d77d78e 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,9 +2,9 @@ return [ 'coolify' => [ - 'version' => '4.0.0-beta.418', + 'version' => '4.0.0-beta.420', 'helper_version' => '1.0.8', - 'realtime_version' => '1.0.8', + 'realtime_version' => '1.0.9', 'self_hosted' => env('SELF_HOSTED', true), 'autoupdate' => env('AUTOUPDATE'), 'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'), diff --git a/database/migrations/2025_05_26_100258_add_server_patch_notifications.php b/database/migrations/2025_05_26_100258_add_server_patch_notifications.php new file mode 100644 index 000000000..6d6611173 --- /dev/null +++ b/database/migrations/2025_05_26_100258_add_server_patch_notifications.php @@ -0,0 +1,74 @@ +boolean('server_patch_email_notifications')->default(true); + }); + + // Add server patch notification fields to discord notification settings + Schema::table('discord_notification_settings', function (Blueprint $table) { + $table->boolean('server_patch_discord_notifications')->default(true); + }); + + // Add server patch notification fields to telegram notification settings + Schema::table('telegram_notification_settings', function (Blueprint $table) { + $table->boolean('server_patch_telegram_notifications')->default(true); + $table->string('telegram_notifications_server_patch_thread_id')->nullable(); + }); + + // Add server patch notification fields to slack notification settings + Schema::table('slack_notification_settings', function (Blueprint $table) { + $table->boolean('server_patch_slack_notifications')->default(true); + }); + + // Add server patch notification fields to pushover notification settings + Schema::table('pushover_notification_settings', function (Blueprint $table) { + $table->boolean('server_patch_pushover_notifications')->default(true); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // Remove server patch notification fields from email notification settings + Schema::table('email_notification_settings', function (Blueprint $table) { + $table->dropColumn('server_patch_email_notifications'); + }); + + // Remove server patch notification fields from discord notification settings + Schema::table('discord_notification_settings', function (Blueprint $table) { + $table->dropColumn('server_patch_discord_notifications'); + }); + + // Remove server patch notification fields from telegram notification settings + Schema::table('telegram_notification_settings', function (Blueprint $table) { + $table->dropColumn([ + 'server_patch_telegram_notifications', + 'telegram_notifications_server_patch_thread_id', + ]); + }); + + // Remove server patch notification fields from slack notification settings + Schema::table('slack_notification_settings', function (Blueprint $table) { + $table->dropColumn('server_patch_slack_notifications'); + }); + + // Remove server patch notification fields from pushover notification settings + Schema::table('pushover_notification_settings', function (Blueprint $table) { + $table->dropColumn('server_patch_pushover_notifications'); + }); + } +}; diff --git a/database/migrations/2025_05_29_100258_add_terminal_enabled_to_server_settings.php b/database/migrations/2025_05_29_100258_add_terminal_enabled_to_server_settings.php new file mode 100644 index 000000000..45db2f28b --- /dev/null +++ b/database/migrations/2025_05_29_100258_add_terminal_enabled_to_server_settings.php @@ -0,0 +1,28 @@ +boolean('is_terminal_enabled')->default(true); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('server_settings', function (Blueprint $table) { + $table->dropColumn('is_terminal_enabled'); + }); + } +}; diff --git a/database/migrations/2025_06_06_073345_create_server_previous_ip.php b/database/migrations/2025_06_06_073345_create_server_previous_ip.php new file mode 100644 index 000000000..7f756c184 --- /dev/null +++ b/database/migrations/2025_06_06_073345_create_server_previous_ip.php @@ -0,0 +1,28 @@ +string('ip_previous')->nullable()->after('ip'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('servers', function (Blueprint $table) { + $table->dropColumn('ip_previous'); + }); + } +}; diff --git a/database/migrations/2025_06_16_123532_change_sentinel_on_by_default.php b/database/migrations/2025_06_16_123532_change_sentinel_on_by_default.php new file mode 100644 index 000000000..f4c6d4038 --- /dev/null +++ b/database/migrations/2025_06_16_123532_change_sentinel_on_by_default.php @@ -0,0 +1,28 @@ +boolean('is_sentinel_enabled')->default(true)->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('server_settings', function (Blueprint $table) { + $table->boolean('is_sentinel_enabled')->default(false)->change(); + }); + } +}; diff --git a/database/seeders/ProductionSeeder.php b/database/seeders/ProductionSeeder.php index 058d4c8e4..adada458e 100644 --- a/database/seeders/ProductionSeeder.php +++ b/database/seeders/ProductionSeeder.php @@ -2,9 +2,12 @@ namespace Database\Seeders; +use App\Actions\Proxy\CheckProxy; +use App\Actions\Proxy\StartProxy; use App\Data\ServerMetadata; use App\Enums\ProxyStatus; use App\Enums\ProxyTypes; +use App\Jobs\CheckAndStartSentinelJob; use App\Models\GithubApp; use App\Models\GitlabApp; use App\Models\InstanceSettings; @@ -115,11 +118,20 @@ class ProductionSeeder extends Seeder $server->settings->is_reachable = true; $server->settings->is_usable = true; $server->settings->save(); + StartProxy::dispatch($server); + CheckAndStartSentinelJob::dispatch($server); } else { $server = Server::find(0); $server->settings->is_reachable = true; $server->settings->is_usable = true; $server->settings->save(); + $shouldStart = CheckProxy::run($server); + if ($shouldStart) { + StartProxy::dispatch($server); + } + if ($server->isSentinelEnabled()) { + CheckAndStartSentinelJob::dispatch($server); + } } if (StandaloneDocker::find(0) == null) { diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 965fca276..57f062202 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -61,7 +61,7 @@ services: retries: 10 timeout: 2s soketi: - image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.8' + image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.9' ports: - "${SOKETI_PORT:-6001}:6001" - "6002:6002" diff --git a/docker/coolify-realtime/Dockerfile b/docker/coolify-realtime/Dockerfile index 3a53da490..7a24200d6 100644 --- a/docker/coolify-realtime/Dockerfile +++ b/docker/coolify-realtime/Dockerfile @@ -2,7 +2,7 @@ # https://github.com/soketi/soketi/releases ARG SOKETI_VERSION=1.6-16-alpine # https://github.com/cloudflare/cloudflared/releases -ARG CLOUDFLARED_VERSION=2025.2.0 +ARG CLOUDFLARED_VERSION=2025.5.0 FROM quay.io/soketi/soketi:${SOKETI_VERSION} diff --git a/docker/coolify-realtime/terminal-server.js b/docker/coolify-realtime/terminal-server.js index 61dd29453..2607d2aec 100755 --- a/docker/coolify-realtime/terminal-server.js +++ b/docker/coolify-realtime/terminal-server.js @@ -265,11 +265,57 @@ function extractTimeout(commandString) { function extractSshArgs(commandString) { const sshCommandMatch = commandString.match(/ssh (.+?) 'bash -se'/); - let sshArgs = sshCommandMatch ? sshCommandMatch[1].split(' ') : []; + if (!sshCommandMatch) return []; + + const argsString = sshCommandMatch[1]; + let sshArgs = []; + + // Parse shell arguments respecting quotes + let current = ''; + let inQuotes = false; + let quoteChar = ''; + let i = 0; + + while (i < argsString.length) { + const char = argsString[i]; + const nextChar = argsString[i + 1]; + + if (!inQuotes && (char === '"' || char === "'")) { + // Starting a quoted section + inQuotes = true; + quoteChar = char; + current += char; + } else if (inQuotes && char === quoteChar) { + // Ending a quoted section + inQuotes = false; + current += char; + quoteChar = ''; + } else if (!inQuotes && char === ' ') { + // Space outside quotes - end of argument + if (current.trim()) { + sshArgs.push(current.trim()); + current = ''; + } + } else { + // Regular character + current += char; + } + i++; + } + + // Add final argument if exists + if (current.trim()) { + sshArgs.push(current.trim()); + } + + // Replace RequestTTY=no with RequestTTY=yes sshArgs = sshArgs.map(arg => arg === 'RequestTTY=no' ? 'RequestTTY=yes' : arg); - if (!sshArgs.includes('RequestTTY=yes')) { + + // Add RequestTTY=yes if not present + if (!sshArgs.includes('RequestTTY=yes') && !sshArgs.some(arg => arg.includes('RequestTTY='))) { sshArgs.push('-o', 'RequestTTY=yes'); } + return sshArgs; } diff --git a/openapi.json b/openapi.json index 40f663e51..791828aed 100644 --- a/openapi.json +++ b/openapi.json @@ -353,6 +353,10 @@ "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" + }, + "connect_to_docker_network": { + "type": "boolean", + "description": "The flag to connect the service to the predefined Docker network." } }, "type": "object" @@ -701,6 +705,10 @@ "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" + }, + "connect_to_docker_network": { + "type": "boolean", + "description": "The flag to connect the service to the predefined Docker network." } }, "type": "object" @@ -1049,6 +1057,10 @@ "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" + }, + "connect_to_docker_network": { + "type": "boolean", + "description": "The flag to connect the service to the predefined Docker network." } }, "type": "object" @@ -1326,6 +1338,10 @@ "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" + }, + "connect_to_docker_network": { + "type": "boolean", + "description": "The flag to connect the service to the predefined Docker network." } }, "type": "object" @@ -1586,6 +1602,10 @@ "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" + }, + "connect_to_docker_network": { + "type": "boolean", + "description": "The flag to connect the service to the predefined Docker network." } }, "type": "object" @@ -1685,6 +1705,10 @@ "type": "boolean", "nullable": true, "description": "Use build server." + }, + "connect_to_docker_network": { + "type": "boolean", + "description": "The flag to connect the service to the predefined Docker network." } }, "type": "object" @@ -2147,6 +2171,10 @@ "type": "boolean", "nullable": true, "description": "Use build server." + }, + "connect_to_docker_network": { + "type": "boolean", + "description": "The flag to connect the service to the predefined Docker network." } }, "type": "object" @@ -7017,6 +7045,15 @@ "type": "string", "format": "uuid" } + }, + { + "name": "latest", + "in": "query", + "description": "Pull latest images.", + "schema": { + "type": "boolean", + "default": false + } } ], "responses": { diff --git a/openapi.yaml b/openapi.yaml index c5113d9f7..3f2fa1c59 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -259,6 +259,9 @@ paths: type: string nullable: true description: 'Password for HTTP Basic Authentication' + connect_to_docker_network: + type: boolean + description: 'The flag to connect the service to the predefined Docker network.' type: object responses: '201': @@ -509,6 +512,9 @@ paths: type: string nullable: true description: 'Password for HTTP Basic Authentication' + connect_to_docker_network: + type: boolean + description: 'The flag to connect the service to the predefined Docker network.' type: object responses: '201': @@ -759,6 +765,9 @@ paths: type: string nullable: true description: 'Password for HTTP Basic Authentication' + connect_to_docker_network: + type: boolean + description: 'The flag to connect the service to the predefined Docker network.' type: object responses: '201': @@ -956,6 +965,9 @@ paths: type: string nullable: true description: 'Password for HTTP Basic Authentication' + connect_to_docker_network: + type: boolean + description: 'The flag to connect the service to the predefined Docker network.' type: object responses: '201': @@ -1144,6 +1156,9 @@ paths: type: string nullable: true description: 'Password for HTTP Basic Authentication' + connect_to_docker_network: + type: boolean + description: 'The flag to connect the service to the predefined Docker network.' type: object responses: '201': @@ -1212,6 +1227,9 @@ paths: type: boolean nullable: true description: 'Use build server.' + connect_to_docker_network: + type: boolean + description: 'The flag to connect the service to the predefined Docker network.' type: object responses: '201': @@ -1539,6 +1557,9 @@ paths: type: boolean nullable: true description: 'Use build server.' + connect_to_docker_network: + type: boolean + description: 'The flag to connect the service to the predefined Docker network.' type: object responses: '200': @@ -4660,6 +4681,13 @@ paths: schema: type: string format: uuid + - + name: latest + in: query + description: 'Pull latest images.' + schema: + type: boolean + default: false responses: '200': description: 'Restart service.' diff --git a/other/nightly/docker-compose.prod.yml b/other/nightly/docker-compose.prod.yml index fa30677ad..57f062202 100644 --- a/other/nightly/docker-compose.prod.yml +++ b/other/nightly/docker-compose.prod.yml @@ -61,7 +61,7 @@ services: retries: 10 timeout: 2s soketi: - image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.8' + image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.9' ports: - "${SOKETI_PORT:-6001}:6001" - "6002:6002" diff --git a/other/nightly/install.sh b/other/nightly/install.sh index f0fcdfb4e..e9f54952a 100755 --- a/other/nightly/install.sh +++ b/other/nightly/install.sh @@ -20,7 +20,7 @@ DATE=$(date +"%Y%m%d-%H%M%S") OS_TYPE=$(grep -w "ID" /etc/os-release | cut -d "=" -f 2 | tr -d '"') ENV_FILE="/data/coolify/source/.env" -VERSION="20" +VERSION="21" DOCKER_VERSION="27.0" # TODO: Ask for a user CURRENT_USER=$USER @@ -438,7 +438,7 @@ fi if [ -x "$(command -v snap)" ]; then SNAP_DOCKER_INSTALLED=$(snap list docker >/dev/null 2>&1 && echo "true" || echo "false") if [ "$SNAP_DOCKER_INSTALLED" = "true" ]; then - echo " - Docker is installed via snap." + echo "Docker is installed via snap." echo " Please note that Coolify does not support Docker installed via snap." echo " Please remove Docker with snap (snap remove docker) and reexecute this script." exit 1 @@ -446,16 +446,46 @@ if [ -x "$(command -v snap)" ]; then fi install_docker() { + set +e curl -s https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh 2>&1 || true if ! [ -x "$(command -v docker)" ]; then curl -s https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} 2>&1 if ! [ -x "$(command -v docker)" ]; then - echo " - Docker installation failed." - echo " Maybe your OS is not supported?" - echo " - Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 + echo "Automated Docker installation failed. Trying manual installation." + install_docker_manually fi fi + set -e +} + +install_docker_manually() { + case "$OS_TYPE" in + "ubuntu" | "debian" | "raspbian") + apt-get update + apt-get install -y ca-certificates curl + install -m 0755 -d /etc/apt/keyrings + curl -fsSL https://download.docker.com/linux/$OS_TYPE/gpg -o /etc/apt/keyrings/docker.asc + chmod a+r /etc/apt/keyrings/docker.asc + + # Add the repository to Apt sources + echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/$OS_TYPE \ + $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | + tee /etc/apt/sources.list.d/docker.list + apt-get update + apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + ;; + *) + exit 1 + ;; + esac + if ! [ -x "$(command -v docker)" ]; then + echo "Docker installation failed." + echo " Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + else + echo "Docker installed successfully." + fi } echo -e "3. Check Docker Installation. " if ! [ -x "$(command -v docker)" ]; then @@ -522,34 +552,18 @@ if ! [ -x "$(command -v docker)" ]; then systemctl enable docker >/dev/null 2>&1 ;; "ubuntu" | "debian" | "raspbian") - if [ "$OS_TYPE" = "ubuntu" ] && [ "$OS_VERSION" = "24.10" ]; then - echo " - Installing Docker for Ubuntu 24.10..." - apt-get update >/dev/null - apt-get install -y ca-certificates curl >/dev/null - install -m 0755 -d /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc - chmod a+r /etc/apt/keyrings/docker.asc - - # Add the repository to Apt sources - echo \ - "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ - $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | - tee /etc/apt/sources.list.d/docker.list >/dev/null - apt-get update >/dev/null - apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin >/dev/null - - if ! [ -x "$(command -v docker)" ]; then - echo " - Docker installation failed." - echo " Please visit https://docs.docker.com/engine/install/ubuntu/ and install Docker manually to continue." - exit 1 - fi - echo " - Docker installed successfully for Ubuntu 24.10." - else - install_docker + install_docker + if ! [ -x "$(command -v docker)" ]; then + echo " - Automated Docker installation failed. Trying manual installation." + install_docker_manually fi ;; *) install_docker + if ! [ -x "$(command -v docker)" ]; then + echo " - Automated Docker installation failed. Trying manual installation." + install_docker_manually + fi ;; esac echo " - Docker installed successfully." @@ -787,6 +801,8 @@ set -e if [ "$IS_COOLIFY_VOLUME_EXISTS" -eq 0 ]; then echo " - Generating SSH key." + test -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal && rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal + test -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub && rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub ssh-keygen -t ed25519 -a 100 -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal -q -N "" -C coolify chown 9999 /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal sed -i "/coolify/d" ~/.ssh/authorized_keys diff --git a/other/nightly/versions.json b/other/nightly/versions.json index 7cd46baab..9fde1e53b 100644 --- a/other/nightly/versions.json +++ b/other/nightly/versions.json @@ -1,16 +1,16 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.417" + "version": "4.0.0-beta.420" }, "nightly": { - "version": "4.0.0-beta.418" + "version": "4.0.0-beta.421" }, "helper": { "version": "1.0.8" }, "realtime": { - "version": "1.0.8" + "version": "1.0.9" }, "sentinel": { "version": "0.0.15" diff --git a/package-lock.json b/package-lock.json index 7996a3653..d86caea87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,22 +8,22 @@ "dependencies": { "@tailwindcss/forms": "0.5.10", "@tailwindcss/typography": "0.5.16", - "@xterm/addon-fit": "^0.10.0", - "@xterm/xterm": "^5.5.0", - "ioredis": "5.6.0" + "@xterm/addon-fit": "0.10.0", + "@xterm/xterm": "5.5.0", + "ioredis": "5.6.1" }, "devDependencies": { - "@tailwindcss/postcss": "^4.1.4", - "@vitejs/plugin-vue": "5.2.3", - "axios": "1.8.4", - "laravel-echo": "2.0.2", - "laravel-vite-plugin": "^1.2.0", - "postcss": "8.5.3", + "@tailwindcss/postcss": "4.1.10", + "@vitejs/plugin-vue": "5.2.4", + "axios": "1.9.0", + "laravel-echo": "2.1.5", + "laravel-vite-plugin": "1.3.0", + "postcss": "8.5.5", "pusher-js": "8.4.0", - "tailwind-scrollbar": "^4.0.2", - "tailwindcss": "^4.1.4", - "vite": "^6.2.6", - "vue": "3.5.13" + "tailwind-scrollbar": "4.0.2", + "tailwindcss": "4.1.10", + "vite": "6.3.5", + "vue": "3.5.16" } }, "node_modules/@alloc/quick-lru": { @@ -74,13 +74,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", - "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.27.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -90,9 +90,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -880,6 +880,14 @@ "win32" ] }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/@tailwindcss/forms": { "version": "0.5.10", "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz", @@ -893,25 +901,25 @@ } }, "node_modules/@tailwindcss/node": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.6.tgz", - "integrity": "sha512-ed6zQbgmKsjsVvodAS1q1Ld2BolEuxJOSyyNc+vhkjdmfNUDCmQnlXBfQkHrlzNmslxHsQU/bFmzcEbv4xXsLg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.10.tgz", + "integrity": "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", - "lightningcss": "1.29.2", + "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.6" + "tailwindcss": "4.1.10" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.6.tgz", - "integrity": "sha512-0bpEBQiGx+227fW4G0fLQ8vuvyy5rsB1YIYNapTq3aRsJ9taF3f5cCaovDjN5pUGKKzcpMrZst/mhNaKAPOHOA==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.10.tgz", + "integrity": "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -923,24 +931,24 @@ "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.6", - "@tailwindcss/oxide-darwin-arm64": "4.1.6", - "@tailwindcss/oxide-darwin-x64": "4.1.6", - "@tailwindcss/oxide-freebsd-x64": "4.1.6", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.6", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.6", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.6", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.6", - "@tailwindcss/oxide-linux-x64-musl": "4.1.6", - "@tailwindcss/oxide-wasm32-wasi": "4.1.6", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.6", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.6" + "@tailwindcss/oxide-android-arm64": "4.1.10", + "@tailwindcss/oxide-darwin-arm64": "4.1.10", + "@tailwindcss/oxide-darwin-x64": "4.1.10", + "@tailwindcss/oxide-freebsd-x64": "4.1.10", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.10", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.10", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.10", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.10", + "@tailwindcss/oxide-linux-x64-musl": "4.1.10", + "@tailwindcss/oxide-wasm32-wasi": "4.1.10", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.10", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.10" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.6.tgz", - "integrity": "sha512-VHwwPiwXtdIvOvqT/0/FLH/pizTVu78FOnI9jQo64kSAikFSZT7K4pjyzoDpSMaveJTGyAKvDjuhxJxKfmvjiQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.10.tgz", + "integrity": "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==", "cpu": [ "arm64" ], @@ -955,9 +963,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.6.tgz", - "integrity": "sha512-weINOCcqv1HVBIGptNrk7c6lWgSFFiQMcCpKM4tnVi5x8OY2v1FrV76jwLukfT6pL1hyajc06tyVmZFYXoxvhQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.10.tgz", + "integrity": "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==", "cpu": [ "arm64" ], @@ -972,9 +980,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.6.tgz", - "integrity": "sha512-3FzekhHG0ww1zQjQ1lPoq0wPrAIVXAbUkWdWM8u5BnYFZgb9ja5ejBqyTgjpo5mfy0hFOoMnMuVDI+7CXhXZaQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.10.tgz", + "integrity": "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==", "cpu": [ "x64" ], @@ -989,9 +997,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.6.tgz", - "integrity": "sha512-4m5F5lpkBZhVQJq53oe5XgJ+aFYWdrgkMwViHjRsES3KEu2m1udR21B1I77RUqie0ZYNscFzY1v9aDssMBZ/1w==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.10.tgz", + "integrity": "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==", "cpu": [ "x64" ], @@ -1006,9 +1014,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.6.tgz", - "integrity": "sha512-qU0rHnA9P/ZoaDKouU1oGPxPWzDKtIfX7eOGi5jOWJKdxieUJdVV+CxWZOpDWlYTd4N3sFQvcnVLJWJ1cLP5TA==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.10.tgz", + "integrity": "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==", "cpu": [ "arm" ], @@ -1023,9 +1031,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.6.tgz", - "integrity": "sha512-jXy3TSTrbfgyd3UxPQeXC3wm8DAgmigzar99Km9Sf6L2OFfn/k+u3VqmpgHQw5QNfCpPe43em6Q7V76Wx7ogIQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.10.tgz", + "integrity": "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==", "cpu": [ "arm64" ], @@ -1040,9 +1048,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.6.tgz", - "integrity": "sha512-8kjivE5xW0qAQ9HX9reVFmZj3t+VmljDLVRJpVBEoTR+3bKMnvC7iLcoSGNIUJGOZy1mLVq7x/gerVg0T+IsYw==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.10.tgz", + "integrity": "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==", "cpu": [ "arm64" ], @@ -1057,9 +1065,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.6.tgz", - "integrity": "sha512-A4spQhwnWVpjWDLXnOW9PSinO2PTKJQNRmL/aIl2U/O+RARls8doDfs6R41+DAXK0ccacvRyDpR46aVQJJCoCg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.10.tgz", + "integrity": "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==", "cpu": [ "x64" ], @@ -1074,9 +1082,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.6.tgz", - "integrity": "sha512-YRee+6ZqdzgiQAHVSLfl3RYmqeeaWVCk796MhXhLQu2kJu2COHBkqlqsqKYx3p8Hmk5pGCQd2jTAoMWWFeyG2A==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.10.tgz", + "integrity": "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==", "cpu": [ "x64" ], @@ -1091,9 +1099,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.6.tgz", - "integrity": "sha512-qAp4ooTYrBQ5pk5jgg54/U1rCJ/9FLYOkkQ/nTE+bVMseMfB6O7J8zb19YTpWuu4UdfRf5zzOrNKfl6T64MNrQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.10.tgz", + "integrity": "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -1112,7 +1120,7 @@ "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", - "@napi-rs/wasm-runtime": "^0.2.9", + "@napi-rs/wasm-runtime": "^0.2.10", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, @@ -1121,9 +1129,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.6.tgz", - "integrity": "sha512-nqpDWk0Xr8ELO/nfRUDjk1pc9wDJ3ObeDdNMHLaymc4PJBWj11gdPCWZFKSK2AVKjJQC7J2EfmSmf47GN7OuLg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.10.tgz", + "integrity": "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==", "cpu": [ "arm64" ], @@ -1138,9 +1146,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.6.tgz", - "integrity": "sha512-5k9xF33xkfKpo9wCvYcegQ21VwIBU1/qEbYlVukfEIyQbEA47uK8AAwS7NVjNE3vHzcmxMYwd0l6L4pPjjm1rQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.10.tgz", + "integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==", "cpu": [ "x64" ], @@ -1155,17 +1163,17 @@ } }, "node_modules/@tailwindcss/postcss": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.6.tgz", - "integrity": "sha512-ELq+gDMBuRXPJlpE3PEen+1MhnHAQQrh2zF0dI1NXOlEWfr2qWf2CQdr5jl9yANv8RErQaQ2l6nIFO9OSCVq/g==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.10.tgz", + "integrity": "sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ==", "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.6", - "@tailwindcss/oxide": "4.1.6", + "@tailwindcss/node": "4.1.10", + "@tailwindcss/oxide": "4.1.10", "postcss": "^8.4.41", - "tailwindcss": "4.1.6" + "tailwindcss": "4.1.10" } }, "node_modules/@tailwindcss/typography": { @@ -1198,9 +1206,9 @@ "license": "MIT" }, "node_modules/@vitejs/plugin-vue": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.3.tgz", - "integrity": "sha512-IYSLEQj4LgZZuoVpdSUCw3dIynTWQgPlaRP6iAvMle4My0HdYwr5g5wQAfwOeHQBmYwEkqF70nRpSilr6PoUDg==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", "dev": true, "license": "MIT", "engines": { @@ -1212,111 +1220,111 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", - "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.16.tgz", + "integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.13", + "@babel/parser": "^7.27.2", + "@vue/shared": "3.5.16", "entities": "^4.5.0", "estree-walker": "^2.0.2", - "source-map-js": "^1.2.0" + "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", - "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz", + "integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.13", - "@vue/shared": "3.5.13" + "@vue/compiler-core": "3.5.16", + "@vue/shared": "3.5.16" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", - "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz", + "integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/compiler-core": "3.5.13", - "@vue/compiler-dom": "3.5.13", - "@vue/compiler-ssr": "3.5.13", - "@vue/shared": "3.5.13", + "@babel/parser": "^7.27.2", + "@vue/compiler-core": "3.5.16", + "@vue/compiler-dom": "3.5.16", + "@vue/compiler-ssr": "3.5.16", + "@vue/shared": "3.5.16", "estree-walker": "^2.0.2", - "magic-string": "^0.30.11", - "postcss": "^8.4.48", - "source-map-js": "^1.2.0" + "magic-string": "^0.30.17", + "postcss": "^8.5.3", + "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", - "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz", + "integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.13", - "@vue/shared": "3.5.13" + "@vue/compiler-dom": "3.5.16", + "@vue/shared": "3.5.16" } }, "node_modules/@vue/reactivity": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz", - "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.16.tgz", + "integrity": "sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA==", "dev": true, "license": "MIT", "dependencies": { - "@vue/shared": "3.5.13" + "@vue/shared": "3.5.16" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz", - "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.16.tgz", + "integrity": "sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ==", "dev": true, "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.13", - "@vue/shared": "3.5.13" + "@vue/reactivity": "3.5.16", + "@vue/shared": "3.5.16" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz", - "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.16.tgz", + "integrity": "sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww==", "dev": true, "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.13", - "@vue/runtime-core": "3.5.13", - "@vue/shared": "3.5.13", + "@vue/reactivity": "3.5.16", + "@vue/runtime-core": "3.5.16", + "@vue/shared": "3.5.16", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz", - "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.16.tgz", + "integrity": "sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.13", - "@vue/shared": "3.5.13" + "@vue/compiler-ssr": "3.5.16", + "@vue/shared": "3.5.16" }, "peerDependencies": { - "vue": "3.5.13" + "vue": "3.5.16" } }, "node_modules/@vue/shared": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", - "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.16.tgz", + "integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==", "dev": true, "license": "MIT" }, @@ -1343,9 +1351,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "dev": true, "license": "MIT", "dependencies": { @@ -1490,6 +1498,51 @@ "node": ">= 0.4" } }, + "node_modules/engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.18.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", @@ -1793,9 +1846,9 @@ } }, "node_modules/ioredis": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.0.tgz", - "integrity": "sha512-tBZlIIWbndeWBWCXWZiqtOF/yxf6yZX3tAlTJ7nfo5jhd6dctNxF7QnYlZLZ1a0o0pDoen7CgZqO+zjNaFbJAg==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz", + "integrity": "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==", "license": "MIT", "dependencies": { "@ioredis/commands": "^1.1.1", @@ -1827,19 +1880,23 @@ } }, "node_modules/laravel-echo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-2.0.2.tgz", - "integrity": "sha512-Ciai6hA7r35MFqNRb8G034cvm9WiveSTFQQKRGJhWtZGbng7C8BBa5QvqDxk/Mw5GeJ+q19jrEwQhf7r1b1lcg==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-2.1.5.tgz", + "integrity": "sha512-xIlV7AYjfIXv9KGiDa3qqc7JOEJUqNl+6Nx/I6bdxnSAMqnNZT5Nc1rwjOYfoYEI6030QkKF8BhPuU6Roakebw==", "dev": true, "license": "MIT", "engines": { "node": ">=20" + }, + "peerDependencies": { + "pusher-js": "*", + "socket.io-client": "*" } }, "node_modules/laravel-vite-plugin": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.2.0.tgz", - "integrity": "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.3.0.tgz", + "integrity": "sha512-P5qyG56YbYxM8OuYmK2OkhcKe0AksNVJUjq9LUZ5tOekU9fBn9LujYyctI4t9XoLjuMvHJXXpCoPntY1oKltuA==", "dev": true, "license": "MIT", "dependencies": { @@ -1857,9 +1914,9 @@ } }, "node_modules/lightningcss": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz", - "integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -1873,22 +1930,22 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-darwin-arm64": "1.29.2", - "lightningcss-darwin-x64": "1.29.2", - "lightningcss-freebsd-x64": "1.29.2", - "lightningcss-linux-arm-gnueabihf": "1.29.2", - "lightningcss-linux-arm64-gnu": "1.29.2", - "lightningcss-linux-arm64-musl": "1.29.2", - "lightningcss-linux-x64-gnu": "1.29.2", - "lightningcss-linux-x64-musl": "1.29.2", - "lightningcss-win32-arm64-msvc": "1.29.2", - "lightningcss-win32-x64-msvc": "1.29.2" + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz", - "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", "cpu": [ "arm64" ], @@ -1907,9 +1964,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz", - "integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", "cpu": [ "x64" ], @@ -1928,9 +1985,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz", - "integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", "cpu": [ "x64" ], @@ -1949,9 +2006,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz", - "integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", "cpu": [ "arm" ], @@ -1970,9 +2027,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz", - "integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", "cpu": [ "arm64" ], @@ -1991,9 +2048,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz", - "integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", "cpu": [ "arm64" ], @@ -2012,9 +2069,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz", - "integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", "cpu": [ "x64" ], @@ -2033,9 +2090,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz", - "integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", "cpu": [ "x64" ], @@ -2054,9 +2111,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz", - "integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", "cpu": [ "arm64" ], @@ -2075,9 +2132,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz", - "integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", "cpu": [ "x64" ], @@ -2262,9 +2319,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz", + "integrity": "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==", "dev": true, "funding": [ { @@ -2282,7 +2339,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -2406,6 +2463,76 @@ "fsevents": "~2.3.2" } }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -2439,15 +2566,15 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.6.tgz", - "integrity": "sha512-j0cGLTreM6u4OWzBeLBpycK0WIh8w7kSwcUsQZoGLHZ7xDTdM69lN64AgoIEEwFi0tnhs4wSykUa5YWxAzgFYg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz", + "integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==", "license": "MIT" }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true, "license": "MIT", "engines": { @@ -2602,17 +2729,17 @@ } }, "node_modules/vue": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz", - "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.16.tgz", + "integrity": "sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.13", - "@vue/compiler-sfc": "3.5.13", - "@vue/runtime-dom": "3.5.13", - "@vue/server-renderer": "3.5.13", - "@vue/shared": "3.5.13" + "@vue/compiler-dom": "3.5.16", + "@vue/compiler-sfc": "3.5.16", + "@vue/runtime-dom": "3.5.16", + "@vue/server-renderer": "3.5.16", + "@vue/shared": "3.5.16" }, "peerDependencies": { "typescript": "*" @@ -2623,6 +2750,39 @@ } } }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/yallist": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", diff --git a/package.json b/package.json index 7e1a85c70..10ec71415 100644 --- a/package.json +++ b/package.json @@ -7,23 +7,23 @@ "build": "vite build" }, "devDependencies": { - "@tailwindcss/postcss": "^4.1.4", - "@vitejs/plugin-vue": "5.2.3", - "axios": "1.8.4", - "laravel-echo": "2.0.2", - "laravel-vite-plugin": "^1.2.0", - "postcss": "8.5.3", + "@tailwindcss/postcss": "4.1.10", + "@vitejs/plugin-vue": "5.2.4", + "axios": "1.9.0", + "laravel-echo": "2.1.5", + "laravel-vite-plugin": "1.3.0", + "postcss": "8.5.5", "pusher-js": "8.4.0", - "tailwind-scrollbar": "^4.0.2", - "tailwindcss": "^4.1.4", - "vite": "^6.2.6", - "vue": "3.5.13" + "tailwind-scrollbar": "4.0.2", + "tailwindcss": "4.1.10", + "vite": "6.3.5", + "vue": "3.5.16" }, "dependencies": { "@tailwindcss/forms": "0.5.10", "@tailwindcss/typography": "0.5.16", - "@xterm/addon-fit": "^0.10.0", - "@xterm/xterm": "^5.5.0", - "ioredis": "5.6.0" + "@xterm/addon-fit": "0.10.0", + "@xterm/xterm": "5.5.0", + "ioredis": "5.6.1" } -} +} \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index f1c2be92d..38adfdb6f 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -14,7 +14,7 @@ - + diff --git a/public/svgs/codimd.png b/public/svgs/codimd.png new file mode 100644 index 000000000..eebdcf784 Binary files /dev/null and b/public/svgs/codimd.png differ diff --git a/public/svgs/diun.svg b/public/svgs/diun.svg new file mode 100644 index 000000000..6084a3cf3 --- /dev/null +++ b/public/svgs/diun.svg @@ -0,0 +1,38 @@ + + + + + + + + + + diff --git a/public/svgs/grist.svg b/public/svgs/grist.svg new file mode 100644 index 000000000..82975b768 --- /dev/null +++ b/public/svgs/grist.svg @@ -0,0 +1,18 @@ + + + + grist-logo-icon-transparent + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/svgs/leantime.svg b/public/svgs/leantime.svg new file mode 100755 index 000000000..dac70d778 --- /dev/null +++ b/public/svgs/leantime.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/limesurvey.svg b/public/svgs/limesurvey.svg new file mode 100644 index 000000000..7f84f0f9d --- /dev/null +++ b/public/svgs/limesurvey.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/svgs/marimo.svg b/public/svgs/marimo.svg new file mode 100644 index 000000000..30a70b487 --- /dev/null +++ b/public/svgs/marimo.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/svgs/netbird.png b/public/svgs/netbird.png new file mode 100644 index 000000000..1b2405c07 Binary files /dev/null and b/public/svgs/netbird.png differ diff --git a/public/svgs/observium.webp b/public/svgs/observium.webp new file mode 100644 index 000000000..ff48b3194 Binary files /dev/null and b/public/svgs/observium.webp differ diff --git a/public/svgs/onetimesecret.svg b/public/svgs/onetimesecret.svg new file mode 100644 index 000000000..eff9738dd --- /dev/null +++ b/public/svgs/onetimesecret.svg @@ -0,0 +1,6 @@ + + +Onetime Secret + + + diff --git a/public/svgs/orangehrm.svg b/public/svgs/orangehrm.svg new file mode 100644 index 000000000..b976d57ec --- /dev/null +++ b/public/svgs/orangehrm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/paymenter.svg b/public/svgs/paymenter.svg new file mode 100644 index 000000000..8c063ff9e --- /dev/null +++ b/public/svgs/paymenter.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/svgs/pgbackweb.png b/public/svgs/pgbackweb.png new file mode 100644 index 000000000..6c76c8075 Binary files /dev/null and b/public/svgs/pgbackweb.png differ diff --git a/public/svgs/ryot.svg b/public/svgs/ryot.svg new file mode 100644 index 000000000..410f22171 --- /dev/null +++ b/public/svgs/ryot.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/public/svgs/seafile.svg b/public/svgs/seafile.svg new file mode 100644 index 000000000..e1c516594 --- /dev/null +++ b/public/svgs/seafile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/superset.svg b/public/svgs/superset.svg new file mode 100644 index 000000000..522c3b28a --- /dev/null +++ b/public/svgs/superset.svg @@ -0,0 +1,9 @@ + + + Superset + + + + + + diff --git a/public/svgs/typesense.png b/public/svgs/typesense.png new file mode 100644 index 000000000..ba91aa2da Binary files /dev/null and b/public/svgs/typesense.png differ diff --git a/public/svgs/yamtrack.svg b/public/svgs/yamtrack.svg new file mode 100644 index 000000000..8fd79ded2 --- /dev/null +++ b/public/svgs/yamtrack.svg @@ -0,0 +1,28 @@ + + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + diff --git a/public/vendor/telescope/app-dark.css b/public/vendor/telescope/app-dark.css index 70a872a92..9559860e7 100644 --- a/public/vendor/telescope/app-dark.css +++ b/public/vendor/telescope/app-dark.css @@ -1,10 +1,8 @@ -@charset "UTF-8"; - -.form-control:-moz-focusring{text-shadow:none!important} +@charset "UTF-8";.form-control:-moz-focusring{text-shadow:none!important} /*! * Bootstrap v4.6.2 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#4b5563;--gray-dark:#1f2937;--primary:#4040c8;--secondary:#4b5563;--success:#059669;--info:#2563eb;--warning:#d97706;--danger:#dc2626;--light:#f3f4f6;--dark:#1f2937;--breakpoint-xs:0;--breakpoint-sm:2px;--breakpoint-md:8px;--breakpoint-lg:9px;--breakpoint-xl:10px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);font-family:sans-serif;line-height:1.15}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{background-color:#111827;color:#f3f4f6;font-family:Figtree,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;margin:0;text-align:left}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;margin-top:0}p{margin-bottom:1rem;margin-top:0}abbr[data-original-title],abbr[title]{border-bottom:0;cursor:help;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:600}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{background-color:transparent;color:#818cf8;text-decoration:none}a:hover{color:#a5b4fc;text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{-ms-overflow-style:scrollbar;margin-bottom:1rem;margin-top:0;overflow:auto}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{caption-side:bottom;color:#9ca3af;padding-bottom:.75rem;padding-top:.75rem;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;margin:0}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{border:0;margin:0;min-width:0;padding:0}legend{color:inherit;display:block;font-size:1.5rem;line-height:inherit;margin-bottom:.5rem;max-width:100%;padding:0;white-space:normal;width:100%}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:none;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}output{display:inline-block}summary{cursor:pointer;display:list-item}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.2;margin-bottom:.5rem}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{border:0;border-top:1px solid rgba(0,0,0,.1);margin-bottom:1rem;margin-top:1rem}.small,small{font-size:.875em;font-weight:400}.mark,mark{background-color:#fcf8e3;padding:.2em}.list-inline,.list-unstyled{list-style:none;padding-left:0}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{font-size:1.25rem;margin-bottom:1rem}.blockquote-footer{color:#4b5563;display:block;font-size:.875em}.blockquote-footer:before{content:"โ€”ย "}.img-fluid,.img-thumbnail{height:auto;max-width:100%}.img-thumbnail{background-color:#111827;border:1px solid #d1d5db;border-radius:.25rem;padding:.25rem}.figure{display:inline-block}.figure-img{line-height:1;margin-bottom:.5rem}.figure-caption{color:#4b5563;font-size:90%}code{word-wrap:break-word;color:#e83e8c;font-size:87.5%}a>code{color:inherit}kbd{background-color:#111827;border-radius:.2rem;color:#fff;font-size:87.5%;padding:.2rem .4rem}kbd kbd{font-size:100%;font-weight:600;padding:0}pre{color:#111827;display:block;font-size:87.5%}pre code{color:inherit;font-size:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px;width:100%}@media (min-width:2px){.container,.container-sm{max-width:1137px}}@media (min-width:8px){.container,.container-md,.container-sm{max-width:1138px}}@media (min-width:9px){.container,.container-lg,.container-md,.container-sm{max-width:1139px}}@media (min-width:10px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:flex;flex-wrap:wrap;margin-left:-15px;margin-right:-15px}.no-gutters{margin-left:0;margin-right:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-left:0;padding-right:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{padding-left:15px;padding-right:15px;position:relative;width:100%}.col{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-auto{flex:0 0 auto;max-width:100%;width:auto}.col-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}@media (min-width:2px){.col-sm{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-auto{flex:0 0 auto;max-width:100%;width:auto}.col-sm-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-sm-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-sm-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-sm-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-sm-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}}@media (min-width:8px){.col-md{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-auto{flex:0 0 auto;max-width:100%;width:auto}.col-md-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-md-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-md-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-md-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-md-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}}@media (min-width:9px){.col-lg{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-auto{flex:0 0 auto;max-width:100%;width:auto}.col-lg-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-lg-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-lg-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-lg-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-lg-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}}@media (min-width:10px){.col-xl{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-auto{flex:0 0 auto;max-width:100%;width:auto}.col-xl-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-xl-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-xl-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-xl-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-xl-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}}.table{color:#f3f4f6;margin-bottom:1rem;width:100%}.table td,.table th{border-top:1px solid #374151;padding:.75rem;vertical-align:top}.table thead th{border-bottom:2px solid #374151;vertical-align:bottom}.table tbody+tbody{border-top:2px solid #374151}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #374151}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:#374151;color:#f3f4f6}.table-primary,.table-primary>td,.table-primary>th{background-color:#cacaf0}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#9c9ce2}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#b6b6ea}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#cdcfd3}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#a1a7ae}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#bfc2c7}.table-success,.table-success>td,.table-success>th{background-color:#b9e2d5}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#7dc8b1}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#a7dbca}.table-info,.table-info>td,.table-info>th{background-color:#c2d3f9}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#8eaef5}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abc2f7}.table-warning,.table-warning>td,.table-warning>th{background-color:#f4d9b9}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ebb87e}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#f1cda3}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c2c2}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed8e8e}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1acac}.table-light,.table-light>td,.table-light>th{background-color:#fcfcfc}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#f9f9fa}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#efefef}.table-dark,.table-dark>td,.table-dark>th{background-color:#c0c3c7}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#8b9097}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b3b6bb}.table-active,.table-active>td,.table-active>th{background-color:#374151}.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:#2d3542}.table .thead-dark th{background-color:#1f2937;border-color:#2d3b4f;color:#fff}.table .thead-light th{background-color:#e5e7eb;border-color:#374151;color:#374151}.table-dark{background-color:#1f2937;color:#fff}.table-dark td,.table-dark th,.table-dark thead th{border-color:#2d3b4f}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:hsla(0,0%,100%,.05)}.table-dark.table-hover tbody tr:hover{background-color:hsla(0,0%,100%,.075);color:#fff}@media (max-width:1.98px){.table-responsive-sm{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:7.98px){.table-responsive-md{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-md>.table-bordered{border:0}}@media (max-width:8.98px){.table-responsive-lg{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:9.98px){.table-responsive-xl{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive>.table-bordered{border:0}.form-control{background-clip:padding-box;background-color:#1f2937;border:1px solid #4b5563;border-radius:.25rem;color:#e5e7eb;display:block;font-size:1rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{background-color:#1f2937;border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25);color:#e5e7eb;outline:0}.form-control::-moz-placeholder{color:#4b5563;opacity:1}.form-control::placeholder{color:#4b5563;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e5e7eb;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #e5e7eb}select.form-control:focus::-ms-value{background-color:#1f2937;color:#e5e7eb}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{font-size:inherit;line-height:1.5;margin-bottom:0;padding-bottom:calc(.375rem + 1px);padding-top:calc(.375rem + 1px)}.col-form-label-lg{font-size:1.25rem;line-height:1.5;padding-bottom:calc(.5rem + 1px);padding-top:calc(.5rem + 1px)}.col-form-label-sm{font-size:.875rem;line-height:1.5;padding-bottom:calc(.25rem + 1px);padding-top:calc(.25rem + 1px)}.form-control-plaintext{background-color:transparent;border:solid transparent;border-width:1px 0;color:#f3f4f6;display:block;font-size:1rem;line-height:1.5;margin-bottom:0;padding:.375rem 0;width:100%}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-left:0;padding-right:0}.form-control-sm{border-radius:.2rem;font-size:.875rem;height:calc(1.5em + .5rem + 2px);line-height:1.5;padding:.25rem .5rem}.form-control-lg{border-radius:6px;font-size:1.25rem;height:calc(1.5em + 1rem + 2px);line-height:1.5;padding:.5rem 1rem}select.form-control[multiple],select.form-control[size],textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-left:-5px;margin-right:-5px}.form-row>.col,.form-row>[class*=col-]{padding-left:5px;padding-right:5px}.form-check{display:block;padding-left:1.25rem;position:relative}.form-check-input{margin-left:-1.25rem;margin-top:.3rem;position:absolute}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#9ca3af}.form-check-label{margin-bottom:0}.form-check-inline{align-items:center;display:inline-flex;margin-right:.75rem;padding-left:0}.form-check-inline .form-check-input{margin-left:0;margin-right:.3125rem;margin-top:0;position:static}.valid-feedback{color:#059669;display:none;font-size:.875em;margin-top:.25rem;width:100%}.valid-tooltip{background-color:rgba(5,150,105,.9);border-radius:.25rem;color:#fff;display:none;font-size:.875rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23059669' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#059669;padding-right:calc(1.5em + .75rem)!important}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-valid,.was-validated .custom-select:valid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#1f2937 url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23059669' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#059669;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#059669}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#059669}.custom-control-input.is-valid~.custom-control-label:before,.was-validated .custom-control-input:valid~.custom-control-label:before{border-color:#059669}.custom-control-input.is-valid:checked~.custom-control-label:before,.was-validated .custom-control-input:valid:checked~.custom-control-label:before{background-color:#07c78c;border-color:#07c78c}.custom-control-input.is-valid:focus~.custom-control-label:before,.was-validated .custom-control-input:valid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label:before{border-color:#059669}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#059669}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.invalid-feedback{color:#dc2626;display:none;font-size:.875em;margin-top:.25rem;width:100%}.invalid-tooltip{background-color:rgba(220,38,38,.9);border-radius:.25rem;color:#fff;display:none;font-size:.875rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc2626'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc2626' stroke='none'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#dc2626;padding-right:calc(1.5em + .75rem)!important}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#1f2937 url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc2626'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc2626' stroke='none'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#dc2626;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc2626}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc2626}.custom-control-input.is-invalid~.custom-control-label:before,.was-validated .custom-control-input:invalid~.custom-control-label:before{border-color:#dc2626}.custom-control-input.is-invalid:checked~.custom-control-label:before,.was-validated .custom-control-input:invalid:checked~.custom-control-label:before{background-color:#e35252;border-color:#e35252}.custom-control-input.is-invalid:focus~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label:before{border-color:#dc2626}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc2626}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.form-inline{align-items:center;display:flex;flex-flow:row wrap}.form-inline .form-check{width:100%}@media (min-width:2px){.form-inline label{justify-content:center}.form-inline .form-group,.form-inline label{align-items:center;display:flex;margin-bottom:0}.form-inline .form-group{flex:0 0 auto;flex-flow:row wrap}.form-inline .form-control{display:inline-block;vertical-align:middle;width:auto}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{align-items:center;display:flex;justify-content:center;padding-left:0;width:auto}.form-inline .form-check-input{flex-shrink:0;margin-left:0;margin-right:.25rem;margin-top:0;position:relative}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;color:#f3f4f6;display:inline-block;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#f3f4f6;text-decoration:none}.btn.focus,.btn:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-primary.focus,.btn-primary:focus,.btn-primary:hover{background-color:#3232af;border-color:#3030a5;color:#fff}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(93,93,208,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{background-color:#3030a5;border-color:#2d2d9b;color:#fff}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(93,93,208,.5)}.btn-secondary{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:hover{background-color:#3b424d;border-color:#353c46;color:#fff}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem hsla(213,9%,44%,.5)}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{background-color:#353c46;border-color:#30363f;color:#fff}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem hsla(213,9%,44%,.5)}.btn-success{background-color:#059669;border-color:#059669;color:#fff}.btn-success.focus,.btn-success:focus,.btn-success:hover{background-color:#04714f;border-color:#036546;color:#fff}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(43,166,128,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#059669;border-color:#059669;color:#fff}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{background-color:#036546;border-color:#03583e;color:#fff}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(43,166,128,.5)}.btn-info{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-info.focus,.btn-info:focus,.btn-info:hover{background-color:#1451d6;border-color:#134cca;color:#fff}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(70,122,238,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{background-color:#134cca;border-color:#1248bf;color:#fff}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(70,122,238,.5)}.btn-warning{background-color:#d97706;border-color:#d97706;color:#fff}.btn-warning.focus,.btn-warning:focus,.btn-warning:hover{background-color:#b46305;border-color:#a75c05;color:#fff}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(223,139,43,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#d97706;border-color:#d97706;color:#fff}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{background-color:#a75c05;border-color:#9b5504;color:#fff}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(223,139,43,.5)}.btn-danger{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-danger.focus,.btn-danger:focus,.btn-danger:hover{background-color:#bd1f1f;border-color:#b21d1d;color:#fff}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(225,71,71,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{background-color:#b21d1d;border-color:#a71b1b;color:#fff}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,71,71,.5)}.btn-light{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-light.focus,.btn-light:focus,.btn-light:hover{background-color:#dde0e6;border-color:#d6d9e0;color:#111827}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem hsla(220,7%,83%,.5)}.btn-light.disabled,.btn-light:disabled{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{background-color:#d6d9e0;border-color:#cfd3db;color:#111827}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem hsla(220,7%,83%,.5)}.btn-dark{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-dark.focus,.btn-dark:focus,.btn-dark:hover{background-color:#11171f;border-color:#0d1116;color:#fff}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(65,73,85,.5)}.btn-dark.disabled,.btn-dark:disabled{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{background-color:#0d1116;border-color:#080b0e;color:#fff}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(65,73,85,.5)}.btn-outline-primary{border-color:#4040c8;color:#4040c8}.btn-outline-primary:hover{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{background-color:transparent;color:#4040c8}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.5)}.btn-outline-secondary{border-color:#4b5563;color:#4b5563}.btn-outline-secondary:hover{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(75,85,99,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{background-color:transparent;color:#4b5563}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(75,85,99,.5)}.btn-outline-success{border-color:#059669;color:#059669}.btn-outline-success:hover{background-color:#059669;border-color:#059669;color:#fff}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(5,150,105,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{background-color:transparent;color:#059669}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{background-color:#059669;border-color:#059669;color:#fff}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(5,150,105,.5)}.btn-outline-info{border-color:#2563eb;color:#2563eb}.btn-outline-info:hover{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(37,99,235,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{background-color:transparent;color:#2563eb}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(37,99,235,.5)}.btn-outline-warning{border-color:#d97706;color:#d97706}.btn-outline-warning:hover{background-color:#d97706;border-color:#d97706;color:#fff}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(217,119,6,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{background-color:transparent;color:#d97706}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{background-color:#d97706;border-color:#d97706;color:#fff}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(217,119,6,.5)}.btn-outline-danger{border-color:#dc2626;color:#dc2626}.btn-outline-danger:hover{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,38,38,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{background-color:transparent;color:#dc2626}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,38,38,.5)}.btn-outline-light{border-color:#f3f4f6;color:#f3f4f6}.btn-outline-light:hover{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(243,244,246,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{background-color:transparent;color:#f3f4f6}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(243,244,246,.5)}.btn-outline-dark{border-color:#1f2937;color:#1f2937}.btn-outline-dark:hover{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(31,41,55,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{background-color:transparent;color:#1f2937}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(31,41,55,.5)}.btn-link{color:#818cf8;font-weight:400;text-decoration:none}.btn-link:hover{color:#a5b4fc}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#4b5563;pointer-events:none}.btn-group-lg>.btn,.btn-lg{border-radius:6px;font-size:1.25rem;line-height:1.5;padding:.5rem 1rem}.btn-group-sm>.btn,.btn-sm{border-radius:.2rem;font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;position:relative;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{height:auto;transition:width .35s ease;width:0}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{border-bottom:0;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:.3em solid;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{background-clip:padding-box;background-color:#374151;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;color:#f3f4f6;display:none;float:left;font-size:1rem;left:0;list-style:none;margin:.125rem 0 0;min-width:10rem;padding:.5rem 0;position:absolute;text-align:left;top:100%;z-index:1000}.dropdown-menu-left{left:0;right:auto}.dropdown-menu-right{left:auto;right:0}@media (min-width:2px){.dropdown-menu-sm-left{left:0;right:auto}.dropdown-menu-sm-right{left:auto;right:0}}@media (min-width:8px){.dropdown-menu-md-left{left:0;right:auto}.dropdown-menu-md-right{left:auto;right:0}}@media (min-width:9px){.dropdown-menu-lg-left{left:0;right:auto}.dropdown-menu-lg-right{left:auto;right:0}}@media (min-width:10px){.dropdown-menu-xl-left{left:0;right:auto}.dropdown-menu-xl-right{left:auto;right:0}}.dropup .dropdown-menu{bottom:100%;margin-bottom:.125rem;margin-top:0;top:auto}.dropup .dropdown-toggle:after{border-bottom:.3em solid;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:0;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-menu{left:100%;margin-left:.125rem;margin-top:0;right:auto;top:0}.dropright .dropdown-toggle:after{border-bottom:.3em solid transparent;border-left:.3em solid;border-right:0;border-top:.3em solid transparent;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropright .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-toggle:after{vertical-align:0}.dropleft .dropdown-menu{left:auto;margin-right:.125rem;margin-top:0;right:100%;top:0}.dropleft .dropdown-toggle:after{content:"";display:inline-block;display:none;margin-left:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:before{border-bottom:.3em solid transparent;border-right:.3em solid;border-top:.3em solid transparent;content:"";display:inline-block;margin-right:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:empty:after{margin-left:0}.dropleft .dropdown-toggle:before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{bottom:auto;right:auto}.dropdown-divider{border-top:1px solid #e5e7eb;height:0;margin:.5rem 0;overflow:hidden}.dropdown-item{background-color:transparent;border:0;clear:both;color:#fff;display:block;font-weight:400;padding:.25rem 1.5rem;text-align:inherit;white-space:nowrap;width:100%}.dropdown-item:focus,.dropdown-item:hover{background-color:#e5e7eb;color:#090d15;text-decoration:none}.dropdown-item.active,.dropdown-item:active{background-color:#4040c8;color:#fff;text-decoration:none}.dropdown-item.disabled,.dropdown-item:disabled{background-color:transparent;color:#6b7280;pointer-events:none}.dropdown-menu.show{display:block}.dropdown-header{color:#4b5563;display:block;font-size:.875rem;margin-bottom:0;padding:.5rem 1.5rem;white-space:nowrap}.dropdown-item-text{color:#fff;display:block;padding:.25rem 1.5rem}.btn-group,.btn-group-vertical{display:inline-flex;position:relative;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{flex:1 1 auto;position:relative}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.dropdown-toggle-split{padding-left:.5625rem;padding-right:.5625rem}.dropdown-toggle-split:after,.dropright .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropleft .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-left:.375rem;padding-right:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-left:.75rem;padding-right:.75rem}.btn-group-vertical{align-items:flex-start;flex-direction:column;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-left-radius:0;border-bottom-right-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{clip:rect(0,0,0,0);pointer-events:none;position:absolute}.input-group{align-items:stretch;display:flex;flex-wrap:wrap;position:relative;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{flex:1 1 auto;margin-bottom:0;min-width:0;position:relative;width:1%}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group>.custom-file{align-items:center;display:flex}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label:after{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-bottom-left-radius:0;border-top-left-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label:after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3),.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label:after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.input-group-append,.input-group-prepend{display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{align-items:center;background-color:#e5e7eb;border:1px solid #4b5563;border-radius:.25rem;color:#e5e7eb;display:flex;font-size:1rem;font-weight:400;line-height:1.5;margin-bottom:0;padding:.375rem .75rem;text-align:center;white-space:nowrap}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{border-radius:6px;font-size:1.25rem;line-height:1.5;padding:.5rem 1rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{border-radius:.2rem;font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-bottom-left-radius:0;border-top-left-radius:0}.custom-control{display:block;min-height:1.5rem;padding-left:1.5rem;position:relative;-webkit-print-color-adjust:exact;print-color-adjust:exact;z-index:1}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{height:1.25rem;left:0;opacity:0;position:absolute;width:1rem;z-index:-1}.custom-control-input:checked~.custom-control-label:before{background-color:#4040c8;border-color:#4040c8;color:#fff}.custom-control-input:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(64,64,200,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label:before{border-color:#a3a3e5}.custom-control-input:not(:disabled):active~.custom-control-label:before{background-color:#cbcbf0;border-color:#cbcbf0;color:#fff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#4b5563}.custom-control-input:disabled~.custom-control-label:before,.custom-control-input[disabled]~.custom-control-label:before{background-color:#e5e7eb}.custom-control-label{margin-bottom:0;position:relative;vertical-align:top}.custom-control-label:before{background-color:#1f2937;border:1px solid #6b7280;pointer-events:none}.custom-control-label:after,.custom-control-label:before{content:"";display:block;height:1rem;left:-1.5rem;position:absolute;top:.25rem;width:1rem}.custom-control-label:after{background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label:before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23fff' d='m6.564.75-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:before{background-color:#4040c8;border-color:#4040c8}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-radio .custom-control-label:before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label:before{border-radius:.5rem;left:-2.25rem;pointer-events:all;width:1.75rem}.custom-switch .custom-control-label:after{background-color:#6b7280;border-radius:.5rem;height:calc(1rem - 4px);left:calc(-2.25rem + 2px);top:calc(.25rem + 2px);transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:calc(1rem - 4px)}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label:after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label:after{background-color:#1f2937;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#1f2937 url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat;border:1px solid #4b5563;border-radius:.25rem;color:#e5e7eb;display:inline-block;font-size:1rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem 1.75rem .375rem .75rem;vertical-align:middle;width:100%}.custom-select:focus{border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0}.custom-select:focus::-ms-value{background-color:#1f2937;color:#e5e7eb}.custom-select[multiple],.custom-select[size]:not([size="1"]){background-image:none;height:auto;padding-right:.75rem}.custom-select:disabled{background-color:#e5e7eb;color:#4b5563}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #e5e7eb}.custom-select-sm{font-size:.875rem;height:calc(1.5em + .5rem + 2px);padding-bottom:.25rem;padding-left:.5rem;padding-top:.25rem}.custom-select-lg{font-size:1.25rem;height:calc(1.5em + 1rem + 2px);padding-bottom:.5rem;padding-left:1rem;padding-top:.5rem}.custom-file{display:inline-block;margin-bottom:0}.custom-file,.custom-file-input{height:calc(1.5em + .75rem + 2px);position:relative;width:100%}.custom-file-input{margin:0;opacity:0;overflow:hidden;z-index:2}.custom-file-input:focus~.custom-file-label{border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e5e7eb}.custom-file-input:lang(en)~.custom-file-label:after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]:after{content:attr(data-browse)}.custom-file-label{background-color:#1f2937;border:1px solid #4b5563;border-radius:.25rem;font-weight:400;height:calc(1.5em + .75rem + 2px);left:0;overflow:hidden;z-index:1}.custom-file-label,.custom-file-label:after{color:#e5e7eb;line-height:1.5;padding:.375rem .75rem;position:absolute;right:0;top:0}.custom-file-label:after{background-color:#e5e7eb;border-left:inherit;border-radius:0 .25rem .25rem 0;bottom:0;content:"Browse";display:block;height:calc(1.5em + .75rem);z-index:3}.custom-range{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;height:1.4rem;padding:0;width:100%}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #111827,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #111827,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #111827,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;margin-top:-.25rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#cbcbf0}.custom-range::-webkit-slider-runnable-track{background-color:#d1d5db;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-moz-range-thumb{-moz-appearance:none;appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#cbcbf0}.custom-range::-moz-range-track{background-color:#d1d5db;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-thumb{appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;margin-left:.2rem;margin-right:.2rem;margin-top:0;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#cbcbf0}.custom-range::-ms-track{background-color:transparent;border-color:transparent;border-width:.5rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-fill-lower,.custom-range::-ms-fill-upper{background-color:#d1d5db;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px}.custom-range:disabled::-webkit-slider-thumb{background-color:#6b7280}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#6b7280}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#6b7280}.custom-control-label:before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label:before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;flex-wrap:wrap;list-style:none;margin-bottom:0;padding-left:0}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#4b5563;cursor:default;pointer-events:none}.nav-tabs{border-bottom:1px solid #d1d5db}.nav-tabs .nav-link{background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem;margin-bottom:-1px}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e5e7eb #e5e7eb #d1d5db;isolation:isolate}.nav-tabs .nav-link.disabled{background-color:transparent;border-color:transparent;color:#4b5563}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{background-color:#111827;border-color:#d1d5db #d1d5db #111827;color:#374151}.nav-tabs .dropdown-menu{border-top-left-radius:0;border-top-right-radius:0;margin-top:-1px}.nav-pills .nav-link{background:none;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{background-color:#1f2937;color:#fff}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{padding:.5rem 1rem;position:relative}.navbar,.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between}.navbar-brand{display:inline-block;font-size:1.25rem;line-height:inherit;margin-right:1rem;padding-bottom:.3125rem;padding-top:.3125rem;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;list-style:none;margin-bottom:0;padding-left:0}.navbar-nav .nav-link{padding-left:0;padding-right:0}.navbar-nav .dropdown-menu{float:none;position:static}.navbar-text{display:inline-block;padding-bottom:.5rem;padding-top:.5rem}.navbar-collapse{align-items:center;flex-basis:100%;flex-grow:1}.navbar-toggler{background-color:transparent;border:1px solid transparent;border-radius:.25rem;font-size:1.25rem;line-height:1;padding:.25rem .75rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{background:50%/100% 100% no-repeat;content:"";display:inline-block;height:1.5em;vertical-align:middle;width:1.5em}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:1.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-left:0;padding-right:0}}@media (min-width:2px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:7.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-left:0;padding-right:0}}@media (min-width:8px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:8.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-left:0;padding-right:0}}@media (min-width:9px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:9.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-left:0;padding-right:0}}@media (min-width:10px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-left:0;padding-right:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{border-color:rgba(0,0,0,.1);color:rgba(0,0,0,.5)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{border-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{word-wrap:break-word;background-clip:border-box;background-color:#1f2937;border:1px solid rgba(0,0,0,.125);border-radius:6px;display:flex;flex-direction:column;min-width:0;position:relative}.card>hr{margin-left:0;margin-right:0}.card>.list-group{border-bottom:inherit;border-top:inherit}.card>.list-group:first-child{border-top-left-radius:5px;border-top-right-radius:5px;border-top-width:0}.card>.list-group:last-child{border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-bottom-width:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{background-color:#374151;border-bottom:1px solid rgba(0,0,0,.125);margin-bottom:0;padding:.75rem 1.25rem}.card-header:first-child{border-radius:5px 5px 0 0}.card-footer{background-color:#374151;border-top:1px solid rgba(0,0,0,.125);padding:.75rem 1.25rem}.card-footer:last-child{border-radius:0 0 5px 5px}.card-header-tabs{border-bottom:0;margin-bottom:-.75rem}.card-header-pills,.card-header-tabs{margin-left:-.625rem;margin-right:-.625rem}.card-img-overlay{border-radius:5px;bottom:0;left:0;padding:1.25rem;position:absolute;right:0;top:0}.card-img,.card-img-bottom,.card-img-top{flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:5px;border-top-right-radius:5px}.card-img,.card-img-bottom{border-bottom-left-radius:5px;border-bottom-right-radius:5px}.card-deck .card{margin-bottom:15px}@media (min-width:2px){.card-deck{display:flex;flex-flow:row wrap;margin-left:-15px;margin-right:-15px}.card-deck .card{flex:1 0 0%;margin-bottom:0;margin-left:15px;margin-right:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:2px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{border-left:0;margin-left:0}.card-group>.card:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:2px){.card-columns{-moz-column-count:3;column-count:3;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{background-color:#e5e7eb;border-radius:.25rem;display:flex;flex-wrap:wrap;list-style:none;margin-bottom:1rem;padding:.75rem 1rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item:before{color:#4b5563;content:"/";float:left;padding-right:.5rem}.breadcrumb-item+.breadcrumb-item:hover:before{text-decoration:underline;text-decoration:none}.breadcrumb-item.active{color:#4b5563}.pagination{border-radius:.25rem;display:flex;list-style:none;padding-left:0}.page-link{background-color:#fff;border:1px solid #d1d5db;color:#818cf8;display:block;line-height:1.25;margin-left:-1px;padding:.5rem .75rem;position:relative}.page-link:hover{background-color:#e5e7eb;border-color:#d1d5db;color:#a5b4fc;text-decoration:none;z-index:2}.page-link:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0;z-index:3}.page-item:first-child .page-link{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem;margin-left:0}.page-item:last-child .page-link{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.page-item.active .page-link{background-color:#4040c8;border-color:#4040c8;color:#fff;z-index:3}.page-item.disabled .page-link{background-color:#fff;border-color:#d1d5db;color:#4b5563;cursor:auto;pointer-events:none}.pagination-lg .page-link{font-size:1.25rem;line-height:1.5;padding:.75rem 1.5rem}.pagination-lg .page-item:first-child .page-link{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg .page-item:last-child .page-link{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm .page-link{font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.pagination-sm .page-item:first-child .page-link{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.badge{border-radius:.25rem;display:inline-block;font-size:.875rem;font-weight:600;line-height:1;padding:.25em .4em;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:baseline;white-space:nowrap}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{border-radius:10rem;padding-left:.6em;padding-right:.6em}.badge-primary{background-color:#4040c8;color:#fff}a.badge-primary:focus,a.badge-primary:hover{background-color:#3030a5;color:#fff}a.badge-primary.focus,a.badge-primary:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.5);outline:0}.badge-secondary{background-color:#4b5563;color:#fff}a.badge-secondary:focus,a.badge-secondary:hover{background-color:#353c46;color:#fff}a.badge-secondary.focus,a.badge-secondary:focus{box-shadow:0 0 0 .2rem rgba(75,85,99,.5);outline:0}.badge-success{background-color:#059669}a.badge-success:focus,a.badge-success:hover{background-color:#036546;color:#fff}a.badge-success.focus,a.badge-success:focus{box-shadow:0 0 0 .2rem rgba(5,150,105,.5);outline:0}.badge-info{background-color:#2563eb}a.badge-info:focus,a.badge-info:hover{background-color:#134cca;color:#fff}a.badge-info.focus,a.badge-info:focus{box-shadow:0 0 0 .2rem rgba(37,99,235,.5);outline:0}.badge-warning{background-color:#d97706}a.badge-warning:focus,a.badge-warning:hover{background-color:#a75c05;color:#fff}a.badge-warning.focus,a.badge-warning:focus{box-shadow:0 0 0 .2rem rgba(217,119,6,.5);outline:0}.badge-danger{background-color:#dc2626}a.badge-danger:focus,a.badge-danger:hover{background-color:#b21d1d;color:#fff}a.badge-danger.focus,a.badge-danger:focus{box-shadow:0 0 0 .2rem rgba(220,38,38,.5);outline:0}.badge-light{background-color:#f3f4f6;color:#111827}a.badge-light:focus,a.badge-light:hover{background-color:#d6d9e0;color:#111827}a.badge-light.focus,a.badge-light:focus{box-shadow:0 0 0 .2rem rgba(243,244,246,.5);outline:0}.badge-dark{background-color:#1f2937;color:#fff}a.badge-dark:focus,a.badge-dark:hover{background-color:#0d1116;color:#fff}a.badge-dark.focus,a.badge-dark:focus{box-shadow:0 0 0 .2rem rgba(31,41,55,.5);outline:0}.jumbotron{background-color:#e5e7eb;border-radius:6px;margin-bottom:2rem;padding:2rem 1rem}@media (min-width:2px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{border-radius:0;padding-left:0;padding-right:0}.alert{border:1px solid transparent;border-radius:.25rem;margin-bottom:1rem;padding:.75rem 1.25rem;position:relative}.alert-heading{color:inherit}.alert-link{font-weight:600}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{color:inherit;padding:.75rem 1.25rem;position:absolute;right:0;top:0;z-index:2}.alert-primary{background-color:#d9d9f4;border-color:#cacaf0;color:#212168}.alert-primary hr{border-top-color:#b6b6ea}.alert-primary .alert-link{color:#151541}.alert-secondary{background-color:#dbdde0;border-color:#cdcfd3;color:#272c33}.alert-secondary hr{border-top-color:#bfc2c7}.alert-secondary .alert-link{color:#111316}.alert-success{background-color:#cdeae1;border-color:#b9e2d5;color:#034e37}.alert-success hr{border-top-color:#a7dbca}.alert-success .alert-link{color:#011d14}.alert-info{background-color:#d3e0fb;border-color:#c2d3f9;color:#13337a}.alert-info hr{border-top-color:#abc2f7}.alert-info .alert-link{color:#0c214e}.alert-warning{background-color:#f7e4cd;border-color:#f4d9b9;color:#713e03}.alert-warning hr{border-top-color:#f1cda3}.alert-warning .alert-link{color:#3f2302}.alert-danger{background-color:#f8d4d4;border-color:#f5c2c2;color:#721414}.alert-danger hr{border-top-color:#f1acac}.alert-danger .alert-link{color:#470c0c}.alert-light{background-color:#fdfdfd;border-color:#fcfcfc;color:#7e7f80}.alert-light hr{border-top-color:#efefef}.alert-light .alert-link{color:#656666}.alert-dark{background-color:#d2d4d7;border-color:#c0c3c7;color:#10151d}.alert-dark hr{border-top-color:#b3b6bb}.alert-dark .alert-link{color:#000}@keyframes progress-bar-stripes{0%{background-position:1rem 0}to{background-position:0 0}}.progress{background-color:#e5e7eb;border-radius:.25rem;font-size:.75rem;height:1rem;line-height:0}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{background-color:#4040c8;color:#fff;flex-direction:column;justify-content:center;text-align:center;transition:width .6s ease;white-space:nowrap}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:1rem 1rem}.progress-bar-animated{animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.media{align-items:flex-start;display:flex}.media-body{flex:1}.list-group{border-radius:.25rem;display:flex;flex-direction:column;margin-bottom:0;padding-left:0}.list-group-item-action{color:#374151;text-align:inherit;width:100%}.list-group-item-action:focus,.list-group-item-action:hover{background-color:#f3f4f6;color:#374151;text-decoration:none;z-index:1}.list-group-item-action:active{background-color:#e5e7eb;color:#f3f4f6}.list-group-item{background-color:#fff;border:1px solid rgba(0,0,0,.125);display:block;padding:.75rem 1.25rem;position:relative}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{background-color:#fff;color:#4b5563;pointer-events:none}.list-group-item.active{background-color:#4040c8;border-color:#4040c8;color:#fff;z-index:2}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{border-top-width:1px;margin-top:-1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}@media (min-width:2px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:8px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-md>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:9px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:10px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{background-color:#cacaf0;color:#212168}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{background-color:#b6b6ea;color:#212168}.list-group-item-primary.list-group-item-action.active{background-color:#212168;border-color:#212168;color:#fff}.list-group-item-secondary{background-color:#cdcfd3;color:#272c33}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{background-color:#bfc2c7;color:#272c33}.list-group-item-secondary.list-group-item-action.active{background-color:#272c33;border-color:#272c33;color:#fff}.list-group-item-success{background-color:#b9e2d5;color:#034e37}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{background-color:#a7dbca;color:#034e37}.list-group-item-success.list-group-item-action.active{background-color:#034e37;border-color:#034e37;color:#fff}.list-group-item-info{background-color:#c2d3f9;color:#13337a}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{background-color:#abc2f7;color:#13337a}.list-group-item-info.list-group-item-action.active{background-color:#13337a;border-color:#13337a;color:#fff}.list-group-item-warning{background-color:#f4d9b9;color:#713e03}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{background-color:#f1cda3;color:#713e03}.list-group-item-warning.list-group-item-action.active{background-color:#713e03;border-color:#713e03;color:#fff}.list-group-item-danger{background-color:#f5c2c2;color:#721414}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{background-color:#f1acac;color:#721414}.list-group-item-danger.list-group-item-action.active{background-color:#721414;border-color:#721414;color:#fff}.list-group-item-light{background-color:#fcfcfc;color:#7e7f80}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{background-color:#efefef;color:#7e7f80}.list-group-item-light.list-group-item-action.active{background-color:#7e7f80;border-color:#7e7f80;color:#fff}.list-group-item-dark{background-color:#c0c3c7;color:#10151d}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{background-color:#b3b6bb;color:#10151d}.list-group-item-dark.list-group-item-action.active{background-color:#10151d;border-color:#10151d;color:#fff}.close{color:#000;float:right;font-size:1.5rem;font-weight:600;line-height:1;opacity:.5;text-shadow:0 1px 0 #fff}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{background-color:transparent;border:0;padding:0}a.close.disabled{pointer-events:none}.toast{background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border:1px solid rgba(0,0,0,.1);border-radius:.25rem;box-shadow:0 .25rem .75rem rgba(0,0,0,.1);flex-basis:350px;font-size:.875rem;max-width:350px;opacity:0}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{align-items:center;background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px);color:#4b5563;display:flex;padding:.25rem .75rem}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{display:none;height:100%;left:0;outline:0;overflow:hidden;position:fixed;top:0;width:100%;z-index:1050}.modal-dialog{margin:.5rem;pointer-events:none;position:relative;width:auto}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{align-items:center;display:flex;min-height:calc(100% - 1rem)}.modal-dialog-centered:before{content:"";display:block;height:calc(100vh - 1rem);height:-moz-min-content;height:min-content}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;height:100%;justify-content:center}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable:before{content:none}.modal-content{background-clip:padding-box;background-color:#1f2937;border:1px solid rgba(0,0,0,.2);border-radius:6px;display:flex;flex-direction:column;outline:0;pointer-events:auto;position:relative;width:100%}.modal-backdrop{background-color:#4b5563;height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:1040}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{align-items:flex-start;border-bottom:1px solid #4b5563;border-top-left-radius:5px;border-top-right-radius:5px;display:flex;justify-content:space-between;padding:1rem}.modal-header .close{margin:-1rem -1rem -1rem auto;padding:1rem}.modal-title{line-height:1.5;margin-bottom:0}.modal-body{flex:1 1 auto;padding:1rem;position:relative}.modal-footer{align-items:center;border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-top:1px solid #4b5563;display:flex;flex-wrap:wrap;justify-content:flex-end;padding:.75rem}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{height:50px;overflow:scroll;position:absolute;top:-9999px;width:50px}@media (min-width:2px){.modal-dialog{margin:1.75rem auto;max-width:500px}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered:before{height:calc(100vh - 3.5rem);height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:9px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:10px){.modal-xl{max-width:1140px}}.tooltip{word-wrap:break-word;display:block;font-family:Figtree,sans-serif;font-size:.875rem;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;margin:0;opacity:0;position:absolute;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;z-index:1070}.tooltip.show{opacity:.9}.tooltip .arrow{display:block;height:.4rem;position:absolute;width:.8rem}.tooltip .arrow:before{border-color:transparent;border-style:solid;content:"";position:absolute}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow:before,.bs-tooltip-top .arrow:before{border-top-color:#000;border-width:.4rem .4rem 0;top:0}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{height:.8rem;left:0;width:.4rem}.bs-tooltip-auto[x-placement^=right] .arrow:before,.bs-tooltip-right .arrow:before{border-right-color:#000;border-width:.4rem .4rem .4rem 0;right:0}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.bs-tooltip-bottom .arrow:before{border-bottom-color:#000;border-width:0 .4rem .4rem;bottom:0}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{height:.8rem;right:0;width:.4rem}.bs-tooltip-auto[x-placement^=left] .arrow:before,.bs-tooltip-left .arrow:before{border-left-color:#000;border-width:.4rem 0 .4rem .4rem;left:0}.tooltip-inner{background-color:#000;border-radius:.25rem;color:#fff;max-width:200px;padding:.25rem .5rem;text-align:center}.popover{word-wrap:break-word;background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:6px;font-family:Figtree,sans-serif;font-size:.875rem;font-style:normal;font-weight:400;left:0;letter-spacing:normal;line-break:auto;line-height:1.5;max-width:276px;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;top:0;white-space:normal;word-break:normal;word-spacing:normal;z-index:1060}.popover,.popover .arrow{display:block;position:absolute}.popover .arrow{height:.5rem;margin:0 6px;width:1rem}.popover .arrow:after,.popover .arrow:before{border-color:transparent;border-style:solid;content:"";display:block;position:absolute}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow:before,.bs-popover-top>.arrow:before{border-top-color:rgba(0,0,0,.25);border-width:.5rem .5rem 0;bottom:0}.bs-popover-auto[x-placement^=top]>.arrow:after,.bs-popover-top>.arrow:after{border-top-color:#fff;border-width:.5rem .5rem 0;bottom:1px}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{height:1rem;left:calc(-.5rem - 1px);margin:6px 0;width:.5rem}.bs-popover-auto[x-placement^=right]>.arrow:before,.bs-popover-right>.arrow:before{border-right-color:rgba(0,0,0,.25);border-width:.5rem .5rem .5rem 0;left:0}.bs-popover-auto[x-placement^=right]>.arrow:after,.bs-popover-right>.arrow:after{border-right-color:#fff;border-width:.5rem .5rem .5rem 0;left:1px}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow:before,.bs-popover-bottom>.arrow:before{border-bottom-color:rgba(0,0,0,.25);border-width:0 .5rem .5rem;top:0}.bs-popover-auto[x-placement^=bottom]>.arrow:after,.bs-popover-bottom>.arrow:after{border-bottom-color:#fff;border-width:0 .5rem .5rem;top:1px}.bs-popover-auto[x-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{border-bottom:1px solid #f7f7f7;content:"";display:block;left:50%;margin-left:-.5rem;position:absolute;top:0;width:1rem}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{height:1rem;margin:6px 0;right:calc(-.5rem - 1px);width:.5rem}.bs-popover-auto[x-placement^=left]>.arrow:before,.bs-popover-left>.arrow:before{border-left-color:rgba(0,0,0,.25);border-width:.5rem 0 .5rem .5rem;right:0}.bs-popover-auto[x-placement^=left]>.arrow:after,.bs-popover-left>.arrow:after{border-left-color:#fff;border-width:.5rem 0 .5rem .5rem;right:1px}.popover-header{background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:5px;border-top-right-radius:5px;font-size:1rem;margin-bottom:0;padding:.5rem .75rem}.popover-header:empty{display:none}.popover-body{color:#f3f4f6;padding:.5rem .75rem}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{overflow:hidden;position:relative;width:100%}.carousel-inner:after{clear:both;content:"";display:block}.carousel-item{backface-visibility:hidden;display:none;float:left;margin-right:-100%;position:relative;transition:transform .6s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transform:none;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{opacity:1;z-index:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0;transition:opacity 0s .6s;z-index:0}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{align-items:center;background:none;border:0;bottom:0;color:#fff;display:flex;justify-content:center;opacity:.5;padding:0;position:absolute;text-align:center;top:0;transition:opacity .15s ease;width:15%;z-index:1}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;opacity:.9;outline:0;text-decoration:none}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{background:50%/100% 100% no-repeat;display:inline-block;height:20px;width:20px}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m5.25 0-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m2.75 0-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{bottom:0;display:flex;justify-content:center;left:0;list-style:none;margin-left:15%;margin-right:15%;padding-left:0;position:absolute;right:0;z-index:15}.carousel-indicators li{background-clip:padding-box;background-color:#fff;border-bottom:10px solid transparent;border-top:10px solid transparent;box-sizing:content-box;cursor:pointer;flex:0 1 auto;height:3px;margin-left:3px;margin-right:3px;opacity:.5;text-indent:-999px;transition:opacity .6s ease;width:30px}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{bottom:20px;color:#fff;left:15%;padding-bottom:20px;padding-top:20px;position:absolute;right:15%;text-align:center;z-index:10}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{animation:spinner-border .75s linear infinite;border:.25em solid;border-radius:50%;border-right:.25em solid transparent;display:inline-block;height:2rem;vertical-align:-.125em;width:2rem}.spinner-border-sm{border-width:.2em;height:1rem;width:1rem}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{animation:spinner-grow .75s linear infinite;background-color:currentcolor;border-radius:50%;display:inline-block;height:2rem;opacity:0;vertical-align:-.125em;width:2rem}.spinner-grow-sm{height:1rem;width:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#4040c8!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#3030a5!important}.bg-secondary{background-color:#4b5563!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#353c46!important}.bg-success{background-color:#059669!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#036546!important}.bg-info{background-color:#2563eb!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#134cca!important}.bg-warning{background-color:#d97706!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#a75c05!important}.bg-danger{background-color:#dc2626!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#b21d1d!important}.bg-light{background-color:#f3f4f6!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#d6d9e0!important}.bg-dark{background-color:#1f2937!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#0d1116!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #4b5563!important}.border-top{border-top:1px solid #4b5563!important}.border-right{border-right:1px solid #4b5563!important}.border-bottom{border-bottom:1px solid #4b5563!important}.border-left{border-left:1px solid #4b5563!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#4040c8!important}.border-secondary{border-color:#4b5563!important}.border-success{border-color:#059669!important}.border-info{border-color:#2563eb!important}.border-warning{border-color:#d97706!important}.border-danger{border-color:#dc2626!important}.border-light{border-color:#f3f4f6!important}.border-dark{border-color:#1f2937!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important}.rounded-lg{border-radius:6px!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix:after{clear:both;content:"";display:block}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:2px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:8px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:9px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:10px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{display:block;overflow:hidden;padding:0;position:relative;width:100%}.embed-responsive:before{content:"";display:block}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{border:0;bottom:0;height:100%;left:0;position:absolute;top:0;width:100%}.embed-responsive-21by9:before{padding-top:42.85714286%}.embed-responsive-16by9:before{padding-top:56.25%}.embed-responsive-4by3:before{padding-top:75%}.embed-responsive-1by1:before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:2px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:8px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:9px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:10px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:2px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:8px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:9px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:10px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.fixed-top{top:0}.fixed-bottom,.fixed-top{left:0;position:fixed;right:0;z-index:1030}.fixed-bottom{bottom:0}@supports (position:sticky){.sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;overflow:visible;position:static;white-space:normal;width:auto}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:2px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:8px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:9px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:10px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link:after{background-color:transparent;bottom:0;content:"";left:0;pointer-events:auto;position:absolute;right:0;top:0;z-index:1}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:2px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:8px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:9px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:10px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:600!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#4040c8!important}a.text-primary:focus,a.text-primary:hover{color:#2a2a92!important}.text-secondary{color:#4b5563!important}a.text-secondary:focus,a.text-secondary:hover{color:#2a3037!important}.text-success{color:#059669!important}a.text-success:focus,a.text-success:hover{color:#034c35!important}.text-info{color:#2563eb!important}a.text-info:focus,a.text-info:hover{color:#1043b3!important}.text-warning{color:#d97706!important}a.text-warning:focus,a.text-warning:hover{color:#8f4e04!important}.text-danger{color:#dc2626!important}a.text-danger:focus,a.text-danger:hover{color:#9c1919!important}.text-light{color:#f3f4f6!important}a.text-light:focus,a.text-light:hover{color:#c7ccd5!important}.text-dark{color:#1f2937!important}a.text-dark:focus,a.text-dark:hover{color:#030506!important}.text-body{color:#f3f4f6!important}.text-muted{color:#9ca3af!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:hsla(0,0%,100%,.5)!important}.text-hide{background-color:transparent;border:0;color:transparent;font:0/0 a;text-shadow:none}.text-decoration-none{text-decoration:none!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,:after,:before{box-shadow:none!important;text-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #6b7280}blockquote,img,pre,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3;}.container,body{min-width:9px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #d1d5db!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#374151}.table .thead-dark th{border-color:#374151;color:inherit}}.vjs-tree{color:#bfc7d5!important;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.vjs-tree .vjs-tree__content{border-left:1px dotted hsla(0,0%,80%,.28)!important}.vjs-tree .vjs-tree__node{cursor:pointer}.vjs-tree .vjs-tree__node:hover{color:#20a0ff}.vjs-tree .vjs-checkbox{left:-30px;position:absolute}.vjs-tree .vjs-value__boolean,.vjs-tree .vjs-value__null,.vjs-tree .vjs-value__number{color:#a291f5!important}.vjs-tree .vjs-value__string{color:#c3e88d!important}.vjs-tree .vjs-key{color:#c3cbd3!important}.hljs-addition,.hljs-attr,.hljs-keyword,.hljs-selector-tag{color:#13ce66}.hljs-bullet,.hljs-meta,.hljs-name,.hljs-string,.hljs-symbol,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable{color:#c3e88d}.hljs-comment,.hljs-deletion,.hljs-quote{color:#bfcbd9}.hljs-literal,.hljs-number,.hljs-title{color:#a291f5!important}body{padding-bottom:20px}.container{max-width:1440px}html{min-width:1140px}[v-cloak]{display:none}svg.icon{height:1rem;width:1rem}.header{border-bottom:1px solid #374151}.header .logo{color:#e5e7eb;text-decoration:none}.header .logo svg{height:1.7rem;width:1.7rem}.sidebar .nav-item a{border-radius:6px;color:#9ca3af;margin-bottom:4px;padding:.5rem .75rem}.sidebar .nav-item a svg{fill:#6b7280;height:1.25rem;margin-right:15px;width:1.25rem}.sidebar .nav-item a:hover{background-color:#1f2937;color:#d1d5db}.sidebar .nav-item a.active{background-color:#1f2937;color:#818cf8}.sidebar .nav-item a.active svg{fill:#6366f1}.card{border:none;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1)}.card .bottom-radius{border-bottom-left-radius:6px;border-bottom-right-radius:6px}.card .card-header{background-color:#374151;border-bottom:none;min-height:60px;padding-bottom:.7rem;padding-top:.7rem}.card .card-header .btn-group .btn{padding:.2rem .5rem}.card .card-header .form-control-with-icon{position:relative}.card .card-header .form-control-with-icon .icon-wrapper{align-items:center;bottom:0;display:flex;justify-content:center;left:.75rem;position:absolute;top:0}.card .card-header .form-control-with-icon .icon-wrapper .icon{fill:#9ca3af}.card .card-header .form-control-with-icon .form-control{border-radius:9999px;font-size:.875rem;padding-left:2.25rem}.card .table td,.card .table th{padding:.75rem 1.25rem}.card .table th{background-color:#1f2937;border-bottom:0;font-size:.875rem;padding:.5rem 1.25rem}.card .table:not(.table-borderless) td{border-top:1px solid #374151}.card .table.penultimate-column-right td:nth-last-child(2),.card .table.penultimate-column-right th:nth-last-child(2){text-align:right}.card .table td.table-fit,.card .table th.table-fit{white-space:nowrap;width:1%}.fill-text-color{fill:#f3f4f6}.fill-danger{fill:#dc2626}.fill-warning{fill:#d97706}.fill-info{fill:#2563eb}.fill-success{fill:#059669}.fill-primary{fill:#4040c8}button:hover .fill-primary{fill:#fff}.btn-outline-primary.active .fill-primary{fill:#111827}.btn-outline-primary:not(:disabled):not(.disabled).active:focus{box-shadow:none!important}.btn-muted{background:#1f2937;color:#9ca3af}.btn-muted:focus,.btn-muted:hover{background:#374151;color:#d1d5db}.btn-muted.active{background:#4040c8;color:#fff}.badge-secondary{background:#d1d5db;color:#374151}.badge-success{background:#10b981;color:#fff}.badge-info{background:#3b82f6;color:#fff}.badge-warning{background:#f59e0b;color:#fff}.badge-danger{background:#ef4444;color:#fff}.control-action svg{fill:#6b7280;height:1.2rem;width:1.2rem}.control-action svg:hover{fill:#818cf8}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.spin{animation:spin 2s linear infinite}.card .nav-pills{background:#374151}.card .nav-pills .nav-link{border-radius:0;color:#9ca3af;font-size:.9rem;padding:.75rem 1.25rem}.card .nav-pills .nav-link:focus,.card .nav-pills .nav-link:hover{color:#e5e7eb}.card .nav-pills .nav-link.active{background:none;border-bottom:2px solid #a5b4fc;color:#a5b4fc}.list-enter-active:not(.dontanimate){transition:background 1s linear}.list-enter:not(.dontanimate),.list-leave-to:not(.dontanimate){background:#312e81}.code-bg .list-enter:not(.dontanimate),.code-bg .list-leave-to:not(.dontanimate){background:#4b5563}#indexScreen td{vertical-align:middle!important}.card-bg-secondary{background:#1f2937}.code-bg{background:#292d3e}.disabled-watcher{background:#dc2626;color:#fff;padding:.75rem}.copy-to-clipboard{--tw-text-opacity:1;color:rgb(231 232 242/var(--tw-text-opacity));opacity:.7;outline:2px solid transparent;outline-offset:2px;position:absolute;right:0;top:0;z-index:10} + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#4b5563;--gray-dark:#1f2937;--primary:#4040c8;--secondary:#4b5563;--success:#059669;--info:#2563eb;--warning:#d97706;--danger:#dc2626;--light:#f3f4f6;--dark:#1f2937;--breakpoint-xs:0;--breakpoint-sm:2px;--breakpoint-md:8px;--breakpoint-lg:9px;--breakpoint-xl:10px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);font-family:sans-serif;line-height:1.15}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{background-color:#111827;color:#f3f4f6;font-family:Figtree,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;margin:0;text-align:left}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;margin-top:0}p{margin-bottom:1rem;margin-top:0}abbr[data-original-title],abbr[title]{border-bottom:0;cursor:help;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:600}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{background-color:transparent;color:#818cf8;text-decoration:none}a:hover{color:#a5b4fc;text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{-ms-overflow-style:scrollbar;margin-bottom:1rem;margin-top:0;overflow:auto}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{caption-side:bottom;color:#9ca3af;padding-bottom:.75rem;padding-top:.75rem;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;margin:0}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{border:0;margin:0;min-width:0;padding:0}legend{color:inherit;display:block;font-size:1.5rem;line-height:inherit;margin-bottom:.5rem;max-width:100%;padding:0;white-space:normal;width:100%}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:none;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}output{display:inline-block}summary{cursor:pointer;display:list-item}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.2;margin-bottom:.5rem}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{border:0;border-top:1px solid rgba(0,0,0,.1);margin-bottom:1rem;margin-top:1rem}.small,small{font-size:.875em;font-weight:400}.mark,mark{background-color:#fcf8e3;padding:.2em}.list-inline,.list-unstyled{list-style:none;padding-left:0}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{font-size:1.25rem;margin-bottom:1rem}.blockquote-footer{color:#4b5563;display:block;font-size:.875em}.blockquote-footer:before{content:"โ€”ย "}.img-fluid,.img-thumbnail{height:auto;max-width:100%}.img-thumbnail{background-color:#111827;border:1px solid #d1d5db;border-radius:.25rem;padding:.25rem}.figure{display:inline-block}.figure-img{line-height:1;margin-bottom:.5rem}.figure-caption{color:#4b5563;font-size:90%}code{word-wrap:break-word;color:#e83e8c;font-size:87.5%}a>code{color:inherit}kbd{background-color:#111827;border-radius:.2rem;color:#fff;font-size:87.5%;padding:.2rem .4rem}kbd kbd{font-size:100%;font-weight:600;padding:0}pre{color:#111827;display:block;font-size:87.5%}pre code{color:inherit;font-size:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px;width:100%}@media (min-width:2px){.container,.container-sm{max-width:1137px}}@media (min-width:8px){.container,.container-md,.container-sm{max-width:1138px}}@media (min-width:9px){.container,.container-lg,.container-md,.container-sm{max-width:1139px}}@media (min-width:10px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:flex;flex-wrap:wrap;margin-left:-15px;margin-right:-15px}.no-gutters{margin-left:0;margin-right:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-left:0;padding-right:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{padding-left:15px;padding-right:15px;position:relative;width:100%}.col{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-auto{flex:0 0 auto;max-width:100%;width:auto}.col-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}@media (min-width:2px){.col-sm{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-auto{flex:0 0 auto;max-width:100%;width:auto}.col-sm-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-sm-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-sm-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-sm-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-sm-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}}@media (min-width:8px){.col-md{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-auto{flex:0 0 auto;max-width:100%;width:auto}.col-md-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-md-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-md-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-md-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-md-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}}@media (min-width:9px){.col-lg{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-auto{flex:0 0 auto;max-width:100%;width:auto}.col-lg-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-lg-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-lg-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-lg-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-lg-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}}@media (min-width:10px){.col-xl{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-auto{flex:0 0 auto;max-width:100%;width:auto}.col-xl-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-xl-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-xl-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-xl-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-xl-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}}.table{color:#f3f4f6;margin-bottom:1rem;width:100%}.table td,.table th{border-top:1px solid #374151;padding:.75rem;vertical-align:top}.table thead th{border-bottom:2px solid #374151;vertical-align:bottom}.table tbody+tbody{border-top:2px solid #374151}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #374151}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:#374151;color:#f3f4f6}.table-primary,.table-primary>td,.table-primary>th{background-color:#cacaf0}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#9c9ce2}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#b6b6ea}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#cdcfd3}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#a1a7ae}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#bfc2c7}.table-success,.table-success>td,.table-success>th{background-color:#b9e2d5}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#7dc8b1}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#a7dbca}.table-info,.table-info>td,.table-info>th{background-color:#c2d3f9}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#8eaef5}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abc2f7}.table-warning,.table-warning>td,.table-warning>th{background-color:#f4d9b9}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ebb87e}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#f1cda3}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c2c2}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed8e8e}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1acac}.table-light,.table-light>td,.table-light>th{background-color:#fcfcfc}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#f9f9fa}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#efefef}.table-dark,.table-dark>td,.table-dark>th{background-color:#c0c3c7}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#8b9097}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b3b6bb}.table-active,.table-active>td,.table-active>th{background-color:#374151}.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:#2d3542}.table .thead-dark th{background-color:#1f2937;border-color:#2d3b4f;color:#fff}.table .thead-light th{background-color:#e5e7eb;border-color:#374151;color:#374151}.table-dark{background-color:#1f2937;color:#fff}.table-dark td,.table-dark th,.table-dark thead th{border-color:#2d3b4f}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:hsla(0,0%,100%,.05)}.table-dark.table-hover tbody tr:hover{background-color:hsla(0,0%,100%,.075);color:#fff}@media (max-width:1.98px){.table-responsive-sm{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:7.98px){.table-responsive-md{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-md>.table-bordered{border:0}}@media (max-width:8.98px){.table-responsive-lg{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:9.98px){.table-responsive-xl{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive>.table-bordered{border:0}.form-control{background-clip:padding-box;background-color:#1f2937;border:1px solid #4b5563;border-radius:.25rem;color:#e5e7eb;display:block;font-size:1rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{background-color:#1f2937;border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25);color:#e5e7eb;outline:0}.form-control::-moz-placeholder{color:#4b5563;opacity:1}.form-control::placeholder{color:#4b5563;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e5e7eb;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #e5e7eb}select.form-control:focus::-ms-value{background-color:#1f2937;color:#e5e7eb}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{font-size:inherit;line-height:1.5;margin-bottom:0;padding-bottom:calc(.375rem + 1px);padding-top:calc(.375rem + 1px)}.col-form-label-lg{font-size:1.25rem;line-height:1.5;padding-bottom:calc(.5rem + 1px);padding-top:calc(.5rem + 1px)}.col-form-label-sm{font-size:.875rem;line-height:1.5;padding-bottom:calc(.25rem + 1px);padding-top:calc(.25rem + 1px)}.form-control-plaintext{background-color:transparent;border:solid transparent;border-width:1px 0;color:#f3f4f6;display:block;font-size:1rem;line-height:1.5;margin-bottom:0;padding:.375rem 0;width:100%}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-left:0;padding-right:0}.form-control-sm{border-radius:.2rem;font-size:.875rem;height:calc(1.5em + .5rem + 2px);line-height:1.5;padding:.25rem .5rem}.form-control-lg{border-radius:6px;font-size:1.25rem;height:calc(1.5em + 1rem + 2px);line-height:1.5;padding:.5rem 1rem}select.form-control[multiple],select.form-control[size],textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-left:-5px;margin-right:-5px}.form-row>.col,.form-row>[class*=col-]{padding-left:5px;padding-right:5px}.form-check{display:block;padding-left:1.25rem;position:relative}.form-check-input{margin-left:-1.25rem;margin-top:.3rem;position:absolute}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#9ca3af}.form-check-label{margin-bottom:0}.form-check-inline{align-items:center;display:inline-flex;margin-right:.75rem;padding-left:0}.form-check-inline .form-check-input{margin-left:0;margin-right:.3125rem;margin-top:0;position:static}.valid-feedback{color:#059669;display:none;font-size:.875em;margin-top:.25rem;width:100%}.valid-tooltip{background-color:rgba(5,150,105,.9);border-radius:.25rem;color:#fff;display:none;font-size:.875rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23059669' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#059669;padding-right:calc(1.5em + .75rem)!important}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-valid,.was-validated .custom-select:valid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#1f2937 url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23059669' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#059669;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#059669}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#059669}.custom-control-input.is-valid~.custom-control-label:before,.was-validated .custom-control-input:valid~.custom-control-label:before{border-color:#059669}.custom-control-input.is-valid:checked~.custom-control-label:before,.was-validated .custom-control-input:valid:checked~.custom-control-label:before{background-color:#07c78c;border-color:#07c78c}.custom-control-input.is-valid:focus~.custom-control-label:before,.was-validated .custom-control-input:valid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label:before{border-color:#059669}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#059669}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.invalid-feedback{color:#dc2626;display:none;font-size:.875em;margin-top:.25rem;width:100%}.invalid-tooltip{background-color:rgba(220,38,38,.9);border-radius:.25rem;color:#fff;display:none;font-size:.875rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc2626'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc2626' stroke='none'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#dc2626;padding-right:calc(1.5em + .75rem)!important}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#1f2937 url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc2626'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc2626' stroke='none'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#dc2626;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc2626}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc2626}.custom-control-input.is-invalid~.custom-control-label:before,.was-validated .custom-control-input:invalid~.custom-control-label:before{border-color:#dc2626}.custom-control-input.is-invalid:checked~.custom-control-label:before,.was-validated .custom-control-input:invalid:checked~.custom-control-label:before{background-color:#e35252;border-color:#e35252}.custom-control-input.is-invalid:focus~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label:before{border-color:#dc2626}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc2626}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.form-inline{align-items:center;display:flex;flex-flow:row wrap}.form-inline .form-check{width:100%}@media (min-width:2px){.form-inline label{justify-content:center}.form-inline .form-group,.form-inline label{align-items:center;display:flex;margin-bottom:0}.form-inline .form-group{flex:0 0 auto;flex-flow:row wrap}.form-inline .form-control{display:inline-block;vertical-align:middle;width:auto}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{align-items:center;display:flex;justify-content:center;padding-left:0;width:auto}.form-inline .form-check-input{flex-shrink:0;margin-left:0;margin-right:.25rem;margin-top:0;position:relative}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;color:#f3f4f6;display:inline-block;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#f3f4f6;text-decoration:none}.btn.focus,.btn:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-primary.focus,.btn-primary:focus,.btn-primary:hover{background-color:#3232af;border-color:#3030a5;color:#fff}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(93,93,208,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{background-color:#3030a5;border-color:#2d2d9b;color:#fff}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(93,93,208,.5)}.btn-secondary{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:hover{background-color:#3b424d;border-color:#353c46;color:#fff}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem hsla(213,9%,44%,.5)}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{background-color:#353c46;border-color:#30363f;color:#fff}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem hsla(213,9%,44%,.5)}.btn-success{background-color:#059669;border-color:#059669;color:#fff}.btn-success.focus,.btn-success:focus,.btn-success:hover{background-color:#04714f;border-color:#036546;color:#fff}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(43,166,128,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#059669;border-color:#059669;color:#fff}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{background-color:#036546;border-color:#03583e;color:#fff}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(43,166,128,.5)}.btn-info{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-info.focus,.btn-info:focus,.btn-info:hover{background-color:#1451d6;border-color:#134cca;color:#fff}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(70,122,238,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{background-color:#134cca;border-color:#1248bf;color:#fff}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(70,122,238,.5)}.btn-warning{background-color:#d97706;border-color:#d97706;color:#fff}.btn-warning.focus,.btn-warning:focus,.btn-warning:hover{background-color:#b46305;border-color:#a75c05;color:#fff}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(223,139,43,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#d97706;border-color:#d97706;color:#fff}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{background-color:#a75c05;border-color:#9b5504;color:#fff}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(223,139,43,.5)}.btn-danger{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-danger.focus,.btn-danger:focus,.btn-danger:hover{background-color:#bd1f1f;border-color:#b21d1d;color:#fff}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(225,71,71,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{background-color:#b21d1d;border-color:#a71b1b;color:#fff}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,71,71,.5)}.btn-light{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-light.focus,.btn-light:focus,.btn-light:hover{background-color:#dde0e6;border-color:#d6d9e0;color:#111827}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem hsla(220,7%,83%,.5)}.btn-light.disabled,.btn-light:disabled{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{background-color:#d6d9e0;border-color:#cfd3db;color:#111827}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem hsla(220,7%,83%,.5)}.btn-dark{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-dark.focus,.btn-dark:focus,.btn-dark:hover{background-color:#11171f;border-color:#0d1116;color:#fff}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(65,73,85,.5)}.btn-dark.disabled,.btn-dark:disabled{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{background-color:#0d1116;border-color:#080b0e;color:#fff}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(65,73,85,.5)}.btn-outline-primary{border-color:#4040c8;color:#4040c8}.btn-outline-primary:hover{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{background-color:transparent;color:#4040c8}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.5)}.btn-outline-secondary{border-color:#4b5563;color:#4b5563}.btn-outline-secondary:hover{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(75,85,99,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{background-color:transparent;color:#4b5563}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(75,85,99,.5)}.btn-outline-success{border-color:#059669;color:#059669}.btn-outline-success:hover{background-color:#059669;border-color:#059669;color:#fff}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(5,150,105,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{background-color:transparent;color:#059669}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{background-color:#059669;border-color:#059669;color:#fff}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(5,150,105,.5)}.btn-outline-info{border-color:#2563eb;color:#2563eb}.btn-outline-info:hover{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(37,99,235,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{background-color:transparent;color:#2563eb}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(37,99,235,.5)}.btn-outline-warning{border-color:#d97706;color:#d97706}.btn-outline-warning:hover{background-color:#d97706;border-color:#d97706;color:#fff}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(217,119,6,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{background-color:transparent;color:#d97706}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{background-color:#d97706;border-color:#d97706;color:#fff}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(217,119,6,.5)}.btn-outline-danger{border-color:#dc2626;color:#dc2626}.btn-outline-danger:hover{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,38,38,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{background-color:transparent;color:#dc2626}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,38,38,.5)}.btn-outline-light{border-color:#f3f4f6;color:#f3f4f6}.btn-outline-light:hover{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(243,244,246,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{background-color:transparent;color:#f3f4f6}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(243,244,246,.5)}.btn-outline-dark{border-color:#1f2937;color:#1f2937}.btn-outline-dark:hover{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(31,41,55,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{background-color:transparent;color:#1f2937}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(31,41,55,.5)}.btn-link{color:#818cf8;font-weight:400;text-decoration:none}.btn-link:hover{color:#a5b4fc}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#4b5563;pointer-events:none}.btn-group-lg>.btn,.btn-lg{border-radius:6px;font-size:1.25rem;line-height:1.5;padding:.5rem 1rem}.btn-group-sm>.btn,.btn-sm{border-radius:.2rem;font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;position:relative;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{height:auto;transition:width .35s ease;width:0}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{border-bottom:0;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:.3em solid;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{background-clip:padding-box;background-color:#374151;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;color:#f3f4f6;display:none;float:left;font-size:1rem;left:0;list-style:none;margin:.125rem 0 0;min-width:10rem;padding:.5rem 0;position:absolute;text-align:left;top:100%;z-index:1000}.dropdown-menu-left{left:0;right:auto}.dropdown-menu-right{left:auto;right:0}@media (min-width:2px){.dropdown-menu-sm-left{left:0;right:auto}.dropdown-menu-sm-right{left:auto;right:0}}@media (min-width:8px){.dropdown-menu-md-left{left:0;right:auto}.dropdown-menu-md-right{left:auto;right:0}}@media (min-width:9px){.dropdown-menu-lg-left{left:0;right:auto}.dropdown-menu-lg-right{left:auto;right:0}}@media (min-width:10px){.dropdown-menu-xl-left{left:0;right:auto}.dropdown-menu-xl-right{left:auto;right:0}}.dropup .dropdown-menu{bottom:100%;margin-bottom:.125rem;margin-top:0;top:auto}.dropup .dropdown-toggle:after{border-bottom:.3em solid;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:0;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-menu{left:100%;margin-left:.125rem;margin-top:0;right:auto;top:0}.dropright .dropdown-toggle:after{border-bottom:.3em solid transparent;border-left:.3em solid;border-right:0;border-top:.3em solid transparent;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropright .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-toggle:after{vertical-align:0}.dropleft .dropdown-menu{left:auto;margin-right:.125rem;margin-top:0;right:100%;top:0}.dropleft .dropdown-toggle:after{content:"";display:inline-block;display:none;margin-left:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:before{border-bottom:.3em solid transparent;border-right:.3em solid;border-top:.3em solid transparent;content:"";display:inline-block;margin-right:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:empty:after{margin-left:0}.dropleft .dropdown-toggle:before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{bottom:auto;right:auto}.dropdown-divider{border-top:1px solid #e5e7eb;height:0;margin:.5rem 0;overflow:hidden}.dropdown-item{background-color:transparent;border:0;clear:both;color:#fff;display:block;font-weight:400;padding:.25rem 1.5rem;text-align:inherit;white-space:nowrap;width:100%}.dropdown-item:focus,.dropdown-item:hover{background-color:#e5e7eb;color:#090d15;text-decoration:none}.dropdown-item.active,.dropdown-item:active{background-color:#4040c8;color:#fff;text-decoration:none}.dropdown-item.disabled,.dropdown-item:disabled{background-color:transparent;color:#6b7280;pointer-events:none}.dropdown-menu.show{display:block}.dropdown-header{color:#4b5563;display:block;font-size:.875rem;margin-bottom:0;padding:.5rem 1.5rem;white-space:nowrap}.dropdown-item-text{color:#fff;display:block;padding:.25rem 1.5rem}.btn-group,.btn-group-vertical{display:inline-flex;position:relative;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{flex:1 1 auto;position:relative}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.dropdown-toggle-split{padding-left:.5625rem;padding-right:.5625rem}.dropdown-toggle-split:after,.dropright .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropleft .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-left:.375rem;padding-right:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-left:.75rem;padding-right:.75rem}.btn-group-vertical{align-items:flex-start;flex-direction:column;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-left-radius:0;border-bottom-right-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{clip:rect(0,0,0,0);pointer-events:none;position:absolute}.input-group{align-items:stretch;display:flex;flex-wrap:wrap;position:relative;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{flex:1 1 auto;margin-bottom:0;min-width:0;position:relative;width:1%}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group>.custom-file{align-items:center;display:flex}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label:after{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-bottom-left-radius:0;border-top-left-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label:after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3),.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label:after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.input-group-append,.input-group-prepend{display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{align-items:center;background-color:#e5e7eb;border:1px solid #4b5563;border-radius:.25rem;color:#e5e7eb;display:flex;font-size:1rem;font-weight:400;line-height:1.5;margin-bottom:0;padding:.375rem .75rem;text-align:center;white-space:nowrap}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{border-radius:6px;font-size:1.25rem;line-height:1.5;padding:.5rem 1rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{border-radius:.2rem;font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-bottom-left-radius:0;border-top-left-radius:0}.custom-control{display:block;min-height:1.5rem;padding-left:1.5rem;position:relative;-webkit-print-color-adjust:exact;print-color-adjust:exact;z-index:1}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{height:1.25rem;left:0;opacity:0;position:absolute;width:1rem;z-index:-1}.custom-control-input:checked~.custom-control-label:before{background-color:#4040c8;border-color:#4040c8;color:#fff}.custom-control-input:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(64,64,200,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label:before{border-color:#a3a3e5}.custom-control-input:not(:disabled):active~.custom-control-label:before{background-color:#cbcbf0;border-color:#cbcbf0;color:#fff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#4b5563}.custom-control-input:disabled~.custom-control-label:before,.custom-control-input[disabled]~.custom-control-label:before{background-color:#e5e7eb}.custom-control-label{margin-bottom:0;position:relative;vertical-align:top}.custom-control-label:before{background-color:#1f2937;border:1px solid #6b7280;pointer-events:none}.custom-control-label:after,.custom-control-label:before{content:"";display:block;height:1rem;left:-1.5rem;position:absolute;top:.25rem;width:1rem}.custom-control-label:after{background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label:before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23fff' d='m6.564.75-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:before{background-color:#4040c8;border-color:#4040c8}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-radio .custom-control-label:before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label:before{border-radius:.5rem;left:-2.25rem;pointer-events:all;width:1.75rem}.custom-switch .custom-control-label:after{background-color:#6b7280;border-radius:.5rem;height:calc(1rem - 4px);left:calc(-2.25rem + 2px);top:calc(.25rem + 2px);transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:calc(1rem - 4px)}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label:after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label:after{background-color:#1f2937;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#1f2937 url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat;border:1px solid #4b5563;border-radius:.25rem;color:#e5e7eb;display:inline-block;font-size:1rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem 1.75rem .375rem .75rem;vertical-align:middle;width:100%}.custom-select:focus{border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0}.custom-select:focus::-ms-value{background-color:#1f2937;color:#e5e7eb}.custom-select[multiple],.custom-select[size]:not([size="1"]){background-image:none;height:auto;padding-right:.75rem}.custom-select:disabled{background-color:#e5e7eb;color:#4b5563}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #e5e7eb}.custom-select-sm{font-size:.875rem;height:calc(1.5em + .5rem + 2px);padding-bottom:.25rem;padding-left:.5rem;padding-top:.25rem}.custom-select-lg{font-size:1.25rem;height:calc(1.5em + 1rem + 2px);padding-bottom:.5rem;padding-left:1rem;padding-top:.5rem}.custom-file{display:inline-block;margin-bottom:0}.custom-file,.custom-file-input{height:calc(1.5em + .75rem + 2px);position:relative;width:100%}.custom-file-input{margin:0;opacity:0;overflow:hidden;z-index:2}.custom-file-input:focus~.custom-file-label{border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e5e7eb}.custom-file-input:lang(en)~.custom-file-label:after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]:after{content:attr(data-browse)}.custom-file-label{background-color:#1f2937;border:1px solid #4b5563;border-radius:.25rem;font-weight:400;height:calc(1.5em + .75rem + 2px);left:0;overflow:hidden;z-index:1}.custom-file-label,.custom-file-label:after{color:#e5e7eb;line-height:1.5;padding:.375rem .75rem;position:absolute;right:0;top:0}.custom-file-label:after{background-color:#e5e7eb;border-left:inherit;border-radius:0 .25rem .25rem 0;bottom:0;content:"Browse";display:block;height:calc(1.5em + .75rem);z-index:3}.custom-range{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;height:1.4rem;padding:0;width:100%}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #111827,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #111827,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #111827,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;margin-top:-.25rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#cbcbf0}.custom-range::-webkit-slider-runnable-track{background-color:#d1d5db;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-moz-range-thumb{-moz-appearance:none;appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#cbcbf0}.custom-range::-moz-range-track{background-color:#d1d5db;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-thumb{appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;margin-left:.2rem;margin-right:.2rem;margin-top:0;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#cbcbf0}.custom-range::-ms-track{background-color:transparent;border-color:transparent;border-width:.5rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-fill-lower,.custom-range::-ms-fill-upper{background-color:#d1d5db;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px}.custom-range:disabled::-webkit-slider-thumb{background-color:#6b7280}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#6b7280}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#6b7280}.custom-control-label:before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label:before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;flex-wrap:wrap;list-style:none;margin-bottom:0;padding-left:0}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#4b5563;cursor:default;pointer-events:none}.nav-tabs{border-bottom:1px solid #d1d5db}.nav-tabs .nav-link{background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem;margin-bottom:-1px}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e5e7eb #e5e7eb #d1d5db;isolation:isolate}.nav-tabs .nav-link.disabled{background-color:transparent;border-color:transparent;color:#4b5563}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{background-color:#111827;border-color:#d1d5db #d1d5db #111827;color:#374151}.nav-tabs .dropdown-menu{border-top-left-radius:0;border-top-right-radius:0;margin-top:-1px}.nav-pills .nav-link{background:none;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{background-color:#1f2937;color:#fff}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{padding:.5rem 1rem;position:relative}.navbar,.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between}.navbar-brand{display:inline-block;font-size:1.25rem;line-height:inherit;margin-right:1rem;padding-bottom:.3125rem;padding-top:.3125rem;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;list-style:none;margin-bottom:0;padding-left:0}.navbar-nav .nav-link{padding-left:0;padding-right:0}.navbar-nav .dropdown-menu{float:none;position:static}.navbar-text{display:inline-block;padding-bottom:.5rem;padding-top:.5rem}.navbar-collapse{align-items:center;flex-basis:100%;flex-grow:1}.navbar-toggler{background-color:transparent;border:1px solid transparent;border-radius:.25rem;font-size:1.25rem;line-height:1;padding:.25rem .75rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{background:50%/100% 100% no-repeat;content:"";display:inline-block;height:1.5em;vertical-align:middle;width:1.5em}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:1.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-left:0;padding-right:0}}@media (min-width:2px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:7.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-left:0;padding-right:0}}@media (min-width:8px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:8.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-left:0;padding-right:0}}@media (min-width:9px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:9.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-left:0;padding-right:0}}@media (min-width:10px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-left:0;padding-right:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{border-color:rgba(0,0,0,.1);color:rgba(0,0,0,.5)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{border-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{word-wrap:break-word;background-clip:border-box;background-color:#1f2937;border:1px solid rgba(0,0,0,.125);border-radius:6px;display:flex;flex-direction:column;min-width:0;position:relative}.card>hr{margin-left:0;margin-right:0}.card>.list-group{border-bottom:inherit;border-top:inherit}.card>.list-group:first-child{border-top-left-radius:5px;border-top-right-radius:5px;border-top-width:0}.card>.list-group:last-child{border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-bottom-width:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{background-color:#374151;border-bottom:1px solid rgba(0,0,0,.125);margin-bottom:0;padding:.75rem 1.25rem}.card-header:first-child{border-radius:5px 5px 0 0}.card-footer{background-color:#374151;border-top:1px solid rgba(0,0,0,.125);padding:.75rem 1.25rem}.card-footer:last-child{border-radius:0 0 5px 5px}.card-header-tabs{border-bottom:0;margin-bottom:-.75rem}.card-header-pills,.card-header-tabs{margin-left:-.625rem;margin-right:-.625rem}.card-img-overlay{border-radius:5px;bottom:0;left:0;padding:1.25rem;position:absolute;right:0;top:0}.card-img,.card-img-bottom,.card-img-top{flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:5px;border-top-right-radius:5px}.card-img,.card-img-bottom{border-bottom-left-radius:5px;border-bottom-right-radius:5px}.card-deck .card{margin-bottom:15px}@media (min-width:2px){.card-deck{display:flex;flex-flow:row wrap;margin-left:-15px;margin-right:-15px}.card-deck .card{flex:1 0 0%;margin-bottom:0;margin-left:15px;margin-right:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:2px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{border-left:0;margin-left:0}.card-group>.card:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:2px){.card-columns{-moz-column-count:3;column-count:3;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{background-color:#e5e7eb;border-radius:.25rem;display:flex;flex-wrap:wrap;list-style:none;margin-bottom:1rem;padding:.75rem 1rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item:before{color:#4b5563;content:"/";float:left;padding-right:.5rem}.breadcrumb-item+.breadcrumb-item:hover:before{text-decoration:underline;text-decoration:none}.breadcrumb-item.active{color:#4b5563}.pagination{border-radius:.25rem;display:flex;list-style:none;padding-left:0}.page-link{background-color:#fff;border:1px solid #d1d5db;color:#818cf8;display:block;line-height:1.25;margin-left:-1px;padding:.5rem .75rem;position:relative}.page-link:hover{background-color:#e5e7eb;border-color:#d1d5db;color:#a5b4fc;text-decoration:none;z-index:2}.page-link:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0;z-index:3}.page-item:first-child .page-link{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem;margin-left:0}.page-item:last-child .page-link{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.page-item.active .page-link{background-color:#4040c8;border-color:#4040c8;color:#fff;z-index:3}.page-item.disabled .page-link{background-color:#fff;border-color:#d1d5db;color:#4b5563;cursor:auto;pointer-events:none}.pagination-lg .page-link{font-size:1.25rem;line-height:1.5;padding:.75rem 1.5rem}.pagination-lg .page-item:first-child .page-link{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg .page-item:last-child .page-link{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm .page-link{font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.pagination-sm .page-item:first-child .page-link{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.badge{border-radius:.25rem;display:inline-block;font-size:.875rem;font-weight:600;line-height:1;padding:.25em .4em;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:baseline;white-space:nowrap}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{border-radius:10rem;padding-left:.6em;padding-right:.6em}.badge-primary{background-color:#4040c8;color:#fff}a.badge-primary:focus,a.badge-primary:hover{background-color:#3030a5;color:#fff}a.badge-primary.focus,a.badge-primary:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.5);outline:0}.badge-secondary{background-color:#4b5563;color:#fff}a.badge-secondary:focus,a.badge-secondary:hover{background-color:#353c46;color:#fff}a.badge-secondary.focus,a.badge-secondary:focus{box-shadow:0 0 0 .2rem rgba(75,85,99,.5);outline:0}.badge-success{background-color:#059669}a.badge-success:focus,a.badge-success:hover{background-color:#036546;color:#fff}a.badge-success.focus,a.badge-success:focus{box-shadow:0 0 0 .2rem rgba(5,150,105,.5);outline:0}.badge-info{background-color:#2563eb}a.badge-info:focus,a.badge-info:hover{background-color:#134cca;color:#fff}a.badge-info.focus,a.badge-info:focus{box-shadow:0 0 0 .2rem rgba(37,99,235,.5);outline:0}.badge-warning{background-color:#d97706}a.badge-warning:focus,a.badge-warning:hover{background-color:#a75c05;color:#fff}a.badge-warning.focus,a.badge-warning:focus{box-shadow:0 0 0 .2rem rgba(217,119,6,.5);outline:0}.badge-danger{background-color:#dc2626}a.badge-danger:focus,a.badge-danger:hover{background-color:#b21d1d;color:#fff}a.badge-danger.focus,a.badge-danger:focus{box-shadow:0 0 0 .2rem rgba(220,38,38,.5);outline:0}.badge-light{background-color:#f3f4f6;color:#111827}a.badge-light:focus,a.badge-light:hover{background-color:#d6d9e0;color:#111827}a.badge-light.focus,a.badge-light:focus{box-shadow:0 0 0 .2rem rgba(243,244,246,.5);outline:0}.badge-dark{background-color:#1f2937;color:#fff}a.badge-dark:focus,a.badge-dark:hover{background-color:#0d1116;color:#fff}a.badge-dark.focus,a.badge-dark:focus{box-shadow:0 0 0 .2rem rgba(31,41,55,.5);outline:0}.jumbotron{background-color:#e5e7eb;border-radius:6px;margin-bottom:2rem;padding:2rem 1rem}@media (min-width:2px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{border-radius:0;padding-left:0;padding-right:0}.alert{border:1px solid transparent;border-radius:.25rem;margin-bottom:1rem;padding:.75rem 1.25rem;position:relative}.alert-heading{color:inherit}.alert-link{font-weight:600}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{color:inherit;padding:.75rem 1.25rem;position:absolute;right:0;top:0;z-index:2}.alert-primary{background-color:#d9d9f4;border-color:#cacaf0;color:#212168}.alert-primary hr{border-top-color:#b6b6ea}.alert-primary .alert-link{color:#151541}.alert-secondary{background-color:#dbdde0;border-color:#cdcfd3;color:#272c33}.alert-secondary hr{border-top-color:#bfc2c7}.alert-secondary .alert-link{color:#111316}.alert-success{background-color:#cdeae1;border-color:#b9e2d5;color:#034e37}.alert-success hr{border-top-color:#a7dbca}.alert-success .alert-link{color:#011d14}.alert-info{background-color:#d3e0fb;border-color:#c2d3f9;color:#13337a}.alert-info hr{border-top-color:#abc2f7}.alert-info .alert-link{color:#0c214e}.alert-warning{background-color:#f7e4cd;border-color:#f4d9b9;color:#713e03}.alert-warning hr{border-top-color:#f1cda3}.alert-warning .alert-link{color:#3f2302}.alert-danger{background-color:#f8d4d4;border-color:#f5c2c2;color:#721414}.alert-danger hr{border-top-color:#f1acac}.alert-danger .alert-link{color:#470c0c}.alert-light{background-color:#fdfdfd;border-color:#fcfcfc;color:#7e7f80}.alert-light hr{border-top-color:#efefef}.alert-light .alert-link{color:#656666}.alert-dark{background-color:#d2d4d7;border-color:#c0c3c7;color:#10151d}.alert-dark hr{border-top-color:#b3b6bb}.alert-dark .alert-link{color:#000}@keyframes progress-bar-stripes{0%{background-position:1rem 0}to{background-position:0 0}}.progress{background-color:#e5e7eb;border-radius:.25rem;font-size:.75rem;height:1rem;line-height:0}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{background-color:#4040c8;color:#fff;flex-direction:column;justify-content:center;text-align:center;transition:width .6s ease;white-space:nowrap}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:1rem 1rem}.progress-bar-animated{animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.media{align-items:flex-start;display:flex}.media-body{flex:1}.list-group{border-radius:.25rem;display:flex;flex-direction:column;margin-bottom:0;padding-left:0}.list-group-item-action{color:#374151;text-align:inherit;width:100%}.list-group-item-action:focus,.list-group-item-action:hover{background-color:#f3f4f6;color:#374151;text-decoration:none;z-index:1}.list-group-item-action:active{background-color:#e5e7eb;color:#f3f4f6}.list-group-item{background-color:#fff;border:1px solid rgba(0,0,0,.125);display:block;padding:.75rem 1.25rem;position:relative}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{background-color:#fff;color:#4b5563;pointer-events:none}.list-group-item.active{background-color:#4040c8;border-color:#4040c8;color:#fff;z-index:2}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{border-top-width:1px;margin-top:-1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}@media (min-width:2px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:8px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-md>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:9px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:10px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{background-color:#cacaf0;color:#212168}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{background-color:#b6b6ea;color:#212168}.list-group-item-primary.list-group-item-action.active{background-color:#212168;border-color:#212168;color:#fff}.list-group-item-secondary{background-color:#cdcfd3;color:#272c33}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{background-color:#bfc2c7;color:#272c33}.list-group-item-secondary.list-group-item-action.active{background-color:#272c33;border-color:#272c33;color:#fff}.list-group-item-success{background-color:#b9e2d5;color:#034e37}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{background-color:#a7dbca;color:#034e37}.list-group-item-success.list-group-item-action.active{background-color:#034e37;border-color:#034e37;color:#fff}.list-group-item-info{background-color:#c2d3f9;color:#13337a}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{background-color:#abc2f7;color:#13337a}.list-group-item-info.list-group-item-action.active{background-color:#13337a;border-color:#13337a;color:#fff}.list-group-item-warning{background-color:#f4d9b9;color:#713e03}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{background-color:#f1cda3;color:#713e03}.list-group-item-warning.list-group-item-action.active{background-color:#713e03;border-color:#713e03;color:#fff}.list-group-item-danger{background-color:#f5c2c2;color:#721414}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{background-color:#f1acac;color:#721414}.list-group-item-danger.list-group-item-action.active{background-color:#721414;border-color:#721414;color:#fff}.list-group-item-light{background-color:#fcfcfc;color:#7e7f80}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{background-color:#efefef;color:#7e7f80}.list-group-item-light.list-group-item-action.active{background-color:#7e7f80;border-color:#7e7f80;color:#fff}.list-group-item-dark{background-color:#c0c3c7;color:#10151d}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{background-color:#b3b6bb;color:#10151d}.list-group-item-dark.list-group-item-action.active{background-color:#10151d;border-color:#10151d;color:#fff}.close{color:#000;float:right;font-size:1.5rem;font-weight:600;line-height:1;opacity:.5;text-shadow:0 1px 0 #fff}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{background-color:transparent;border:0;padding:0}a.close.disabled{pointer-events:none}.toast{background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border:1px solid rgba(0,0,0,.1);border-radius:.25rem;box-shadow:0 .25rem .75rem rgba(0,0,0,.1);flex-basis:350px;font-size:.875rem;max-width:350px;opacity:0}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{align-items:center;background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px);color:#4b5563;display:flex;padding:.25rem .75rem}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{display:none;height:100%;left:0;outline:0;overflow:hidden;position:fixed;top:0;width:100%;z-index:1050}.modal-dialog{margin:.5rem;pointer-events:none;position:relative;width:auto}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{align-items:center;display:flex;min-height:calc(100% - 1rem)}.modal-dialog-centered:before{content:"";display:block;height:calc(100vh - 1rem);height:-moz-min-content;height:min-content}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;height:100%;justify-content:center}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable:before{content:none}.modal-content{background-clip:padding-box;background-color:#1f2937;border:1px solid rgba(0,0,0,.2);border-radius:6px;display:flex;flex-direction:column;outline:0;pointer-events:auto;position:relative;width:100%}.modal-backdrop{background-color:#4b5563;height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:1040}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{align-items:flex-start;border-bottom:1px solid #4b5563;border-top-left-radius:5px;border-top-right-radius:5px;display:flex;justify-content:space-between;padding:1rem}.modal-header .close{margin:-1rem -1rem -1rem auto;padding:1rem}.modal-title{line-height:1.5;margin-bottom:0}.modal-body{flex:1 1 auto;padding:1rem;position:relative}.modal-footer{align-items:center;border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-top:1px solid #4b5563;display:flex;flex-wrap:wrap;justify-content:flex-end;padding:.75rem}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{height:50px;overflow:scroll;position:absolute;top:-9999px;width:50px}@media (min-width:2px){.modal-dialog{margin:1.75rem auto;max-width:500px}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered:before{height:calc(100vh - 3.5rem);height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:9px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:10px){.modal-xl{max-width:1140px}}.tooltip{word-wrap:break-word;display:block;font-family:Figtree,sans-serif;font-size:.875rem;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;margin:0;opacity:0;position:absolute;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;z-index:1070}.tooltip.show{opacity:.9}.tooltip .arrow{display:block;height:.4rem;position:absolute;width:.8rem}.tooltip .arrow:before{border-color:transparent;border-style:solid;content:"";position:absolute}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow:before,.bs-tooltip-top .arrow:before{border-top-color:#000;border-width:.4rem .4rem 0;top:0}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{height:.8rem;left:0;width:.4rem}.bs-tooltip-auto[x-placement^=right] .arrow:before,.bs-tooltip-right .arrow:before{border-right-color:#000;border-width:.4rem .4rem .4rem 0;right:0}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.bs-tooltip-bottom .arrow:before{border-bottom-color:#000;border-width:0 .4rem .4rem;bottom:0}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{height:.8rem;right:0;width:.4rem}.bs-tooltip-auto[x-placement^=left] .arrow:before,.bs-tooltip-left .arrow:before{border-left-color:#000;border-width:.4rem 0 .4rem .4rem;left:0}.tooltip-inner{background-color:#000;border-radius:.25rem;color:#fff;max-width:200px;padding:.25rem .5rem;text-align:center}.popover{word-wrap:break-word;background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:6px;font-family:Figtree,sans-serif;font-size:.875rem;font-style:normal;font-weight:400;left:0;letter-spacing:normal;line-break:auto;line-height:1.5;max-width:276px;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;top:0;white-space:normal;word-break:normal;word-spacing:normal;z-index:1060}.popover,.popover .arrow{display:block;position:absolute}.popover .arrow{height:.5rem;margin:0 6px;width:1rem}.popover .arrow:after,.popover .arrow:before{border-color:transparent;border-style:solid;content:"";display:block;position:absolute}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow:before,.bs-popover-top>.arrow:before{border-top-color:rgba(0,0,0,.25);border-width:.5rem .5rem 0;bottom:0}.bs-popover-auto[x-placement^=top]>.arrow:after,.bs-popover-top>.arrow:after{border-top-color:#fff;border-width:.5rem .5rem 0;bottom:1px}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{height:1rem;left:calc(-.5rem - 1px);margin:6px 0;width:.5rem}.bs-popover-auto[x-placement^=right]>.arrow:before,.bs-popover-right>.arrow:before{border-right-color:rgba(0,0,0,.25);border-width:.5rem .5rem .5rem 0;left:0}.bs-popover-auto[x-placement^=right]>.arrow:after,.bs-popover-right>.arrow:after{border-right-color:#fff;border-width:.5rem .5rem .5rem 0;left:1px}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow:before,.bs-popover-bottom>.arrow:before{border-bottom-color:rgba(0,0,0,.25);border-width:0 .5rem .5rem;top:0}.bs-popover-auto[x-placement^=bottom]>.arrow:after,.bs-popover-bottom>.arrow:after{border-bottom-color:#fff;border-width:0 .5rem .5rem;top:1px}.bs-popover-auto[x-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{border-bottom:1px solid #f7f7f7;content:"";display:block;left:50%;margin-left:-.5rem;position:absolute;top:0;width:1rem}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{height:1rem;margin:6px 0;right:calc(-.5rem - 1px);width:.5rem}.bs-popover-auto[x-placement^=left]>.arrow:before,.bs-popover-left>.arrow:before{border-left-color:rgba(0,0,0,.25);border-width:.5rem 0 .5rem .5rem;right:0}.bs-popover-auto[x-placement^=left]>.arrow:after,.bs-popover-left>.arrow:after{border-left-color:#fff;border-width:.5rem 0 .5rem .5rem;right:1px}.popover-header{background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:5px;border-top-right-radius:5px;font-size:1rem;margin-bottom:0;padding:.5rem .75rem}.popover-header:empty{display:none}.popover-body{color:#f3f4f6;padding:.5rem .75rem}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{overflow:hidden;position:relative;width:100%}.carousel-inner:after{clear:both;content:"";display:block}.carousel-item{backface-visibility:hidden;display:none;float:left;margin-right:-100%;position:relative;transition:transform .6s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transform:none;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{opacity:1;z-index:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0;transition:opacity 0s .6s;z-index:0}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{align-items:center;background:none;border:0;bottom:0;color:#fff;display:flex;justify-content:center;opacity:.5;padding:0;position:absolute;text-align:center;top:0;transition:opacity .15s ease;width:15%;z-index:1}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;opacity:.9;outline:0;text-decoration:none}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{background:50%/100% 100% no-repeat;display:inline-block;height:20px;width:20px}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m5.25 0-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m2.75 0-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{bottom:0;display:flex;justify-content:center;left:0;list-style:none;margin-left:15%;margin-right:15%;padding-left:0;position:absolute;right:0;z-index:15}.carousel-indicators li{background-clip:padding-box;background-color:#fff;border-bottom:10px solid transparent;border-top:10px solid transparent;box-sizing:content-box;cursor:pointer;flex:0 1 auto;height:3px;margin-left:3px;margin-right:3px;opacity:.5;text-indent:-999px;transition:opacity .6s ease;width:30px}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{bottom:20px;color:#fff;left:15%;padding-bottom:20px;padding-top:20px;position:absolute;right:15%;text-align:center;z-index:10}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{animation:spinner-border .75s linear infinite;border:.25em solid;border-radius:50%;border-right:.25em solid transparent;display:inline-block;height:2rem;vertical-align:-.125em;width:2rem}.spinner-border-sm{border-width:.2em;height:1rem;width:1rem}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{animation:spinner-grow .75s linear infinite;background-color:currentcolor;border-radius:50%;display:inline-block;height:2rem;opacity:0;vertical-align:-.125em;width:2rem}.spinner-grow-sm{height:1rem;width:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#4040c8!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#3030a5!important}.bg-secondary{background-color:#4b5563!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#353c46!important}.bg-success{background-color:#059669!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#036546!important}.bg-info{background-color:#2563eb!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#134cca!important}.bg-warning{background-color:#d97706!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#a75c05!important}.bg-danger{background-color:#dc2626!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#b21d1d!important}.bg-light{background-color:#f3f4f6!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#d6d9e0!important}.bg-dark{background-color:#1f2937!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#0d1116!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #4b5563!important}.border-top{border-top:1px solid #4b5563!important}.border-right{border-right:1px solid #4b5563!important}.border-bottom{border-bottom:1px solid #4b5563!important}.border-left{border-left:1px solid #4b5563!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#4040c8!important}.border-secondary{border-color:#4b5563!important}.border-success{border-color:#059669!important}.border-info{border-color:#2563eb!important}.border-warning{border-color:#d97706!important}.border-danger{border-color:#dc2626!important}.border-light{border-color:#f3f4f6!important}.border-dark{border-color:#1f2937!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important}.rounded-lg{border-radius:6px!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix:after{clear:both;content:"";display:block}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:2px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:8px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:9px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:10px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{display:block;overflow:hidden;padding:0;position:relative;width:100%}.embed-responsive:before{content:"";display:block}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{border:0;bottom:0;height:100%;left:0;position:absolute;top:0;width:100%}.embed-responsive-21by9:before{padding-top:42.85714286%}.embed-responsive-16by9:before{padding-top:56.25%}.embed-responsive-4by3:before{padding-top:75%}.embed-responsive-1by1:before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:2px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:8px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:9px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:10px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:2px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:8px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:9px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:10px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.fixed-top{top:0}.fixed-bottom,.fixed-top{left:0;position:fixed;right:0;z-index:1030}.fixed-bottom{bottom:0}@supports (position:sticky){.sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;overflow:visible;position:static;white-space:normal;width:auto}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:2px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:8px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:9px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:10px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link:after{background-color:transparent;bottom:0;content:"";left:0;pointer-events:auto;position:absolute;right:0;top:0;z-index:1}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:2px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:8px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:9px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:10px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:600!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#4040c8!important}a.text-primary:focus,a.text-primary:hover{color:#2a2a92!important}.text-secondary{color:#4b5563!important}a.text-secondary:focus,a.text-secondary:hover{color:#2a3037!important}.text-success{color:#059669!important}a.text-success:focus,a.text-success:hover{color:#034c35!important}.text-info{color:#2563eb!important}a.text-info:focus,a.text-info:hover{color:#1043b3!important}.text-warning{color:#d97706!important}a.text-warning:focus,a.text-warning:hover{color:#8f4e04!important}.text-danger{color:#dc2626!important}a.text-danger:focus,a.text-danger:hover{color:#9c1919!important}.text-light{color:#f3f4f6!important}a.text-light:focus,a.text-light:hover{color:#c7ccd5!important}.text-dark{color:#1f2937!important}a.text-dark:focus,a.text-dark:hover{color:#030506!important}.text-body{color:#f3f4f6!important}.text-muted{color:#9ca3af!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:hsla(0,0%,100%,.5)!important}.text-hide{background-color:transparent;border:0;color:transparent;font:0/0 a;text-shadow:none}.text-decoration-none{text-decoration:none!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,:after,:before{box-shadow:none!important;text-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #6b7280}blockquote,img,pre,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}.container,body{min-width:9px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #d1d5db!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#374151}.table .thead-dark th{border-color:#374151;color:inherit}}.vjs-tree{color:#bfc7d5!important;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.vjs-tree .vjs-tree__content{border-left:1px dotted hsla(0,0%,80%,.28)!important}.vjs-tree .vjs-tree__node{cursor:pointer}.vjs-tree .vjs-tree__node:hover{color:#20a0ff}.vjs-tree .vjs-checkbox{left:-30px;position:absolute}.vjs-tree .vjs-value__boolean,.vjs-tree .vjs-value__null,.vjs-tree .vjs-value__number{color:#a291f5!important}.vjs-tree .vjs-value__string{color:#c3e88d!important}.vjs-tree .vjs-key{color:#c3cbd3!important}.hljs-addition,.hljs-attr,.hljs-keyword,.hljs-selector-tag{color:#13ce66}.hljs-bullet,.hljs-meta,.hljs-name,.hljs-string,.hljs-symbol,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable{color:#c3e88d}.hljs-comment,.hljs-deletion,.hljs-quote{color:#bfcbd9}.hljs-literal,.hljs-number,.hljs-title{color:#a291f5!important}body{padding-bottom:20px}.container{max-width:1440px}html{min-width:1140px}[v-cloak]{display:none}svg.icon{height:1rem;width:1rem}.header{border-bottom:1px solid #374151}.header .logo{color:#e5e7eb;text-decoration:none}.header .logo svg{height:1.7rem;width:1.7rem}.sidebar .nav-item a{border-radius:6px;color:#9ca3af;margin-bottom:4px;padding:.5rem .75rem}.sidebar .nav-item a svg{fill:#6b7280;height:1.25rem;margin-right:15px;width:1.25rem}.sidebar .nav-item a:hover{background-color:#1f2937;color:#d1d5db}.sidebar .nav-item a.active{background-color:#1f2937;color:#818cf8}.sidebar .nav-item a.active svg{fill:#6366f1}.card{border:none;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1)}.card .bottom-radius{border-bottom-left-radius:6px;border-bottom-right-radius:6px}.card .card-header{background-color:#374151;border-bottom:none;min-height:60px;padding-bottom:.7rem;padding-top:.7rem}.card .card-header .btn-group .btn{padding:.2rem .5rem}.card .card-header .form-control-with-icon{position:relative}.card .card-header .form-control-with-icon .icon-wrapper{align-items:center;bottom:0;display:flex;justify-content:center;left:.75rem;position:absolute;top:0}.card .card-header .form-control-with-icon .icon-wrapper .icon{fill:#9ca3af}.card .card-header .form-control-with-icon .form-control{border-radius:9999px;font-size:.875rem;padding-left:2.25rem}.card .table td,.card .table th{padding:.75rem 1.25rem}.card .table th{background-color:#1f2937;border-bottom:0;font-size:.875rem;padding:.5rem 1.25rem}.card .table:not(.table-borderless) td{border-top:1px solid #374151}.card .table.penultimate-column-right td:nth-last-child(2),.card .table.penultimate-column-right th:nth-last-child(2){text-align:right}.card .table td.table-fit,.card .table th.table-fit{white-space:nowrap;width:1%}.fill-text-color{fill:#f3f4f6}.fill-danger{fill:#dc2626}.fill-warning{fill:#d97706}.fill-info{fill:#2563eb}.fill-success{fill:#059669}.fill-primary{fill:#4040c8}button:hover .fill-primary{fill:#fff}.btn-outline-primary.active .fill-primary{fill:#111827}.btn-outline-primary:not(:disabled):not(.disabled).active:focus{box-shadow:none!important}.btn-muted{background:#1f2937;color:#9ca3af}.btn-muted:focus,.btn-muted:hover{background:#374151;color:#d1d5db}.btn-muted.active{background:#4040c8;color:#fff}.badge-secondary{background:#d1d5db;color:#374151}.badge-success{background:#10b981;color:#fff}.badge-info{background:#3b82f6;color:#fff}.badge-warning{background:#f59e0b;color:#fff}.badge-danger{background:#ef4444;color:#fff}.control-action svg{fill:#6b7280;height:1.2rem;width:1.2rem}.control-action svg:hover{fill:#818cf8}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.spin{animation:spin 2s linear infinite}.card .nav-pills{background:#374151}.card .nav-pills .nav-link{border-radius:0;color:#9ca3af;font-size:.9rem;padding:.75rem 1.25rem}.card .nav-pills .nav-link:focus,.card .nav-pills .nav-link:hover{color:#e5e7eb}.card .nav-pills .nav-link.active{background:none;border-bottom:2px solid #a5b4fc;color:#a5b4fc}.list-enter-active:not(.dontanimate){transition:background 1s linear}.list-enter:not(.dontanimate),.list-leave-to:not(.dontanimate){background:#312e81}.code-bg .list-enter:not(.dontanimate),.code-bg .list-leave-to:not(.dontanimate){background:#4b5563}#indexScreen td{vertical-align:middle!important}.card-bg-secondary{background:#1f2937}.code-bg{background:#292d3e}.disabled-watcher{background:#dc2626;color:#fff;padding:.75rem}.copy-to-clipboard{--tw-text-opacity:1;color:rgb(231 232 242/var(--tw-text-opacity));opacity:.7;outline:2px solid transparent;outline-offset:2px;position:absolute;right:0;top:0;z-index:10} diff --git a/public/vendor/telescope/app.css b/public/vendor/telescope/app.css index fac021b32..1f6375bf1 100644 --- a/public/vendor/telescope/app.css +++ b/public/vendor/telescope/app.css @@ -1,8 +1,7 @@ @charset "UTF-8"; - /*! * Bootstrap v4.6.2 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#4b5563;--gray-dark:#1f2937;--primary:#4040c8;--secondary:#4b5563;--success:#059669;--info:#2563eb;--warning:#d97706;--danger:#dc2626;--light:#f3f4f6;--dark:#1f2937;--breakpoint-xs:0;--breakpoint-sm:2px;--breakpoint-md:8px;--breakpoint-lg:9px;--breakpoint-xl:10px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);font-family:sans-serif;line-height:1.15}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{background-color:#f3f4f6;color:#111827;font-family:Figtree,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;margin:0;text-align:left}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;margin-top:0}p{margin-bottom:1rem;margin-top:0}abbr[data-original-title],abbr[title]{border-bottom:0;cursor:help;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:600}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{background-color:transparent;color:#6366f1;text-decoration:none}a:hover{color:#4f46e5;text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{-ms-overflow-style:scrollbar;margin-bottom:1rem;margin-top:0;overflow:auto}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{caption-side:bottom;color:#6b7280;padding-bottom:.75rem;padding-top:.75rem;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;margin:0}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{border:0;margin:0;min-width:0;padding:0}legend{color:inherit;display:block;font-size:1.5rem;line-height:inherit;margin-bottom:.5rem;max-width:100%;padding:0;white-space:normal;width:100%}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:none;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}output{display:inline-block}summary{cursor:pointer;display:list-item}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.2;margin-bottom:.5rem}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{border:0;border-top:1px solid rgba(0,0,0,.1);margin-bottom:1rem;margin-top:1rem}.small,small{font-size:.875em;font-weight:400}.mark,mark{background-color:#fcf8e3;padding:.2em}.list-inline,.list-unstyled{list-style:none;padding-left:0}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{font-size:1.25rem;margin-bottom:1rem}.blockquote-footer{color:#4b5563;display:block;font-size:.875em}.blockquote-footer:before{content:"โ€”ย "}.img-fluid,.img-thumbnail{height:auto;max-width:100%}.img-thumbnail{background-color:#f3f4f6;border:1px solid #d1d5db;border-radius:.25rem;padding:.25rem}.figure{display:inline-block}.figure-img{line-height:1;margin-bottom:.5rem}.figure-caption{color:#4b5563;font-size:90%}code{word-wrap:break-word;color:#e83e8c;font-size:87.5%}a>code{color:inherit}kbd{background-color:#111827;border-radius:.2rem;color:#fff;font-size:87.5%;padding:.2rem .4rem}kbd kbd{font-size:100%;font-weight:600;padding:0}pre{color:#111827;display:block;font-size:87.5%}pre code{color:inherit;font-size:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px;width:100%}@media (min-width:2px){.container,.container-sm{max-width:1137px}}@media (min-width:8px){.container,.container-md,.container-sm{max-width:1138px}}@media (min-width:9px){.container,.container-lg,.container-md,.container-sm{max-width:1139px}}@media (min-width:10px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:flex;flex-wrap:wrap;margin-left:-15px;margin-right:-15px}.no-gutters{margin-left:0;margin-right:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-left:0;padding-right:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{padding-left:15px;padding-right:15px;position:relative;width:100%}.col{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-auto{flex:0 0 auto;max-width:100%;width:auto}.col-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}@media (min-width:2px){.col-sm{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-auto{flex:0 0 auto;max-width:100%;width:auto}.col-sm-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-sm-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-sm-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-sm-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-sm-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}}@media (min-width:8px){.col-md{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-auto{flex:0 0 auto;max-width:100%;width:auto}.col-md-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-md-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-md-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-md-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-md-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}}@media (min-width:9px){.col-lg{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-auto{flex:0 0 auto;max-width:100%;width:auto}.col-lg-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-lg-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-lg-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-lg-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-lg-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}}@media (min-width:10px){.col-xl{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-auto{flex:0 0 auto;max-width:100%;width:auto}.col-xl-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-xl-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-xl-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-xl-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-xl-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}}.table{color:#111827;margin-bottom:1rem;width:100%}.table td,.table th{border-top:1px solid #e5e7eb;padding:.75rem;vertical-align:top}.table thead th{border-bottom:2px solid #e5e7eb;vertical-align:bottom}.table tbody+tbody{border-top:2px solid #e5e7eb}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #e5e7eb}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:#f3f4f6;color:#111827}.table-primary,.table-primary>td,.table-primary>th{background-color:#cacaf0}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#9c9ce2}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#b6b6ea}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#cdcfd3}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#a1a7ae}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#bfc2c7}.table-success,.table-success>td,.table-success>th{background-color:#b9e2d5}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#7dc8b1}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#a7dbca}.table-info,.table-info>td,.table-info>th{background-color:#c2d3f9}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#8eaef5}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abc2f7}.table-warning,.table-warning>td,.table-warning>th{background-color:#f4d9b9}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ebb87e}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#f1cda3}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c2c2}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed8e8e}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1acac}.table-light,.table-light>td,.table-light>th{background-color:#fcfcfc}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#f9f9fa}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#efefef}.table-dark,.table-dark>td,.table-dark>th{background-color:#c0c3c7}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#8b9097}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b3b6bb}.table-active,.table-active>td,.table-active>th{background-color:#f3f4f6}.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:#e4e7eb}.table .thead-dark th{background-color:#1f2937;border-color:#2d3b4f;color:#fff}.table .thead-light th{background-color:#e5e7eb;border-color:#e5e7eb;color:#374151}.table-dark{background-color:#1f2937;color:#fff}.table-dark td,.table-dark th,.table-dark thead th{border-color:#2d3b4f}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:hsla(0,0%,100%,.05)}.table-dark.table-hover tbody tr:hover{background-color:hsla(0,0%,100%,.075);color:#fff}@media (max-width:1.98px){.table-responsive-sm{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:7.98px){.table-responsive-md{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-md>.table-bordered{border:0}}@media (max-width:8.98px){.table-responsive-lg{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:9.98px){.table-responsive-xl{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive>.table-bordered{border:0}.form-control{background-clip:padding-box;background-color:#fff;border:1px solid #d1d5db;border-radius:.25rem;color:#1f2937;display:block;font-size:1rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{background-color:#fff;border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25);color:#1f2937;outline:0}.form-control::-moz-placeholder{color:#4b5563;opacity:1}.form-control::placeholder{color:#4b5563;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e5e7eb;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #1f2937}select.form-control:focus::-ms-value{background-color:#fff;color:#1f2937}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{font-size:inherit;line-height:1.5;margin-bottom:0;padding-bottom:calc(.375rem + 1px);padding-top:calc(.375rem + 1px)}.col-form-label-lg{font-size:1.25rem;line-height:1.5;padding-bottom:calc(.5rem + 1px);padding-top:calc(.5rem + 1px)}.col-form-label-sm{font-size:.875rem;line-height:1.5;padding-bottom:calc(.25rem + 1px);padding-top:calc(.25rem + 1px)}.form-control-plaintext{background-color:transparent;border:solid transparent;border-width:1px 0;color:#111827;display:block;font-size:1rem;line-height:1.5;margin-bottom:0;padding:.375rem 0;width:100%}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-left:0;padding-right:0}.form-control-sm{border-radius:.2rem;font-size:.875rem;height:calc(1.5em + .5rem + 2px);line-height:1.5;padding:.25rem .5rem}.form-control-lg{border-radius:6px;font-size:1.25rem;height:calc(1.5em + 1rem + 2px);line-height:1.5;padding:.5rem 1rem}select.form-control[multiple],select.form-control[size],textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-left:-5px;margin-right:-5px}.form-row>.col,.form-row>[class*=col-]{padding-left:5px;padding-right:5px}.form-check{display:block;padding-left:1.25rem;position:relative}.form-check-input{margin-left:-1.25rem;margin-top:.3rem;position:absolute}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6b7280}.form-check-label{margin-bottom:0}.form-check-inline{align-items:center;display:inline-flex;margin-right:.75rem;padding-left:0}.form-check-inline .form-check-input{margin-left:0;margin-right:.3125rem;margin-top:0;position:static}.valid-feedback{color:#059669;display:none;font-size:.875em;margin-top:.25rem;width:100%}.valid-tooltip{background-color:rgba(5,150,105,.9);border-radius:.25rem;color:#fff;display:none;font-size:.875rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23059669' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#059669;padding-right:calc(1.5em + .75rem)!important}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-valid,.was-validated .custom-select:valid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23059669' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#059669;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#059669}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#059669}.custom-control-input.is-valid~.custom-control-label:before,.was-validated .custom-control-input:valid~.custom-control-label:before{border-color:#059669}.custom-control-input.is-valid:checked~.custom-control-label:before,.was-validated .custom-control-input:valid:checked~.custom-control-label:before{background-color:#07c78c;border-color:#07c78c}.custom-control-input.is-valid:focus~.custom-control-label:before,.was-validated .custom-control-input:valid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label:before{border-color:#059669}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#059669}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.invalid-feedback{color:#dc2626;display:none;font-size:.875em;margin-top:.25rem;width:100%}.invalid-tooltip{background-color:rgba(220,38,38,.9);border-radius:.25rem;color:#fff;display:none;font-size:.875rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc2626'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc2626' stroke='none'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#dc2626;padding-right:calc(1.5em + .75rem)!important}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc2626'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc2626' stroke='none'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#dc2626;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc2626}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc2626}.custom-control-input.is-invalid~.custom-control-label:before,.was-validated .custom-control-input:invalid~.custom-control-label:before{border-color:#dc2626}.custom-control-input.is-invalid:checked~.custom-control-label:before,.was-validated .custom-control-input:invalid:checked~.custom-control-label:before{background-color:#e35252;border-color:#e35252}.custom-control-input.is-invalid:focus~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label:before{border-color:#dc2626}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc2626}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.form-inline{align-items:center;display:flex;flex-flow:row wrap}.form-inline .form-check{width:100%}@media (min-width:2px){.form-inline label{justify-content:center}.form-inline .form-group,.form-inline label{align-items:center;display:flex;margin-bottom:0}.form-inline .form-group{flex:0 0 auto;flex-flow:row wrap}.form-inline .form-control{display:inline-block;vertical-align:middle;width:auto}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{align-items:center;display:flex;justify-content:center;padding-left:0;width:auto}.form-inline .form-check-input{flex-shrink:0;margin-left:0;margin-right:.25rem;margin-top:0;position:relative}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;color:#111827;display:inline-block;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#111827;text-decoration:none}.btn.focus,.btn:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-primary.focus,.btn-primary:focus,.btn-primary:hover{background-color:#3232af;border-color:#3030a5;color:#fff}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 0 rgba(93,93,208,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{background-color:#3030a5;border-color:#2d2d9b;color:#fff}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(93,93,208,.5)}.btn-secondary{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:hover{background-color:#3b424d;border-color:#353c46;color:#fff}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 0 hsla(213,9%,44%,.5)}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{background-color:#353c46;border-color:#30363f;color:#fff}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 0 hsla(213,9%,44%,.5)}.btn-success{background-color:#059669;border-color:#059669;color:#fff}.btn-success.focus,.btn-success:focus,.btn-success:hover{background-color:#04714f;border-color:#036546;color:#fff}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 0 rgba(43,166,128,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#059669;border-color:#059669;color:#fff}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{background-color:#036546;border-color:#03583e;color:#fff}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(43,166,128,.5)}.btn-info{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-info.focus,.btn-info:focus,.btn-info:hover{background-color:#1451d6;border-color:#134cca;color:#fff}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 0 rgba(70,122,238,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{background-color:#134cca;border-color:#1248bf;color:#fff}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(70,122,238,.5)}.btn-warning{background-color:#d97706;border-color:#d97706;color:#fff}.btn-warning.focus,.btn-warning:focus,.btn-warning:hover{background-color:#b46305;border-color:#a75c05;color:#fff}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 0 rgba(223,139,43,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#d97706;border-color:#d97706;color:#fff}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{background-color:#a75c05;border-color:#9b5504;color:#fff}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(223,139,43,.5)}.btn-danger{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-danger.focus,.btn-danger:focus,.btn-danger:hover{background-color:#bd1f1f;border-color:#b21d1d;color:#fff}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 0 rgba(225,71,71,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{background-color:#b21d1d;border-color:#a71b1b;color:#fff}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(225,71,71,.5)}.btn-light{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-light.focus,.btn-light:focus,.btn-light:hover{background-color:#dde0e6;border-color:#d6d9e0;color:#111827}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 0 hsla(220,7%,83%,.5)}.btn-light.disabled,.btn-light:disabled{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{background-color:#d6d9e0;border-color:#cfd3db;color:#111827}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 0 hsla(220,7%,83%,.5)}.btn-dark{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-dark.focus,.btn-dark:focus,.btn-dark:hover{background-color:#11171f;border-color:#0d1116;color:#fff}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 0 rgba(65,73,85,.5)}.btn-dark.disabled,.btn-dark:disabled{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{background-color:#0d1116;border-color:#080b0e;color:#fff}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(65,73,85,.5)}.btn-outline-primary{border-color:#4040c8;color:#4040c8}.btn-outline-primary:hover{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 0 rgba(64,64,200,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{background-color:transparent;color:#4040c8}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(64,64,200,.5)}.btn-outline-secondary{border-color:#4b5563;color:#4b5563}.btn-outline-secondary:hover{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 0 rgba(75,85,99,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{background-color:transparent;color:#4b5563}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(75,85,99,.5)}.btn-outline-success{border-color:#059669;color:#059669}.btn-outline-success:hover{background-color:#059669;border-color:#059669;color:#fff}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 0 rgba(5,150,105,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{background-color:transparent;color:#059669}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{background-color:#059669;border-color:#059669;color:#fff}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(5,150,105,.5)}.btn-outline-info{border-color:#2563eb;color:#2563eb}.btn-outline-info:hover{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 0 rgba(37,99,235,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{background-color:transparent;color:#2563eb}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(37,99,235,.5)}.btn-outline-warning{border-color:#d97706;color:#d97706}.btn-outline-warning:hover{background-color:#d97706;border-color:#d97706;color:#fff}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 0 rgba(217,119,6,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{background-color:transparent;color:#d97706}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{background-color:#d97706;border-color:#d97706;color:#fff}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(217,119,6,.5)}.btn-outline-danger{border-color:#dc2626;color:#dc2626}.btn-outline-danger:hover{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 0 rgba(220,38,38,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{background-color:transparent;color:#dc2626}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(220,38,38,.5)}.btn-outline-light{border-color:#f3f4f6;color:#f3f4f6}.btn-outline-light:hover{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 0 rgba(243,244,246,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{background-color:transparent;color:#f3f4f6}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(243,244,246,.5)}.btn-outline-dark{border-color:#1f2937;color:#1f2937}.btn-outline-dark:hover{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 0 rgba(31,41,55,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{background-color:transparent;color:#1f2937}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(31,41,55,.5)}.btn-link{color:#6366f1;font-weight:400;text-decoration:none}.btn-link:hover{color:#4f46e5}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#4b5563;pointer-events:none}.btn-group-lg>.btn,.btn-lg{border-radius:6px;font-size:1.25rem;line-height:1.5;padding:.5rem 1rem}.btn-group-sm>.btn,.btn-sm{border-radius:.2rem;font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;position:relative;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{height:auto;transition:width .35s ease;width:0}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{border-bottom:0;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:.3em solid;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;color:#111827;display:none;float:left;font-size:1rem;left:0;list-style:none;margin:.125rem 0 0;min-width:10rem;padding:.5rem 0;position:absolute;text-align:left;top:100%;z-index:1000}.dropdown-menu-left{left:0;right:auto}.dropdown-menu-right{left:auto;right:0}@media (min-width:2px){.dropdown-menu-sm-left{left:0;right:auto}.dropdown-menu-sm-right{left:auto;right:0}}@media (min-width:8px){.dropdown-menu-md-left{left:0;right:auto}.dropdown-menu-md-right{left:auto;right:0}}@media (min-width:9px){.dropdown-menu-lg-left{left:0;right:auto}.dropdown-menu-lg-right{left:auto;right:0}}@media (min-width:10px){.dropdown-menu-xl-left{left:0;right:auto}.dropdown-menu-xl-right{left:auto;right:0}}.dropup .dropdown-menu{bottom:100%;margin-bottom:.125rem;margin-top:0;top:auto}.dropup .dropdown-toggle:after{border-bottom:.3em solid;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:0;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-menu{left:100%;margin-left:.125rem;margin-top:0;right:auto;top:0}.dropright .dropdown-toggle:after{border-bottom:.3em solid transparent;border-left:.3em solid;border-right:0;border-top:.3em solid transparent;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropright .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-toggle:after{vertical-align:0}.dropleft .dropdown-menu{left:auto;margin-right:.125rem;margin-top:0;right:100%;top:0}.dropleft .dropdown-toggle:after{content:"";display:inline-block;display:none;margin-left:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:before{border-bottom:.3em solid transparent;border-right:.3em solid;border-top:.3em solid transparent;content:"";display:inline-block;margin-right:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:empty:after{margin-left:0}.dropleft .dropdown-toggle:before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{bottom:auto;right:auto}.dropdown-divider{border-top:1px solid #e5e7eb;height:0;margin:.5rem 0;overflow:hidden}.dropdown-item{background-color:transparent;border:0;clear:both;color:#374151;display:block;font-weight:400;padding:.25rem 1.5rem;text-align:inherit;white-space:nowrap;width:100%}.dropdown-item:focus,.dropdown-item:hover{background-color:#e5e7eb;color:#090d15;text-decoration:none}.dropdown-item.active,.dropdown-item:active{background-color:#4040c8;color:#fff;text-decoration:none}.dropdown-item.disabled,.dropdown-item:disabled{background-color:transparent;color:#6b7280;pointer-events:none}.dropdown-menu.show{display:block}.dropdown-header{color:#4b5563;display:block;font-size:.875rem;margin-bottom:0;padding:.5rem 1.5rem;white-space:nowrap}.dropdown-item-text{color:#374151;display:block;padding:.25rem 1.5rem}.btn-group,.btn-group-vertical{display:inline-flex;position:relative;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{flex:1 1 auto;position:relative}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.dropdown-toggle-split{padding-left:.5625rem;padding-right:.5625rem}.dropdown-toggle-split:after,.dropright .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropleft .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-left:.375rem;padding-right:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-left:.75rem;padding-right:.75rem}.btn-group-vertical{align-items:flex-start;flex-direction:column;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-left-radius:0;border-bottom-right-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{clip:rect(0,0,0,0);pointer-events:none;position:absolute}.input-group{align-items:stretch;display:flex;flex-wrap:wrap;position:relative;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{flex:1 1 auto;margin-bottom:0;min-width:0;position:relative;width:1%}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group>.custom-file{align-items:center;display:flex}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label:after{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-bottom-left-radius:0;border-top-left-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label:after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3),.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label:after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.input-group-append,.input-group-prepend{display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{align-items:center;background-color:#e5e7eb;border:1px solid #d1d5db;border-radius:.25rem;color:#1f2937;display:flex;font-size:1rem;font-weight:400;line-height:1.5;margin-bottom:0;padding:.375rem .75rem;text-align:center;white-space:nowrap}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{border-radius:6px;font-size:1.25rem;line-height:1.5;padding:.5rem 1rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{border-radius:.2rem;font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-bottom-left-radius:0;border-top-left-radius:0}.custom-control{display:block;min-height:1.5rem;padding-left:1.5rem;position:relative;-webkit-print-color-adjust:exact;print-color-adjust:exact;z-index:1}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{height:1.25rem;left:0;opacity:0;position:absolute;width:1rem;z-index:-1}.custom-control-input:checked~.custom-control-label:before{background-color:#4040c8;border-color:#4040c8;color:#fff}.custom-control-input:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(64,64,200,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label:before{border-color:#a3a3e5}.custom-control-input:not(:disabled):active~.custom-control-label:before{background-color:#cbcbf0;border-color:#cbcbf0;color:#fff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#4b5563}.custom-control-input:disabled~.custom-control-label:before,.custom-control-input[disabled]~.custom-control-label:before{background-color:#e5e7eb}.custom-control-label{margin-bottom:0;position:relative;vertical-align:top}.custom-control-label:before{background-color:#fff;border:1px solid #6b7280;pointer-events:none}.custom-control-label:after,.custom-control-label:before{content:"";display:block;height:1rem;left:-1.5rem;position:absolute;top:.25rem;width:1rem}.custom-control-label:after{background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label:before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23fff' d='m6.564.75-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:before{background-color:#4040c8;border-color:#4040c8}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-radio .custom-control-label:before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label:before{border-radius:.5rem;left:-2.25rem;pointer-events:all;width:1.75rem}.custom-switch .custom-control-label:after{background-color:#6b7280;border-radius:.5rem;height:calc(1rem - 4px);left:calc(-2.25rem + 2px);top:calc(.25rem + 2px);transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:calc(1rem - 4px)}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label:after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label:after{background-color:#fff;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat;border:1px solid #d1d5db;border-radius:.25rem;color:#1f2937;display:inline-block;font-size:1rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem 1.75rem .375rem .75rem;vertical-align:middle;width:100%}.custom-select:focus{border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0}.custom-select:focus::-ms-value{background-color:#fff;color:#1f2937}.custom-select[multiple],.custom-select[size]:not([size="1"]){background-image:none;height:auto;padding-right:.75rem}.custom-select:disabled{background-color:#e5e7eb;color:#4b5563}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #1f2937}.custom-select-sm{font-size:.875rem;height:calc(1.5em + .5rem + 2px);padding-bottom:.25rem;padding-left:.5rem;padding-top:.25rem}.custom-select-lg{font-size:1.25rem;height:calc(1.5em + 1rem + 2px);padding-bottom:.5rem;padding-left:1rem;padding-top:.5rem}.custom-file{display:inline-block;margin-bottom:0}.custom-file,.custom-file-input{height:calc(1.5em + .75rem + 2px);position:relative;width:100%}.custom-file-input{margin:0;opacity:0;overflow:hidden;z-index:2}.custom-file-input:focus~.custom-file-label{border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e5e7eb}.custom-file-input:lang(en)~.custom-file-label:after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]:after{content:attr(data-browse)}.custom-file-label{background-color:#fff;border:1px solid #d1d5db;border-radius:.25rem;font-weight:400;height:calc(1.5em + .75rem + 2px);left:0;overflow:hidden;z-index:1}.custom-file-label,.custom-file-label:after{color:#1f2937;line-height:1.5;padding:.375rem .75rem;position:absolute;right:0;top:0}.custom-file-label:after{background-color:#e5e7eb;border-left:inherit;border-radius:0 .25rem .25rem 0;bottom:0;content:"Browse";display:block;height:calc(1.5em + .75rem);z-index:3}.custom-range{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;height:1.4rem;padding:0;width:100%}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #f3f4f6,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #f3f4f6,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #f3f4f6,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;margin-top:-.25rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#cbcbf0}.custom-range::-webkit-slider-runnable-track{background-color:#d1d5db;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-moz-range-thumb{-moz-appearance:none;appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#cbcbf0}.custom-range::-moz-range-track{background-color:#d1d5db;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-thumb{appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;margin-left:.2rem;margin-right:.2rem;margin-top:0;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#cbcbf0}.custom-range::-ms-track{background-color:transparent;border-color:transparent;border-width:.5rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-fill-lower,.custom-range::-ms-fill-upper{background-color:#d1d5db;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px}.custom-range:disabled::-webkit-slider-thumb{background-color:#6b7280}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#6b7280}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#6b7280}.custom-control-label:before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label:before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;flex-wrap:wrap;list-style:none;margin-bottom:0;padding-left:0}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#4b5563;cursor:default;pointer-events:none}.nav-tabs{border-bottom:1px solid #d1d5db}.nav-tabs .nav-link{background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem;margin-bottom:-1px}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e5e7eb #e5e7eb #d1d5db;isolation:isolate}.nav-tabs .nav-link.disabled{background-color:transparent;border-color:transparent;color:#4b5563}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{background-color:#f3f4f6;border-color:#d1d5db #d1d5db #f3f4f6;color:#374151}.nav-tabs .dropdown-menu{border-top-left-radius:0;border-top-right-radius:0;margin-top:-1px}.nav-pills .nav-link{background:none;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{background-color:#e5e7eb;color:#fff}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{padding:.5rem 1rem;position:relative}.navbar,.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between}.navbar-brand{display:inline-block;font-size:1.25rem;line-height:inherit;margin-right:1rem;padding-bottom:.3125rem;padding-top:.3125rem;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;list-style:none;margin-bottom:0;padding-left:0}.navbar-nav .nav-link{padding-left:0;padding-right:0}.navbar-nav .dropdown-menu{float:none;position:static}.navbar-text{display:inline-block;padding-bottom:.5rem;padding-top:.5rem}.navbar-collapse{align-items:center;flex-basis:100%;flex-grow:1}.navbar-toggler{background-color:transparent;border:1px solid transparent;border-radius:.25rem;font-size:1.25rem;line-height:1;padding:.25rem .75rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{background:50%/100% 100% no-repeat;content:"";display:inline-block;height:1.5em;vertical-align:middle;width:1.5em}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:1.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-left:0;padding-right:0}}@media (min-width:2px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:7.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-left:0;padding-right:0}}@media (min-width:8px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:8.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-left:0;padding-right:0}}@media (min-width:9px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:9.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-left:0;padding-right:0}}@media (min-width:10px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-left:0;padding-right:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{border-color:rgba(0,0,0,.1);color:rgba(0,0,0,.5)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{border-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{word-wrap:break-word;background-clip:border-box;background-color:#fff;border:1px solid rgba(0,0,0,.125);border-radius:6px;display:flex;flex-direction:column;min-width:0;position:relative}.card>hr{margin-left:0;margin-right:0}.card>.list-group{border-bottom:inherit;border-top:inherit}.card>.list-group:first-child{border-top-left-radius:5px;border-top-right-radius:5px;border-top-width:0}.card>.list-group:last-child{border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-bottom-width:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{background-color:#fff;border-bottom:1px solid rgba(0,0,0,.125);margin-bottom:0;padding:.75rem 1.25rem}.card-header:first-child{border-radius:5px 5px 0 0}.card-footer{background-color:#fff;border-top:1px solid rgba(0,0,0,.125);padding:.75rem 1.25rem}.card-footer:last-child{border-radius:0 0 5px 5px}.card-header-tabs{border-bottom:0;margin-bottom:-.75rem}.card-header-pills,.card-header-tabs{margin-left:-.625rem;margin-right:-.625rem}.card-img-overlay{border-radius:5px;bottom:0;left:0;padding:1.25rem;position:absolute;right:0;top:0}.card-img,.card-img-bottom,.card-img-top{flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:5px;border-top-right-radius:5px}.card-img,.card-img-bottom{border-bottom-left-radius:5px;border-bottom-right-radius:5px}.card-deck .card{margin-bottom:15px}@media (min-width:2px){.card-deck{display:flex;flex-flow:row wrap;margin-left:-15px;margin-right:-15px}.card-deck .card{flex:1 0 0%;margin-bottom:0;margin-left:15px;margin-right:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:2px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{border-left:0;margin-left:0}.card-group>.card:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:2px){.card-columns{-moz-column-count:3;column-count:3;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{background-color:#e5e7eb;border-radius:.25rem;display:flex;flex-wrap:wrap;list-style:none;margin-bottom:1rem;padding:.75rem 1rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item:before{color:#4b5563;content:"/";float:left;padding-right:.5rem}.breadcrumb-item+.breadcrumb-item:hover:before{text-decoration:underline;text-decoration:none}.breadcrumb-item.active{color:#4b5563}.pagination{border-radius:.25rem;display:flex;list-style:none;padding-left:0}.page-link{background-color:#fff;border:1px solid #d1d5db;color:#6366f1;display:block;line-height:1.25;margin-left:-1px;padding:.5rem .75rem;position:relative}.page-link:hover{background-color:#e5e7eb;border-color:#d1d5db;color:#4f46e5;text-decoration:none;z-index:2}.page-link:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0;z-index:3}.page-item:first-child .page-link{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem;margin-left:0}.page-item:last-child .page-link{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.page-item.active .page-link{background-color:#4040c8;border-color:#4040c8;color:#fff;z-index:3}.page-item.disabled .page-link{background-color:#fff;border-color:#d1d5db;color:#4b5563;cursor:auto;pointer-events:none}.pagination-lg .page-link{font-size:1.25rem;line-height:1.5;padding:.75rem 1.5rem}.pagination-lg .page-item:first-child .page-link{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg .page-item:last-child .page-link{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm .page-link{font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.pagination-sm .page-item:first-child .page-link{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.badge{border-radius:.25rem;display:inline-block;font-size:.875rem;font-weight:600;line-height:1;padding:.25em .4em;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:baseline;white-space:nowrap}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{border-radius:10rem;padding-left:.6em;padding-right:.6em}.badge-primary{background-color:#4040c8;color:#fff}a.badge-primary:focus,a.badge-primary:hover{background-color:#3030a5;color:#fff}a.badge-primary.focus,a.badge-primary:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.5);outline:0}.badge-secondary{background-color:#4b5563;color:#fff}a.badge-secondary:focus,a.badge-secondary:hover{background-color:#353c46;color:#fff}a.badge-secondary.focus,a.badge-secondary:focus{box-shadow:0 0 0 .2rem rgba(75,85,99,.5);outline:0}.badge-success{background-color:#059669;color:#fff}a.badge-success:focus,a.badge-success:hover{background-color:#036546;color:#fff}a.badge-success.focus,a.badge-success:focus{box-shadow:0 0 0 .2rem rgba(5,150,105,.5);outline:0}.badge-info{background-color:#2563eb;color:#fff}a.badge-info:focus,a.badge-info:hover{background-color:#134cca;color:#fff}a.badge-info.focus,a.badge-info:focus{box-shadow:0 0 0 .2rem rgba(37,99,235,.5);outline:0}.badge-warning{background-color:#d97706;color:#fff}a.badge-warning:focus,a.badge-warning:hover{background-color:#a75c05;color:#fff}a.badge-warning.focus,a.badge-warning:focus{box-shadow:0 0 0 .2rem rgba(217,119,6,.5);outline:0}.badge-danger{background-color:#dc2626;color:#fff}a.badge-danger:focus,a.badge-danger:hover{background-color:#b21d1d;color:#fff}a.badge-danger.focus,a.badge-danger:focus{box-shadow:0 0 0 .2rem rgba(220,38,38,.5);outline:0}.badge-light{background-color:#f3f4f6;color:#111827}a.badge-light:focus,a.badge-light:hover{background-color:#d6d9e0;color:#111827}a.badge-light.focus,a.badge-light:focus{box-shadow:0 0 0 .2rem rgba(243,244,246,.5);outline:0}.badge-dark{background-color:#1f2937;color:#fff}a.badge-dark:focus,a.badge-dark:hover{background-color:#0d1116;color:#fff}a.badge-dark.focus,a.badge-dark:focus{box-shadow:0 0 0 .2rem rgba(31,41,55,.5);outline:0}.jumbotron{background-color:#e5e7eb;border-radius:6px;margin-bottom:2rem;padding:2rem 1rem}@media (min-width:2px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{border-radius:0;padding-left:0;padding-right:0}.alert{border:1px solid transparent;border-radius:.25rem;margin-bottom:1rem;padding:.75rem 1.25rem;position:relative}.alert-heading{color:inherit}.alert-link{font-weight:600}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{color:inherit;padding:.75rem 1.25rem;position:absolute;right:0;top:0;z-index:2}.alert-primary{background-color:#d9d9f4;border-color:#cacaf0;color:#212168}.alert-primary hr{border-top-color:#b6b6ea}.alert-primary .alert-link{color:#151541}.alert-secondary{background-color:#dbdde0;border-color:#cdcfd3;color:#272c33}.alert-secondary hr{border-top-color:#bfc2c7}.alert-secondary .alert-link{color:#111316}.alert-success{background-color:#cdeae1;border-color:#b9e2d5;color:#034e37}.alert-success hr{border-top-color:#a7dbca}.alert-success .alert-link{color:#011d14}.alert-info{background-color:#d3e0fb;border-color:#c2d3f9;color:#13337a}.alert-info hr{border-top-color:#abc2f7}.alert-info .alert-link{color:#0c214e}.alert-warning{background-color:#f7e4cd;border-color:#f4d9b9;color:#713e03}.alert-warning hr{border-top-color:#f1cda3}.alert-warning .alert-link{color:#3f2302}.alert-danger{background-color:#f8d4d4;border-color:#f5c2c2;color:#721414}.alert-danger hr{border-top-color:#f1acac}.alert-danger .alert-link{color:#470c0c}.alert-light{background-color:#fdfdfd;border-color:#fcfcfc;color:#7e7f80}.alert-light hr{border-top-color:#efefef}.alert-light .alert-link{color:#656666}.alert-dark{background-color:#d2d4d7;border-color:#c0c3c7;color:#10151d}.alert-dark hr{border-top-color:#b3b6bb}.alert-dark .alert-link{color:#000}@keyframes progress-bar-stripes{0%{background-position:1rem 0}to{background-position:0 0}}.progress{background-color:#e5e7eb;border-radius:.25rem;font-size:.75rem;height:1rem;line-height:0}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{background-color:#4040c8;color:#fff;flex-direction:column;justify-content:center;text-align:center;transition:width .6s ease;white-space:nowrap}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:1rem 1rem}.progress-bar-animated{animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.media{align-items:flex-start;display:flex}.media-body{flex:1}.list-group{border-radius:.25rem;display:flex;flex-direction:column;margin-bottom:0;padding-left:0}.list-group-item-action{color:#374151;text-align:inherit;width:100%}.list-group-item-action:focus,.list-group-item-action:hover{background-color:#f3f4f6;color:#374151;text-decoration:none;z-index:1}.list-group-item-action:active{background-color:#e5e7eb;color:#111827}.list-group-item{background-color:#fff;border:1px solid rgba(0,0,0,.125);display:block;padding:.75rem 1.25rem;position:relative}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{background-color:#fff;color:#4b5563;pointer-events:none}.list-group-item.active{background-color:#4040c8;border-color:#4040c8;color:#fff;z-index:2}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{border-top-width:1px;margin-top:-1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}@media (min-width:2px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:8px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-md>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:9px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:10px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{background-color:#cacaf0;color:#212168}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{background-color:#b6b6ea;color:#212168}.list-group-item-primary.list-group-item-action.active{background-color:#212168;border-color:#212168;color:#fff}.list-group-item-secondary{background-color:#cdcfd3;color:#272c33}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{background-color:#bfc2c7;color:#272c33}.list-group-item-secondary.list-group-item-action.active{background-color:#272c33;border-color:#272c33;color:#fff}.list-group-item-success{background-color:#b9e2d5;color:#034e37}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{background-color:#a7dbca;color:#034e37}.list-group-item-success.list-group-item-action.active{background-color:#034e37;border-color:#034e37;color:#fff}.list-group-item-info{background-color:#c2d3f9;color:#13337a}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{background-color:#abc2f7;color:#13337a}.list-group-item-info.list-group-item-action.active{background-color:#13337a;border-color:#13337a;color:#fff}.list-group-item-warning{background-color:#f4d9b9;color:#713e03}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{background-color:#f1cda3;color:#713e03}.list-group-item-warning.list-group-item-action.active{background-color:#713e03;border-color:#713e03;color:#fff}.list-group-item-danger{background-color:#f5c2c2;color:#721414}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{background-color:#f1acac;color:#721414}.list-group-item-danger.list-group-item-action.active{background-color:#721414;border-color:#721414;color:#fff}.list-group-item-light{background-color:#fcfcfc;color:#7e7f80}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{background-color:#efefef;color:#7e7f80}.list-group-item-light.list-group-item-action.active{background-color:#7e7f80;border-color:#7e7f80;color:#fff}.list-group-item-dark{background-color:#c0c3c7;color:#10151d}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{background-color:#b3b6bb;color:#10151d}.list-group-item-dark.list-group-item-action.active{background-color:#10151d;border-color:#10151d;color:#fff}.close{color:#000;float:right;font-size:1.5rem;font-weight:600;line-height:1;opacity:.5;text-shadow:0 1px 0 #fff}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{background-color:transparent;border:0;padding:0}a.close.disabled{pointer-events:none}.toast{background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border:1px solid rgba(0,0,0,.1);border-radius:.25rem;box-shadow:0 .25rem .75rem rgba(0,0,0,.1);flex-basis:350px;font-size:.875rem;max-width:350px;opacity:0}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{align-items:center;background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px);color:#4b5563;display:flex;padding:.25rem .75rem}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{display:none;height:100%;left:0;outline:0;overflow:hidden;position:fixed;top:0;width:100%;z-index:1050}.modal-dialog{margin:.5rem;pointer-events:none;position:relative;width:auto}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{align-items:center;display:flex;min-height:calc(100% - 1rem)}.modal-dialog-centered:before{content:"";display:block;height:calc(100vh - 1rem);height:-moz-min-content;height:min-content}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;height:100%;justify-content:center}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable:before{content:none}.modal-content{background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:6px;display:flex;flex-direction:column;outline:0;pointer-events:auto;position:relative;width:100%}.modal-backdrop{background-color:#000;height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:1040}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{align-items:flex-start;border-bottom:1px solid #d1d5db;border-top-left-radius:5px;border-top-right-radius:5px;display:flex;justify-content:space-between;padding:1rem}.modal-header .close{margin:-1rem -1rem -1rem auto;padding:1rem}.modal-title{line-height:1.5;margin-bottom:0}.modal-body{flex:1 1 auto;padding:1rem;position:relative}.modal-footer{align-items:center;border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-top:1px solid #d1d5db;display:flex;flex-wrap:wrap;justify-content:flex-end;padding:.75rem}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{height:50px;overflow:scroll;position:absolute;top:-9999px;width:50px}@media (min-width:2px){.modal-dialog{margin:1.75rem auto;max-width:500px}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered:before{height:calc(100vh - 3.5rem);height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:9px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:10px){.modal-xl{max-width:1140px}}.tooltip{word-wrap:break-word;display:block;font-family:Figtree,sans-serif;font-size:.875rem;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;margin:0;opacity:0;position:absolute;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;z-index:1070}.tooltip.show{opacity:.9}.tooltip .arrow{display:block;height:.4rem;position:absolute;width:.8rem}.tooltip .arrow:before{border-color:transparent;border-style:solid;content:"";position:absolute}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow:before,.bs-tooltip-top .arrow:before{border-top-color:#000;border-width:.4rem .4rem 0;top:0}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{height:.8rem;left:0;width:.4rem}.bs-tooltip-auto[x-placement^=right] .arrow:before,.bs-tooltip-right .arrow:before{border-right-color:#000;border-width:.4rem .4rem .4rem 0;right:0}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.bs-tooltip-bottom .arrow:before{border-bottom-color:#000;border-width:0 .4rem .4rem;bottom:0}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{height:.8rem;right:0;width:.4rem}.bs-tooltip-auto[x-placement^=left] .arrow:before,.bs-tooltip-left .arrow:before{border-left-color:#000;border-width:.4rem 0 .4rem .4rem;left:0}.tooltip-inner{background-color:#000;border-radius:.25rem;color:#fff;max-width:200px;padding:.25rem .5rem;text-align:center}.popover{word-wrap:break-word;background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:6px;font-family:Figtree,sans-serif;font-size:.875rem;font-style:normal;font-weight:400;left:0;letter-spacing:normal;line-break:auto;line-height:1.5;max-width:276px;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;top:0;white-space:normal;word-break:normal;word-spacing:normal;z-index:1060}.popover,.popover .arrow{display:block;position:absolute}.popover .arrow{height:.5rem;margin:0 6px;width:1rem}.popover .arrow:after,.popover .arrow:before{border-color:transparent;border-style:solid;content:"";display:block;position:absolute}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow:before,.bs-popover-top>.arrow:before{border-top-color:rgba(0,0,0,.25);border-width:.5rem .5rem 0;bottom:0}.bs-popover-auto[x-placement^=top]>.arrow:after,.bs-popover-top>.arrow:after{border-top-color:#fff;border-width:.5rem .5rem 0;bottom:1px}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{height:1rem;left:calc(-.5rem - 1px);margin:6px 0;width:.5rem}.bs-popover-auto[x-placement^=right]>.arrow:before,.bs-popover-right>.arrow:before{border-right-color:rgba(0,0,0,.25);border-width:.5rem .5rem .5rem 0;left:0}.bs-popover-auto[x-placement^=right]>.arrow:after,.bs-popover-right>.arrow:after{border-right-color:#fff;border-width:.5rem .5rem .5rem 0;left:1px}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow:before,.bs-popover-bottom>.arrow:before{border-bottom-color:rgba(0,0,0,.25);border-width:0 .5rem .5rem;top:0}.bs-popover-auto[x-placement^=bottom]>.arrow:after,.bs-popover-bottom>.arrow:after{border-bottom-color:#fff;border-width:0 .5rem .5rem;top:1px}.bs-popover-auto[x-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{border-bottom:1px solid #f7f7f7;content:"";display:block;left:50%;margin-left:-.5rem;position:absolute;top:0;width:1rem}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{height:1rem;margin:6px 0;right:calc(-.5rem - 1px);width:.5rem}.bs-popover-auto[x-placement^=left]>.arrow:before,.bs-popover-left>.arrow:before{border-left-color:rgba(0,0,0,.25);border-width:.5rem 0 .5rem .5rem;right:0}.bs-popover-auto[x-placement^=left]>.arrow:after,.bs-popover-left>.arrow:after{border-left-color:#fff;border-width:.5rem 0 .5rem .5rem;right:1px}.popover-header{background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:5px;border-top-right-radius:5px;font-size:1rem;margin-bottom:0;padding:.5rem .75rem}.popover-header:empty{display:none}.popover-body{color:#111827;padding:.5rem .75rem}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{overflow:hidden;position:relative;width:100%}.carousel-inner:after{clear:both;content:"";display:block}.carousel-item{backface-visibility:hidden;display:none;float:left;margin-right:-100%;position:relative;transition:transform .6s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transform:none;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{opacity:1;z-index:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0;transition:opacity 0s .6s;z-index:0}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{align-items:center;background:none;border:0;bottom:0;color:#fff;display:flex;justify-content:center;opacity:.5;padding:0;position:absolute;text-align:center;top:0;transition:opacity .15s ease;width:15%;z-index:1}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;opacity:.9;outline:0;text-decoration:none}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{background:50%/100% 100% no-repeat;display:inline-block;height:20px;width:20px}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m5.25 0-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m2.75 0-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{bottom:0;display:flex;justify-content:center;left:0;list-style:none;margin-left:15%;margin-right:15%;padding-left:0;position:absolute;right:0;z-index:15}.carousel-indicators li{background-clip:padding-box;background-color:#fff;border-bottom:10px solid transparent;border-top:10px solid transparent;box-sizing:content-box;cursor:pointer;flex:0 1 auto;height:3px;margin-left:3px;margin-right:3px;opacity:.5;text-indent:-999px;transition:opacity .6s ease;width:30px}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{bottom:20px;color:#fff;left:15%;padding-bottom:20px;padding-top:20px;position:absolute;right:15%;text-align:center;z-index:10}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{animation:spinner-border .75s linear infinite;border:.25em solid;border-radius:50%;border-right:.25em solid transparent;display:inline-block;height:2rem;vertical-align:-.125em;width:2rem}.spinner-border-sm{border-width:.2em;height:1rem;width:1rem}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{animation:spinner-grow .75s linear infinite;background-color:currentcolor;border-radius:50%;display:inline-block;height:2rem;opacity:0;vertical-align:-.125em;width:2rem}.spinner-grow-sm{height:1rem;width:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#4040c8!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#3030a5!important}.bg-secondary{background-color:#4b5563!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#353c46!important}.bg-success{background-color:#059669!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#036546!important}.bg-info{background-color:#2563eb!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#134cca!important}.bg-warning{background-color:#d97706!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#a75c05!important}.bg-danger{background-color:#dc2626!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#b21d1d!important}.bg-light{background-color:#f3f4f6!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#d6d9e0!important}.bg-dark{background-color:#1f2937!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#0d1116!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #d1d5db!important}.border-top{border-top:1px solid #d1d5db!important}.border-right{border-right:1px solid #d1d5db!important}.border-bottom{border-bottom:1px solid #d1d5db!important}.border-left{border-left:1px solid #d1d5db!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#4040c8!important}.border-secondary{border-color:#4b5563!important}.border-success{border-color:#059669!important}.border-info{border-color:#2563eb!important}.border-warning{border-color:#d97706!important}.border-danger{border-color:#dc2626!important}.border-light{border-color:#f3f4f6!important}.border-dark{border-color:#1f2937!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important}.rounded-lg{border-radius:6px!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix:after{clear:both;content:"";display:block}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:2px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:8px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:9px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:10px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{display:block;overflow:hidden;padding:0;position:relative;width:100%}.embed-responsive:before{content:"";display:block}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{border:0;bottom:0;height:100%;left:0;position:absolute;top:0;width:100%}.embed-responsive-21by9:before{padding-top:42.85714286%}.embed-responsive-16by9:before{padding-top:56.25%}.embed-responsive-4by3:before{padding-top:75%}.embed-responsive-1by1:before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:2px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:8px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:9px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:10px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:2px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:8px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:9px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:10px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.fixed-top{top:0}.fixed-bottom,.fixed-top{left:0;position:fixed;right:0;z-index:1030}.fixed-bottom{bottom:0}@supports (position:sticky){.sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;overflow:visible;position:static;white-space:normal;width:auto}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:2px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:8px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:9px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:10px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link:after{background-color:transparent;bottom:0;content:"";left:0;pointer-events:auto;position:absolute;right:0;top:0;z-index:1}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:2px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:8px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:9px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:10px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:600!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#4040c8!important}a.text-primary:focus,a.text-primary:hover{color:#2a2a92!important}.text-secondary{color:#4b5563!important}a.text-secondary:focus,a.text-secondary:hover{color:#2a3037!important}.text-success{color:#059669!important}a.text-success:focus,a.text-success:hover{color:#034c35!important}.text-info{color:#2563eb!important}a.text-info:focus,a.text-info:hover{color:#1043b3!important}.text-warning{color:#d97706!important}a.text-warning:focus,a.text-warning:hover{color:#8f4e04!important}.text-danger{color:#dc2626!important}a.text-danger:focus,a.text-danger:hover{color:#9c1919!important}.text-light{color:#f3f4f6!important}a.text-light:focus,a.text-light:hover{color:#c7ccd5!important}.text-dark{color:#1f2937!important}a.text-dark:focus,a.text-dark:hover{color:#030506!important}.text-body{color:#111827!important}.text-muted{color:#6b7280!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:hsla(0,0%,100%,.5)!important}.text-hide{background-color:transparent;border:0;color:transparent;font:0/0 a;text-shadow:none}.text-decoration-none{text-decoration:none!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,:after,:before{box-shadow:none!important;text-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #6b7280}blockquote,img,pre,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3;}.container,body{min-width:9px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #d1d5db!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#e5e7eb}.table .thead-dark th{border-color:#e5e7eb;color:inherit}}.vjs-tree{color:#bfc7d5!important;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.vjs-tree .vjs-tree__content{border-left:1px dotted hsla(0,0%,80%,.28)!important}.vjs-tree .vjs-tree__node{cursor:pointer}.vjs-tree .vjs-tree__node:hover{color:#20a0ff}.vjs-tree .vjs-checkbox{left:-30px;position:absolute}.vjs-tree .vjs-value__boolean,.vjs-tree .vjs-value__null,.vjs-tree .vjs-value__number{color:#a291f5!important}.vjs-tree .vjs-value__string{color:#c3e88d!important}.vjs-tree .vjs-key{color:#c3cbd3!important}.hljs-addition,.hljs-attr,.hljs-keyword,.hljs-selector-tag{color:#13ce66}.hljs-bullet,.hljs-meta,.hljs-name,.hljs-string,.hljs-symbol,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable{color:#c3e88d}.hljs-comment,.hljs-deletion,.hljs-quote{color:#bfcbd9}.hljs-literal,.hljs-number,.hljs-title{color:#a291f5!important}body{padding-bottom:20px}.container{max-width:1440px}html{min-width:1140px}[v-cloak]{display:none}svg.icon{height:1rem;width:1rem}.header{border-bottom:1px solid #e5e7eb}.header .logo{color:#374151;text-decoration:none}.header .logo svg{height:1.7rem;width:1.7rem}.sidebar .nav-item a{border-radius:6px;color:#4b5563;margin-bottom:4px;padding:.5rem .75rem}.sidebar .nav-item a svg{fill:#9ca3af;height:1.25rem;margin-right:15px;width:1.25rem}.sidebar .nav-item a.active,.sidebar .nav-item a:hover{background-color:#e5e7eb;color:#4040c8}.sidebar .nav-item a.active svg{fill:#4040c8}.card{border:none;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1)}.card .bottom-radius{border-bottom-left-radius:6px;border-bottom-right-radius:6px}.card .card-header{background-color:#fff;border-bottom:none;min-height:60px;padding-bottom:.7rem;padding-top:.7rem}.card .card-header .btn-group .btn{padding:.2rem .5rem}.card .card-header .form-control-with-icon{position:relative}.card .card-header .form-control-with-icon .icon-wrapper{align-items:center;bottom:0;display:flex;justify-content:center;left:.75rem;position:absolute;top:0}.card .card-header .form-control-with-icon .icon-wrapper .icon{fill:#6b7280}.card .card-header .form-control-with-icon .form-control{border-radius:9999px;font-size:.875rem;padding-left:2.25rem}.card .table td,.card .table th{padding:.75rem 1.25rem}.card .table th{background-color:#f3f4f6;border-bottom:0;font-size:.875rem;padding:.5rem 1.25rem}.card .table:not(.table-borderless) td{border-top:1px solid #e5e7eb}.card .table.penultimate-column-right td:nth-last-child(2),.card .table.penultimate-column-right th:nth-last-child(2){text-align:right}.card .table td.table-fit,.card .table th.table-fit{white-space:nowrap;width:1%}.fill-text-color{fill:#111827}.fill-danger{fill:#dc2626}.fill-warning{fill:#d97706}.fill-info{fill:#2563eb}.fill-success{fill:#059669}.fill-primary{fill:#4040c8}button:hover .fill-primary{fill:#fff}.btn-outline-primary.active .fill-primary{fill:#f3f4f6}.btn-outline-primary:not(:disabled):not(.disabled).active:focus{box-shadow:none!important}.btn-muted{background:#e5e7eb;color:#4b5563}.btn-muted:focus,.btn-muted:hover{background:#d1d5db;color:#111827}.btn-muted.active{background:#4040c8;color:#fff}.badge-secondary{background:#e5e7eb;color:#4b5563}.badge-success{background:#d1fae5;color:#059669}.badge-info{background:#dbeafe;color:#2563eb}.badge-warning{background:#fef3c7;color:#d97706}.badge-danger{background:#fee2e2;color:#dc2626}.control-action svg{fill:#d1d5db;height:1.2rem;width:1.2rem}.control-action svg:hover{fill:#4f46e5}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.spin{animation:spin 2s linear infinite}.card .nav-pills{background:#fff}.card .nav-pills .nav-link{border-radius:0;color:#4b5563;font-size:.9rem;padding:.75rem 1.25rem}.card .nav-pills .nav-link:focus,.card .nav-pills .nav-link:hover{color:#1f2937}.card .nav-pills .nav-link.active{background:none;border-bottom:2px solid #4f46e5;color:#4f46e5}.list-enter-active:not(.dontanimate){transition:background 1s linear}.list-enter:not(.dontanimate),.list-leave-to:not(.dontanimate){background:#eef2ff}.code-bg .list-enter:not(.dontanimate),.code-bg .list-leave-to:not(.dontanimate){background:#4b5563}#indexScreen td{vertical-align:middle!important}.card-bg-secondary{background:#f3f4f6}.code-bg{background:#292d3e}.disabled-watcher{background:#dc2626;color:#fff;padding:.75rem}.copy-to-clipboard{--tw-text-opacity:1;color:rgb(231 232 242/var(--tw-text-opacity));opacity:.7;outline:2px solid transparent;outline-offset:2px;position:absolute;right:0;top:0;z-index:10} + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#4b5563;--gray-dark:#1f2937;--primary:#4040c8;--secondary:#4b5563;--success:#059669;--info:#2563eb;--warning:#d97706;--danger:#dc2626;--light:#f3f4f6;--dark:#1f2937;--breakpoint-xs:0;--breakpoint-sm:2px;--breakpoint-md:8px;--breakpoint-lg:9px;--breakpoint-xl:10px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);font-family:sans-serif;line-height:1.15}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{background-color:#f3f4f6;color:#111827;font-family:Figtree,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;margin:0;text-align:left}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;margin-top:0}p{margin-bottom:1rem;margin-top:0}abbr[data-original-title],abbr[title]{border-bottom:0;cursor:help;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:600}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{background-color:transparent;color:#6366f1;text-decoration:none}a:hover{color:#4f46e5;text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{-ms-overflow-style:scrollbar;margin-bottom:1rem;margin-top:0;overflow:auto}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{caption-side:bottom;color:#6b7280;padding-bottom:.75rem;padding-top:.75rem;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;margin:0}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{border:0;margin:0;min-width:0;padding:0}legend{color:inherit;display:block;font-size:1.5rem;line-height:inherit;margin-bottom:.5rem;max-width:100%;padding:0;white-space:normal;width:100%}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:none;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}output{display:inline-block}summary{cursor:pointer;display:list-item}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.2;margin-bottom:.5rem}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{border:0;border-top:1px solid rgba(0,0,0,.1);margin-bottom:1rem;margin-top:1rem}.small,small{font-size:.875em;font-weight:400}.mark,mark{background-color:#fcf8e3;padding:.2em}.list-inline,.list-unstyled{list-style:none;padding-left:0}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{font-size:1.25rem;margin-bottom:1rem}.blockquote-footer{color:#4b5563;display:block;font-size:.875em}.blockquote-footer:before{content:"โ€”ย "}.img-fluid,.img-thumbnail{height:auto;max-width:100%}.img-thumbnail{background-color:#f3f4f6;border:1px solid #d1d5db;border-radius:.25rem;padding:.25rem}.figure{display:inline-block}.figure-img{line-height:1;margin-bottom:.5rem}.figure-caption{color:#4b5563;font-size:90%}code{word-wrap:break-word;color:#e83e8c;font-size:87.5%}a>code{color:inherit}kbd{background-color:#111827;border-radius:.2rem;color:#fff;font-size:87.5%;padding:.2rem .4rem}kbd kbd{font-size:100%;font-weight:600;padding:0}pre{color:#111827;display:block;font-size:87.5%}pre code{color:inherit;font-size:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px;width:100%}@media (min-width:2px){.container,.container-sm{max-width:1137px}}@media (min-width:8px){.container,.container-md,.container-sm{max-width:1138px}}@media (min-width:9px){.container,.container-lg,.container-md,.container-sm{max-width:1139px}}@media (min-width:10px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:flex;flex-wrap:wrap;margin-left:-15px;margin-right:-15px}.no-gutters{margin-left:0;margin-right:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-left:0;padding-right:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{padding-left:15px;padding-right:15px;position:relative;width:100%}.col{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-auto{flex:0 0 auto;max-width:100%;width:auto}.col-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}@media (min-width:2px){.col-sm{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-auto{flex:0 0 auto;max-width:100%;width:auto}.col-sm-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-sm-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-sm-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-sm-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-sm-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}}@media (min-width:8px){.col-md{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-auto{flex:0 0 auto;max-width:100%;width:auto}.col-md-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-md-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-md-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-md-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-md-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}}@media (min-width:9px){.col-lg{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-auto{flex:0 0 auto;max-width:100%;width:auto}.col-lg-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-lg-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-lg-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-lg-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-lg-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}}@media (min-width:10px){.col-xl{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-auto{flex:0 0 auto;max-width:100%;width:auto}.col-xl-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-xl-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-xl-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-xl-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-xl-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}}.table{color:#111827;margin-bottom:1rem;width:100%}.table td,.table th{border-top:1px solid #e5e7eb;padding:.75rem;vertical-align:top}.table thead th{border-bottom:2px solid #e5e7eb;vertical-align:bottom}.table tbody+tbody{border-top:2px solid #e5e7eb}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #e5e7eb}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:#f3f4f6;color:#111827}.table-primary,.table-primary>td,.table-primary>th{background-color:#cacaf0}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#9c9ce2}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#b6b6ea}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#cdcfd3}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#a1a7ae}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#bfc2c7}.table-success,.table-success>td,.table-success>th{background-color:#b9e2d5}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#7dc8b1}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#a7dbca}.table-info,.table-info>td,.table-info>th{background-color:#c2d3f9}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#8eaef5}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abc2f7}.table-warning,.table-warning>td,.table-warning>th{background-color:#f4d9b9}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ebb87e}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#f1cda3}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c2c2}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed8e8e}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1acac}.table-light,.table-light>td,.table-light>th{background-color:#fcfcfc}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#f9f9fa}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#efefef}.table-dark,.table-dark>td,.table-dark>th{background-color:#c0c3c7}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#8b9097}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b3b6bb}.table-active,.table-active>td,.table-active>th{background-color:#f3f4f6}.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:#e4e7eb}.table .thead-dark th{background-color:#1f2937;border-color:#2d3b4f;color:#fff}.table .thead-light th{background-color:#e5e7eb;border-color:#e5e7eb;color:#374151}.table-dark{background-color:#1f2937;color:#fff}.table-dark td,.table-dark th,.table-dark thead th{border-color:#2d3b4f}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:hsla(0,0%,100%,.05)}.table-dark.table-hover tbody tr:hover{background-color:hsla(0,0%,100%,.075);color:#fff}@media (max-width:1.98px){.table-responsive-sm{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:7.98px){.table-responsive-md{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-md>.table-bordered{border:0}}@media (max-width:8.98px){.table-responsive-lg{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:9.98px){.table-responsive-xl{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive>.table-bordered{border:0}.form-control{background-clip:padding-box;background-color:#fff;border:1px solid #d1d5db;border-radius:.25rem;color:#1f2937;display:block;font-size:1rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{background-color:#fff;border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25);color:#1f2937;outline:0}.form-control::-moz-placeholder{color:#4b5563;opacity:1}.form-control::placeholder{color:#4b5563;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e5e7eb;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #1f2937}select.form-control:focus::-ms-value{background-color:#fff;color:#1f2937}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{font-size:inherit;line-height:1.5;margin-bottom:0;padding-bottom:calc(.375rem + 1px);padding-top:calc(.375rem + 1px)}.col-form-label-lg{font-size:1.25rem;line-height:1.5;padding-bottom:calc(.5rem + 1px);padding-top:calc(.5rem + 1px)}.col-form-label-sm{font-size:.875rem;line-height:1.5;padding-bottom:calc(.25rem + 1px);padding-top:calc(.25rem + 1px)}.form-control-plaintext{background-color:transparent;border:solid transparent;border-width:1px 0;color:#111827;display:block;font-size:1rem;line-height:1.5;margin-bottom:0;padding:.375rem 0;width:100%}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-left:0;padding-right:0}.form-control-sm{border-radius:.2rem;font-size:.875rem;height:calc(1.5em + .5rem + 2px);line-height:1.5;padding:.25rem .5rem}.form-control-lg{border-radius:6px;font-size:1.25rem;height:calc(1.5em + 1rem + 2px);line-height:1.5;padding:.5rem 1rem}select.form-control[multiple],select.form-control[size],textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-left:-5px;margin-right:-5px}.form-row>.col,.form-row>[class*=col-]{padding-left:5px;padding-right:5px}.form-check{display:block;padding-left:1.25rem;position:relative}.form-check-input{margin-left:-1.25rem;margin-top:.3rem;position:absolute}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6b7280}.form-check-label{margin-bottom:0}.form-check-inline{align-items:center;display:inline-flex;margin-right:.75rem;padding-left:0}.form-check-inline .form-check-input{margin-left:0;margin-right:.3125rem;margin-top:0;position:static}.valid-feedback{color:#059669;display:none;font-size:.875em;margin-top:.25rem;width:100%}.valid-tooltip{background-color:rgba(5,150,105,.9);border-radius:.25rem;color:#fff;display:none;font-size:.875rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23059669' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#059669;padding-right:calc(1.5em + .75rem)!important}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-valid,.was-validated .custom-select:valid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23059669' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#059669;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#059669}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#059669}.custom-control-input.is-valid~.custom-control-label:before,.was-validated .custom-control-input:valid~.custom-control-label:before{border-color:#059669}.custom-control-input.is-valid:checked~.custom-control-label:before,.was-validated .custom-control-input:valid:checked~.custom-control-label:before{background-color:#07c78c;border-color:#07c78c}.custom-control-input.is-valid:focus~.custom-control-label:before,.was-validated .custom-control-input:valid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label:before{border-color:#059669}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#059669}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#059669;box-shadow:0 0 0 .2rem rgba(5,150,105,.25)}.invalid-feedback{color:#dc2626;display:none;font-size:.875em;margin-top:.25rem;width:100%}.invalid-tooltip{background-color:rgba(220,38,38,.9);border-radius:.25rem;color:#fff;display:none;font-size:.875rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc2626'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc2626' stroke='none'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#dc2626;padding-right:calc(1.5em + .75rem)!important}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc2626'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc2626' stroke='none'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#dc2626;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc2626}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc2626}.custom-control-input.is-invalid~.custom-control-label:before,.was-validated .custom-control-input:invalid~.custom-control-label:before{border-color:#dc2626}.custom-control-input.is-invalid:checked~.custom-control-label:before,.was-validated .custom-control-input:invalid:checked~.custom-control-label:before{background-color:#e35252;border-color:#e35252}.custom-control-input.is-invalid:focus~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label:before{border-color:#dc2626}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc2626}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc2626;box-shadow:0 0 0 .2rem rgba(220,38,38,.25)}.form-inline{align-items:center;display:flex;flex-flow:row wrap}.form-inline .form-check{width:100%}@media (min-width:2px){.form-inline label{justify-content:center}.form-inline .form-group,.form-inline label{align-items:center;display:flex;margin-bottom:0}.form-inline .form-group{flex:0 0 auto;flex-flow:row wrap}.form-inline .form-control{display:inline-block;vertical-align:middle;width:auto}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{align-items:center;display:flex;justify-content:center;padding-left:0;width:auto}.form-inline .form-check-input{flex-shrink:0;margin-left:0;margin-right:.25rem;margin-top:0;position:relative}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;color:#111827;display:inline-block;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#111827;text-decoration:none}.btn.focus,.btn:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-primary.focus,.btn-primary:focus,.btn-primary:hover{background-color:#3232af;border-color:#3030a5;color:#fff}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 0 rgba(93,93,208,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{background-color:#3030a5;border-color:#2d2d9b;color:#fff}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(93,93,208,.5)}.btn-secondary{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:hover{background-color:#3b424d;border-color:#353c46;color:#fff}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 0 hsla(213,9%,44%,.5)}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{background-color:#353c46;border-color:#30363f;color:#fff}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 0 hsla(213,9%,44%,.5)}.btn-success{background-color:#059669;border-color:#059669;color:#fff}.btn-success.focus,.btn-success:focus,.btn-success:hover{background-color:#04714f;border-color:#036546;color:#fff}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 0 rgba(43,166,128,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#059669;border-color:#059669;color:#fff}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{background-color:#036546;border-color:#03583e;color:#fff}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(43,166,128,.5)}.btn-info{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-info.focus,.btn-info:focus,.btn-info:hover{background-color:#1451d6;border-color:#134cca;color:#fff}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 0 rgba(70,122,238,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{background-color:#134cca;border-color:#1248bf;color:#fff}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(70,122,238,.5)}.btn-warning{background-color:#d97706;border-color:#d97706;color:#fff}.btn-warning.focus,.btn-warning:focus,.btn-warning:hover{background-color:#b46305;border-color:#a75c05;color:#fff}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 0 rgba(223,139,43,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#d97706;border-color:#d97706;color:#fff}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{background-color:#a75c05;border-color:#9b5504;color:#fff}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(223,139,43,.5)}.btn-danger{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-danger.focus,.btn-danger:focus,.btn-danger:hover{background-color:#bd1f1f;border-color:#b21d1d;color:#fff}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 0 rgba(225,71,71,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{background-color:#b21d1d;border-color:#a71b1b;color:#fff}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(225,71,71,.5)}.btn-light{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-light.focus,.btn-light:focus,.btn-light:hover{background-color:#dde0e6;border-color:#d6d9e0;color:#111827}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 0 hsla(220,7%,83%,.5)}.btn-light.disabled,.btn-light:disabled{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{background-color:#d6d9e0;border-color:#cfd3db;color:#111827}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 0 hsla(220,7%,83%,.5)}.btn-dark{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-dark.focus,.btn-dark:focus,.btn-dark:hover{background-color:#11171f;border-color:#0d1116;color:#fff}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 0 rgba(65,73,85,.5)}.btn-dark.disabled,.btn-dark:disabled{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{background-color:#0d1116;border-color:#080b0e;color:#fff}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(65,73,85,.5)}.btn-outline-primary{border-color:#4040c8;color:#4040c8}.btn-outline-primary:hover{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 0 rgba(64,64,200,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{background-color:transparent;color:#4040c8}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{background-color:#4040c8;border-color:#4040c8;color:#fff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(64,64,200,.5)}.btn-outline-secondary{border-color:#4b5563;color:#4b5563}.btn-outline-secondary:hover{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 0 rgba(75,85,99,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{background-color:transparent;color:#4b5563}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{background-color:#4b5563;border-color:#4b5563;color:#fff}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(75,85,99,.5)}.btn-outline-success{border-color:#059669;color:#059669}.btn-outline-success:hover{background-color:#059669;border-color:#059669;color:#fff}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 0 rgba(5,150,105,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{background-color:transparent;color:#059669}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{background-color:#059669;border-color:#059669;color:#fff}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(5,150,105,.5)}.btn-outline-info{border-color:#2563eb;color:#2563eb}.btn-outline-info:hover{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 0 rgba(37,99,235,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{background-color:transparent;color:#2563eb}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{background-color:#2563eb;border-color:#2563eb;color:#fff}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(37,99,235,.5)}.btn-outline-warning{border-color:#d97706;color:#d97706}.btn-outline-warning:hover{background-color:#d97706;border-color:#d97706;color:#fff}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 0 rgba(217,119,6,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{background-color:transparent;color:#d97706}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{background-color:#d97706;border-color:#d97706;color:#fff}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(217,119,6,.5)}.btn-outline-danger{border-color:#dc2626;color:#dc2626}.btn-outline-danger:hover{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 0 rgba(220,38,38,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{background-color:transparent;color:#dc2626}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{background-color:#dc2626;border-color:#dc2626;color:#fff}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(220,38,38,.5)}.btn-outline-light{border-color:#f3f4f6;color:#f3f4f6}.btn-outline-light:hover{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 0 rgba(243,244,246,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{background-color:transparent;color:#f3f4f6}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{background-color:#f3f4f6;border-color:#f3f4f6;color:#111827}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(243,244,246,.5)}.btn-outline-dark{border-color:#1f2937;color:#1f2937}.btn-outline-dark:hover{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 0 rgba(31,41,55,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{background-color:transparent;color:#1f2937}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{background-color:#1f2937;border-color:#1f2937;color:#fff}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(31,41,55,.5)}.btn-link{color:#6366f1;font-weight:400;text-decoration:none}.btn-link:hover{color:#4f46e5}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#4b5563;pointer-events:none}.btn-group-lg>.btn,.btn-lg{border-radius:6px;font-size:1.25rem;line-height:1.5;padding:.5rem 1rem}.btn-group-sm>.btn,.btn-sm{border-radius:.2rem;font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;position:relative;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{height:auto;transition:width .35s ease;width:0}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{border-bottom:0;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:.3em solid;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;color:#111827;display:none;float:left;font-size:1rem;left:0;list-style:none;margin:.125rem 0 0;min-width:10rem;padding:.5rem 0;position:absolute;text-align:left;top:100%;z-index:1000}.dropdown-menu-left{left:0;right:auto}.dropdown-menu-right{left:auto;right:0}@media (min-width:2px){.dropdown-menu-sm-left{left:0;right:auto}.dropdown-menu-sm-right{left:auto;right:0}}@media (min-width:8px){.dropdown-menu-md-left{left:0;right:auto}.dropdown-menu-md-right{left:auto;right:0}}@media (min-width:9px){.dropdown-menu-lg-left{left:0;right:auto}.dropdown-menu-lg-right{left:auto;right:0}}@media (min-width:10px){.dropdown-menu-xl-left{left:0;right:auto}.dropdown-menu-xl-right{left:auto;right:0}}.dropup .dropdown-menu{bottom:100%;margin-bottom:.125rem;margin-top:0;top:auto}.dropup .dropdown-toggle:after{border-bottom:.3em solid;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:0;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-menu{left:100%;margin-left:.125rem;margin-top:0;right:auto;top:0}.dropright .dropdown-toggle:after{border-bottom:.3em solid transparent;border-left:.3em solid;border-right:0;border-top:.3em solid transparent;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropright .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-toggle:after{vertical-align:0}.dropleft .dropdown-menu{left:auto;margin-right:.125rem;margin-top:0;right:100%;top:0}.dropleft .dropdown-toggle:after{content:"";display:inline-block;display:none;margin-left:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:before{border-bottom:.3em solid transparent;border-right:.3em solid;border-top:.3em solid transparent;content:"";display:inline-block;margin-right:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:empty:after{margin-left:0}.dropleft .dropdown-toggle:before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{bottom:auto;right:auto}.dropdown-divider{border-top:1px solid #e5e7eb;height:0;margin:.5rem 0;overflow:hidden}.dropdown-item{background-color:transparent;border:0;clear:both;color:#374151;display:block;font-weight:400;padding:.25rem 1.5rem;text-align:inherit;white-space:nowrap;width:100%}.dropdown-item:focus,.dropdown-item:hover{background-color:#e5e7eb;color:#090d15;text-decoration:none}.dropdown-item.active,.dropdown-item:active{background-color:#4040c8;color:#fff;text-decoration:none}.dropdown-item.disabled,.dropdown-item:disabled{background-color:transparent;color:#6b7280;pointer-events:none}.dropdown-menu.show{display:block}.dropdown-header{color:#4b5563;display:block;font-size:.875rem;margin-bottom:0;padding:.5rem 1.5rem;white-space:nowrap}.dropdown-item-text{color:#374151;display:block;padding:.25rem 1.5rem}.btn-group,.btn-group-vertical{display:inline-flex;position:relative;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{flex:1 1 auto;position:relative}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.dropdown-toggle-split{padding-left:.5625rem;padding-right:.5625rem}.dropdown-toggle-split:after,.dropright .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropleft .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-left:.375rem;padding-right:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-left:.75rem;padding-right:.75rem}.btn-group-vertical{align-items:flex-start;flex-direction:column;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-left-radius:0;border-bottom-right-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{clip:rect(0,0,0,0);pointer-events:none;position:absolute}.input-group{align-items:stretch;display:flex;flex-wrap:wrap;position:relative;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{flex:1 1 auto;margin-bottom:0;min-width:0;position:relative;width:1%}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group>.custom-file{align-items:center;display:flex}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label:after{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-bottom-left-radius:0;border-top-left-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label:after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3),.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label:after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.input-group-append,.input-group-prepend{display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{align-items:center;background-color:#e5e7eb;border:1px solid #d1d5db;border-radius:.25rem;color:#1f2937;display:flex;font-size:1rem;font-weight:400;line-height:1.5;margin-bottom:0;padding:.375rem .75rem;text-align:center;white-space:nowrap}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{border-radius:6px;font-size:1.25rem;line-height:1.5;padding:.5rem 1rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{border-radius:.2rem;font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-bottom-left-radius:0;border-top-left-radius:0}.custom-control{display:block;min-height:1.5rem;padding-left:1.5rem;position:relative;-webkit-print-color-adjust:exact;print-color-adjust:exact;z-index:1}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{height:1.25rem;left:0;opacity:0;position:absolute;width:1rem;z-index:-1}.custom-control-input:checked~.custom-control-label:before{background-color:#4040c8;border-color:#4040c8;color:#fff}.custom-control-input:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(64,64,200,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label:before{border-color:#a3a3e5}.custom-control-input:not(:disabled):active~.custom-control-label:before{background-color:#cbcbf0;border-color:#cbcbf0;color:#fff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#4b5563}.custom-control-input:disabled~.custom-control-label:before,.custom-control-input[disabled]~.custom-control-label:before{background-color:#e5e7eb}.custom-control-label{margin-bottom:0;position:relative;vertical-align:top}.custom-control-label:before{background-color:#fff;border:1px solid #6b7280;pointer-events:none}.custom-control-label:after,.custom-control-label:before{content:"";display:block;height:1rem;left:-1.5rem;position:absolute;top:.25rem;width:1rem}.custom-control-label:after{background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label:before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23fff' d='m6.564.75-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:before{background-color:#4040c8;border-color:#4040c8}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-radio .custom-control-label:before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label:before{border-radius:.5rem;left:-2.25rem;pointer-events:all;width:1.75rem}.custom-switch .custom-control-label:after{background-color:#6b7280;border-radius:.5rem;height:calc(1rem - 4px);left:calc(-2.25rem + 2px);top:calc(.25rem + 2px);transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:calc(1rem - 4px)}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label:after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label:after{background-color:#fff;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(64,64,200,.5)}.custom-select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%231f2937' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat;border:1px solid #d1d5db;border-radius:.25rem;color:#1f2937;display:inline-block;font-size:1rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem 1.75rem .375rem .75rem;vertical-align:middle;width:100%}.custom-select:focus{border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0}.custom-select:focus::-ms-value{background-color:#fff;color:#1f2937}.custom-select[multiple],.custom-select[size]:not([size="1"]){background-image:none;height:auto;padding-right:.75rem}.custom-select:disabled{background-color:#e5e7eb;color:#4b5563}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #1f2937}.custom-select-sm{font-size:.875rem;height:calc(1.5em + .5rem + 2px);padding-bottom:.25rem;padding-left:.5rem;padding-top:.25rem}.custom-select-lg{font-size:1.25rem;height:calc(1.5em + 1rem + 2px);padding-bottom:.5rem;padding-left:1rem;padding-top:.5rem}.custom-file{display:inline-block;margin-bottom:0}.custom-file,.custom-file-input{height:calc(1.5em + .75rem + 2px);position:relative;width:100%}.custom-file-input{margin:0;opacity:0;overflow:hidden;z-index:2}.custom-file-input:focus~.custom-file-label{border-color:#a3a3e5;box-shadow:0 0 0 .2rem rgba(64,64,200,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e5e7eb}.custom-file-input:lang(en)~.custom-file-label:after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]:after{content:attr(data-browse)}.custom-file-label{background-color:#fff;border:1px solid #d1d5db;border-radius:.25rem;font-weight:400;height:calc(1.5em + .75rem + 2px);left:0;overflow:hidden;z-index:1}.custom-file-label,.custom-file-label:after{color:#1f2937;line-height:1.5;padding:.375rem .75rem;position:absolute;right:0;top:0}.custom-file-label:after{background-color:#e5e7eb;border-left:inherit;border-radius:0 .25rem .25rem 0;bottom:0;content:"Browse";display:block;height:calc(1.5em + .75rem);z-index:3}.custom-range{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;height:1.4rem;padding:0;width:100%}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #f3f4f6,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #f3f4f6,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #f3f4f6,0 0 0 .2rem rgba(64,64,200,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;margin-top:-.25rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#cbcbf0}.custom-range::-webkit-slider-runnable-track{background-color:#d1d5db;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-moz-range-thumb{-moz-appearance:none;appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#cbcbf0}.custom-range::-moz-range-track{background-color:#d1d5db;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-thumb{appearance:none;background-color:#4040c8;border:0;border-radius:1rem;height:1rem;margin-left:.2rem;margin-right:.2rem;margin-top:0;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#cbcbf0}.custom-range::-ms-track{background-color:transparent;border-color:transparent;border-width:.5rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-fill-lower,.custom-range::-ms-fill-upper{background-color:#d1d5db;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px}.custom-range:disabled::-webkit-slider-thumb{background-color:#6b7280}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#6b7280}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#6b7280}.custom-control-label:before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label:before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;flex-wrap:wrap;list-style:none;margin-bottom:0;padding-left:0}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#4b5563;cursor:default;pointer-events:none}.nav-tabs{border-bottom:1px solid #d1d5db}.nav-tabs .nav-link{background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem;margin-bottom:-1px}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e5e7eb #e5e7eb #d1d5db;isolation:isolate}.nav-tabs .nav-link.disabled{background-color:transparent;border-color:transparent;color:#4b5563}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{background-color:#f3f4f6;border-color:#d1d5db #d1d5db #f3f4f6;color:#374151}.nav-tabs .dropdown-menu{border-top-left-radius:0;border-top-right-radius:0;margin-top:-1px}.nav-pills .nav-link{background:none;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{background-color:#e5e7eb;color:#fff}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{padding:.5rem 1rem;position:relative}.navbar,.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between}.navbar-brand{display:inline-block;font-size:1.25rem;line-height:inherit;margin-right:1rem;padding-bottom:.3125rem;padding-top:.3125rem;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;list-style:none;margin-bottom:0;padding-left:0}.navbar-nav .nav-link{padding-left:0;padding-right:0}.navbar-nav .dropdown-menu{float:none;position:static}.navbar-text{display:inline-block;padding-bottom:.5rem;padding-top:.5rem}.navbar-collapse{align-items:center;flex-basis:100%;flex-grow:1}.navbar-toggler{background-color:transparent;border:1px solid transparent;border-radius:.25rem;font-size:1.25rem;line-height:1;padding:.25rem .75rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{background:50%/100% 100% no-repeat;content:"";display:inline-block;height:1.5em;vertical-align:middle;width:1.5em}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:1.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-left:0;padding-right:0}}@media (min-width:2px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:7.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-left:0;padding-right:0}}@media (min-width:8px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:8.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-left:0;padding-right:0}}@media (min-width:9px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:9.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-left:0;padding-right:0}}@media (min-width:10px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-left:0;padding-right:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{border-color:rgba(0,0,0,.1);color:rgba(0,0,0,.5)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{border-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{word-wrap:break-word;background-clip:border-box;background-color:#fff;border:1px solid rgba(0,0,0,.125);border-radius:6px;display:flex;flex-direction:column;min-width:0;position:relative}.card>hr{margin-left:0;margin-right:0}.card>.list-group{border-bottom:inherit;border-top:inherit}.card>.list-group:first-child{border-top-left-radius:5px;border-top-right-radius:5px;border-top-width:0}.card>.list-group:last-child{border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-bottom-width:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{background-color:#fff;border-bottom:1px solid rgba(0,0,0,.125);margin-bottom:0;padding:.75rem 1.25rem}.card-header:first-child{border-radius:5px 5px 0 0}.card-footer{background-color:#fff;border-top:1px solid rgba(0,0,0,.125);padding:.75rem 1.25rem}.card-footer:last-child{border-radius:0 0 5px 5px}.card-header-tabs{border-bottom:0;margin-bottom:-.75rem}.card-header-pills,.card-header-tabs{margin-left:-.625rem;margin-right:-.625rem}.card-img-overlay{border-radius:5px;bottom:0;left:0;padding:1.25rem;position:absolute;right:0;top:0}.card-img,.card-img-bottom,.card-img-top{flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:5px;border-top-right-radius:5px}.card-img,.card-img-bottom{border-bottom-left-radius:5px;border-bottom-right-radius:5px}.card-deck .card{margin-bottom:15px}@media (min-width:2px){.card-deck{display:flex;flex-flow:row wrap;margin-left:-15px;margin-right:-15px}.card-deck .card{flex:1 0 0%;margin-bottom:0;margin-left:15px;margin-right:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:2px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{border-left:0;margin-left:0}.card-group>.card:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:2px){.card-columns{-moz-column-count:3;column-count:3;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{background-color:#e5e7eb;border-radius:.25rem;display:flex;flex-wrap:wrap;list-style:none;margin-bottom:1rem;padding:.75rem 1rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item:before{color:#4b5563;content:"/";float:left;padding-right:.5rem}.breadcrumb-item+.breadcrumb-item:hover:before{text-decoration:underline;text-decoration:none}.breadcrumb-item.active{color:#4b5563}.pagination{border-radius:.25rem;display:flex;list-style:none;padding-left:0}.page-link{background-color:#fff;border:1px solid #d1d5db;color:#6366f1;display:block;line-height:1.25;margin-left:-1px;padding:.5rem .75rem;position:relative}.page-link:hover{background-color:#e5e7eb;border-color:#d1d5db;color:#4f46e5;text-decoration:none;z-index:2}.page-link:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.25);outline:0;z-index:3}.page-item:first-child .page-link{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem;margin-left:0}.page-item:last-child .page-link{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.page-item.active .page-link{background-color:#4040c8;border-color:#4040c8;color:#fff;z-index:3}.page-item.disabled .page-link{background-color:#fff;border-color:#d1d5db;color:#4b5563;cursor:auto;pointer-events:none}.pagination-lg .page-link{font-size:1.25rem;line-height:1.5;padding:.75rem 1.5rem}.pagination-lg .page-item:first-child .page-link{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg .page-item:last-child .page-link{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm .page-link{font-size:.875rem;line-height:1.5;padding:.25rem .5rem}.pagination-sm .page-item:first-child .page-link{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.badge{border-radius:.25rem;display:inline-block;font-size:.875rem;font-weight:600;line-height:1;padding:.25em .4em;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:baseline;white-space:nowrap}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{border-radius:10rem;padding-left:.6em;padding-right:.6em}.badge-primary{background-color:#4040c8;color:#fff}a.badge-primary:focus,a.badge-primary:hover{background-color:#3030a5;color:#fff}a.badge-primary.focus,a.badge-primary:focus{box-shadow:0 0 0 .2rem rgba(64,64,200,.5);outline:0}.badge-secondary{background-color:#4b5563;color:#fff}a.badge-secondary:focus,a.badge-secondary:hover{background-color:#353c46;color:#fff}a.badge-secondary.focus,a.badge-secondary:focus{box-shadow:0 0 0 .2rem rgba(75,85,99,.5);outline:0}.badge-success{background-color:#059669;color:#fff}a.badge-success:focus,a.badge-success:hover{background-color:#036546;color:#fff}a.badge-success.focus,a.badge-success:focus{box-shadow:0 0 0 .2rem rgba(5,150,105,.5);outline:0}.badge-info{background-color:#2563eb;color:#fff}a.badge-info:focus,a.badge-info:hover{background-color:#134cca;color:#fff}a.badge-info.focus,a.badge-info:focus{box-shadow:0 0 0 .2rem rgba(37,99,235,.5);outline:0}.badge-warning{background-color:#d97706;color:#fff}a.badge-warning:focus,a.badge-warning:hover{background-color:#a75c05;color:#fff}a.badge-warning.focus,a.badge-warning:focus{box-shadow:0 0 0 .2rem rgba(217,119,6,.5);outline:0}.badge-danger{background-color:#dc2626;color:#fff}a.badge-danger:focus,a.badge-danger:hover{background-color:#b21d1d;color:#fff}a.badge-danger.focus,a.badge-danger:focus{box-shadow:0 0 0 .2rem rgba(220,38,38,.5);outline:0}.badge-light{background-color:#f3f4f6;color:#111827}a.badge-light:focus,a.badge-light:hover{background-color:#d6d9e0;color:#111827}a.badge-light.focus,a.badge-light:focus{box-shadow:0 0 0 .2rem rgba(243,244,246,.5);outline:0}.badge-dark{background-color:#1f2937;color:#fff}a.badge-dark:focus,a.badge-dark:hover{background-color:#0d1116;color:#fff}a.badge-dark.focus,a.badge-dark:focus{box-shadow:0 0 0 .2rem rgba(31,41,55,.5);outline:0}.jumbotron{background-color:#e5e7eb;border-radius:6px;margin-bottom:2rem;padding:2rem 1rem}@media (min-width:2px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{border-radius:0;padding-left:0;padding-right:0}.alert{border:1px solid transparent;border-radius:.25rem;margin-bottom:1rem;padding:.75rem 1.25rem;position:relative}.alert-heading{color:inherit}.alert-link{font-weight:600}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{color:inherit;padding:.75rem 1.25rem;position:absolute;right:0;top:0;z-index:2}.alert-primary{background-color:#d9d9f4;border-color:#cacaf0;color:#212168}.alert-primary hr{border-top-color:#b6b6ea}.alert-primary .alert-link{color:#151541}.alert-secondary{background-color:#dbdde0;border-color:#cdcfd3;color:#272c33}.alert-secondary hr{border-top-color:#bfc2c7}.alert-secondary .alert-link{color:#111316}.alert-success{background-color:#cdeae1;border-color:#b9e2d5;color:#034e37}.alert-success hr{border-top-color:#a7dbca}.alert-success .alert-link{color:#011d14}.alert-info{background-color:#d3e0fb;border-color:#c2d3f9;color:#13337a}.alert-info hr{border-top-color:#abc2f7}.alert-info .alert-link{color:#0c214e}.alert-warning{background-color:#f7e4cd;border-color:#f4d9b9;color:#713e03}.alert-warning hr{border-top-color:#f1cda3}.alert-warning .alert-link{color:#3f2302}.alert-danger{background-color:#f8d4d4;border-color:#f5c2c2;color:#721414}.alert-danger hr{border-top-color:#f1acac}.alert-danger .alert-link{color:#470c0c}.alert-light{background-color:#fdfdfd;border-color:#fcfcfc;color:#7e7f80}.alert-light hr{border-top-color:#efefef}.alert-light .alert-link{color:#656666}.alert-dark{background-color:#d2d4d7;border-color:#c0c3c7;color:#10151d}.alert-dark hr{border-top-color:#b3b6bb}.alert-dark .alert-link{color:#000}@keyframes progress-bar-stripes{0%{background-position:1rem 0}to{background-position:0 0}}.progress{background-color:#e5e7eb;border-radius:.25rem;font-size:.75rem;height:1rem;line-height:0}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{background-color:#4040c8;color:#fff;flex-direction:column;justify-content:center;text-align:center;transition:width .6s ease;white-space:nowrap}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:1rem 1rem}.progress-bar-animated{animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.media{align-items:flex-start;display:flex}.media-body{flex:1}.list-group{border-radius:.25rem;display:flex;flex-direction:column;margin-bottom:0;padding-left:0}.list-group-item-action{color:#374151;text-align:inherit;width:100%}.list-group-item-action:focus,.list-group-item-action:hover{background-color:#f3f4f6;color:#374151;text-decoration:none;z-index:1}.list-group-item-action:active{background-color:#e5e7eb;color:#111827}.list-group-item{background-color:#fff;border:1px solid rgba(0,0,0,.125);display:block;padding:.75rem 1.25rem;position:relative}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{background-color:#fff;color:#4b5563;pointer-events:none}.list-group-item.active{background-color:#4040c8;border-color:#4040c8;color:#fff;z-index:2}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{border-top-width:1px;margin-top:-1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}@media (min-width:2px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:8px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-md>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:9px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:10px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{background-color:#cacaf0;color:#212168}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{background-color:#b6b6ea;color:#212168}.list-group-item-primary.list-group-item-action.active{background-color:#212168;border-color:#212168;color:#fff}.list-group-item-secondary{background-color:#cdcfd3;color:#272c33}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{background-color:#bfc2c7;color:#272c33}.list-group-item-secondary.list-group-item-action.active{background-color:#272c33;border-color:#272c33;color:#fff}.list-group-item-success{background-color:#b9e2d5;color:#034e37}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{background-color:#a7dbca;color:#034e37}.list-group-item-success.list-group-item-action.active{background-color:#034e37;border-color:#034e37;color:#fff}.list-group-item-info{background-color:#c2d3f9;color:#13337a}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{background-color:#abc2f7;color:#13337a}.list-group-item-info.list-group-item-action.active{background-color:#13337a;border-color:#13337a;color:#fff}.list-group-item-warning{background-color:#f4d9b9;color:#713e03}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{background-color:#f1cda3;color:#713e03}.list-group-item-warning.list-group-item-action.active{background-color:#713e03;border-color:#713e03;color:#fff}.list-group-item-danger{background-color:#f5c2c2;color:#721414}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{background-color:#f1acac;color:#721414}.list-group-item-danger.list-group-item-action.active{background-color:#721414;border-color:#721414;color:#fff}.list-group-item-light{background-color:#fcfcfc;color:#7e7f80}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{background-color:#efefef;color:#7e7f80}.list-group-item-light.list-group-item-action.active{background-color:#7e7f80;border-color:#7e7f80;color:#fff}.list-group-item-dark{background-color:#c0c3c7;color:#10151d}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{background-color:#b3b6bb;color:#10151d}.list-group-item-dark.list-group-item-action.active{background-color:#10151d;border-color:#10151d;color:#fff}.close{color:#000;float:right;font-size:1.5rem;font-weight:600;line-height:1;opacity:.5;text-shadow:0 1px 0 #fff}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{background-color:transparent;border:0;padding:0}a.close.disabled{pointer-events:none}.toast{background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border:1px solid rgba(0,0,0,.1);border-radius:.25rem;box-shadow:0 .25rem .75rem rgba(0,0,0,.1);flex-basis:350px;font-size:.875rem;max-width:350px;opacity:0}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{align-items:center;background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px);color:#4b5563;display:flex;padding:.25rem .75rem}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{display:none;height:100%;left:0;outline:0;overflow:hidden;position:fixed;top:0;width:100%;z-index:1050}.modal-dialog{margin:.5rem;pointer-events:none;position:relative;width:auto}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{align-items:center;display:flex;min-height:calc(100% - 1rem)}.modal-dialog-centered:before{content:"";display:block;height:calc(100vh - 1rem);height:-moz-min-content;height:min-content}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;height:100%;justify-content:center}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable:before{content:none}.modal-content{background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:6px;display:flex;flex-direction:column;outline:0;pointer-events:auto;position:relative;width:100%}.modal-backdrop{background-color:#000;height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:1040}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{align-items:flex-start;border-bottom:1px solid #d1d5db;border-top-left-radius:5px;border-top-right-radius:5px;display:flex;justify-content:space-between;padding:1rem}.modal-header .close{margin:-1rem -1rem -1rem auto;padding:1rem}.modal-title{line-height:1.5;margin-bottom:0}.modal-body{flex:1 1 auto;padding:1rem;position:relative}.modal-footer{align-items:center;border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-top:1px solid #d1d5db;display:flex;flex-wrap:wrap;justify-content:flex-end;padding:.75rem}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{height:50px;overflow:scroll;position:absolute;top:-9999px;width:50px}@media (min-width:2px){.modal-dialog{margin:1.75rem auto;max-width:500px}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered:before{height:calc(100vh - 3.5rem);height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:9px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:10px){.modal-xl{max-width:1140px}}.tooltip{word-wrap:break-word;display:block;font-family:Figtree,sans-serif;font-size:.875rem;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;margin:0;opacity:0;position:absolute;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;z-index:1070}.tooltip.show{opacity:.9}.tooltip .arrow{display:block;height:.4rem;position:absolute;width:.8rem}.tooltip .arrow:before{border-color:transparent;border-style:solid;content:"";position:absolute}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow:before,.bs-tooltip-top .arrow:before{border-top-color:#000;border-width:.4rem .4rem 0;top:0}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{height:.8rem;left:0;width:.4rem}.bs-tooltip-auto[x-placement^=right] .arrow:before,.bs-tooltip-right .arrow:before{border-right-color:#000;border-width:.4rem .4rem .4rem 0;right:0}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.bs-tooltip-bottom .arrow:before{border-bottom-color:#000;border-width:0 .4rem .4rem;bottom:0}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{height:.8rem;right:0;width:.4rem}.bs-tooltip-auto[x-placement^=left] .arrow:before,.bs-tooltip-left .arrow:before{border-left-color:#000;border-width:.4rem 0 .4rem .4rem;left:0}.tooltip-inner{background-color:#000;border-radius:.25rem;color:#fff;max-width:200px;padding:.25rem .5rem;text-align:center}.popover{word-wrap:break-word;background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:6px;font-family:Figtree,sans-serif;font-size:.875rem;font-style:normal;font-weight:400;left:0;letter-spacing:normal;line-break:auto;line-height:1.5;max-width:276px;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;top:0;white-space:normal;word-break:normal;word-spacing:normal;z-index:1060}.popover,.popover .arrow{display:block;position:absolute}.popover .arrow{height:.5rem;margin:0 6px;width:1rem}.popover .arrow:after,.popover .arrow:before{border-color:transparent;border-style:solid;content:"";display:block;position:absolute}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow:before,.bs-popover-top>.arrow:before{border-top-color:rgba(0,0,0,.25);border-width:.5rem .5rem 0;bottom:0}.bs-popover-auto[x-placement^=top]>.arrow:after,.bs-popover-top>.arrow:after{border-top-color:#fff;border-width:.5rem .5rem 0;bottom:1px}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{height:1rem;left:calc(-.5rem - 1px);margin:6px 0;width:.5rem}.bs-popover-auto[x-placement^=right]>.arrow:before,.bs-popover-right>.arrow:before{border-right-color:rgba(0,0,0,.25);border-width:.5rem .5rem .5rem 0;left:0}.bs-popover-auto[x-placement^=right]>.arrow:after,.bs-popover-right>.arrow:after{border-right-color:#fff;border-width:.5rem .5rem .5rem 0;left:1px}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow:before,.bs-popover-bottom>.arrow:before{border-bottom-color:rgba(0,0,0,.25);border-width:0 .5rem .5rem;top:0}.bs-popover-auto[x-placement^=bottom]>.arrow:after,.bs-popover-bottom>.arrow:after{border-bottom-color:#fff;border-width:0 .5rem .5rem;top:1px}.bs-popover-auto[x-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{border-bottom:1px solid #f7f7f7;content:"";display:block;left:50%;margin-left:-.5rem;position:absolute;top:0;width:1rem}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{height:1rem;margin:6px 0;right:calc(-.5rem - 1px);width:.5rem}.bs-popover-auto[x-placement^=left]>.arrow:before,.bs-popover-left>.arrow:before{border-left-color:rgba(0,0,0,.25);border-width:.5rem 0 .5rem .5rem;right:0}.bs-popover-auto[x-placement^=left]>.arrow:after,.bs-popover-left>.arrow:after{border-left-color:#fff;border-width:.5rem 0 .5rem .5rem;right:1px}.popover-header{background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:5px;border-top-right-radius:5px;font-size:1rem;margin-bottom:0;padding:.5rem .75rem}.popover-header:empty{display:none}.popover-body{color:#111827;padding:.5rem .75rem}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{overflow:hidden;position:relative;width:100%}.carousel-inner:after{clear:both;content:"";display:block}.carousel-item{backface-visibility:hidden;display:none;float:left;margin-right:-100%;position:relative;transition:transform .6s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transform:none;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{opacity:1;z-index:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0;transition:opacity 0s .6s;z-index:0}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{align-items:center;background:none;border:0;bottom:0;color:#fff;display:flex;justify-content:center;opacity:.5;padding:0;position:absolute;text-align:center;top:0;transition:opacity .15s ease;width:15%;z-index:1}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;opacity:.9;outline:0;text-decoration:none}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{background:50%/100% 100% no-repeat;display:inline-block;height:20px;width:20px}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m5.25 0-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m2.75 0-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{bottom:0;display:flex;justify-content:center;left:0;list-style:none;margin-left:15%;margin-right:15%;padding-left:0;position:absolute;right:0;z-index:15}.carousel-indicators li{background-clip:padding-box;background-color:#fff;border-bottom:10px solid transparent;border-top:10px solid transparent;box-sizing:content-box;cursor:pointer;flex:0 1 auto;height:3px;margin-left:3px;margin-right:3px;opacity:.5;text-indent:-999px;transition:opacity .6s ease;width:30px}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{bottom:20px;color:#fff;left:15%;padding-bottom:20px;padding-top:20px;position:absolute;right:15%;text-align:center;z-index:10}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{animation:spinner-border .75s linear infinite;border:.25em solid;border-radius:50%;border-right:.25em solid transparent;display:inline-block;height:2rem;vertical-align:-.125em;width:2rem}.spinner-border-sm{border-width:.2em;height:1rem;width:1rem}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{animation:spinner-grow .75s linear infinite;background-color:currentcolor;border-radius:50%;display:inline-block;height:2rem;opacity:0;vertical-align:-.125em;width:2rem}.spinner-grow-sm{height:1rem;width:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#4040c8!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#3030a5!important}.bg-secondary{background-color:#4b5563!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#353c46!important}.bg-success{background-color:#059669!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#036546!important}.bg-info{background-color:#2563eb!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#134cca!important}.bg-warning{background-color:#d97706!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#a75c05!important}.bg-danger{background-color:#dc2626!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#b21d1d!important}.bg-light{background-color:#f3f4f6!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#d6d9e0!important}.bg-dark{background-color:#1f2937!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#0d1116!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #d1d5db!important}.border-top{border-top:1px solid #d1d5db!important}.border-right{border-right:1px solid #d1d5db!important}.border-bottom{border-bottom:1px solid #d1d5db!important}.border-left{border-left:1px solid #d1d5db!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#4040c8!important}.border-secondary{border-color:#4b5563!important}.border-success{border-color:#059669!important}.border-info{border-color:#2563eb!important}.border-warning{border-color:#d97706!important}.border-danger{border-color:#dc2626!important}.border-light{border-color:#f3f4f6!important}.border-dark{border-color:#1f2937!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important}.rounded-lg{border-radius:6px!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix:after{clear:both;content:"";display:block}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:2px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:8px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:9px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:10px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{display:block;overflow:hidden;padding:0;position:relative;width:100%}.embed-responsive:before{content:"";display:block}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{border:0;bottom:0;height:100%;left:0;position:absolute;top:0;width:100%}.embed-responsive-21by9:before{padding-top:42.85714286%}.embed-responsive-16by9:before{padding-top:56.25%}.embed-responsive-4by3:before{padding-top:75%}.embed-responsive-1by1:before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:2px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:8px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:9px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:10px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:2px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:8px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:9px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:10px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.fixed-top{top:0}.fixed-bottom,.fixed-top{left:0;position:fixed;right:0;z-index:1030}.fixed-bottom{bottom:0}@supports (position:sticky){.sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;overflow:visible;position:static;white-space:normal;width:auto}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:2px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:8px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:9px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:10px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link:after{background-color:transparent;bottom:0;content:"";left:0;pointer-events:auto;position:absolute;right:0;top:0;z-index:1}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:2px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:8px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:9px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:10px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:600!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#4040c8!important}a.text-primary:focus,a.text-primary:hover{color:#2a2a92!important}.text-secondary{color:#4b5563!important}a.text-secondary:focus,a.text-secondary:hover{color:#2a3037!important}.text-success{color:#059669!important}a.text-success:focus,a.text-success:hover{color:#034c35!important}.text-info{color:#2563eb!important}a.text-info:focus,a.text-info:hover{color:#1043b3!important}.text-warning{color:#d97706!important}a.text-warning:focus,a.text-warning:hover{color:#8f4e04!important}.text-danger{color:#dc2626!important}a.text-danger:focus,a.text-danger:hover{color:#9c1919!important}.text-light{color:#f3f4f6!important}a.text-light:focus,a.text-light:hover{color:#c7ccd5!important}.text-dark{color:#1f2937!important}a.text-dark:focus,a.text-dark:hover{color:#030506!important}.text-body{color:#111827!important}.text-muted{color:#6b7280!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:hsla(0,0%,100%,.5)!important}.text-hide{background-color:transparent;border:0;color:transparent;font:0/0 a;text-shadow:none}.text-decoration-none{text-decoration:none!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,:after,:before{box-shadow:none!important;text-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #6b7280}blockquote,img,pre,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}.container,body{min-width:9px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #d1d5db!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#e5e7eb}.table .thead-dark th{border-color:#e5e7eb;color:inherit}}.vjs-tree{color:#bfc7d5!important;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.vjs-tree .vjs-tree__content{border-left:1px dotted hsla(0,0%,80%,.28)!important}.vjs-tree .vjs-tree__node{cursor:pointer}.vjs-tree .vjs-tree__node:hover{color:#20a0ff}.vjs-tree .vjs-checkbox{left:-30px;position:absolute}.vjs-tree .vjs-value__boolean,.vjs-tree .vjs-value__null,.vjs-tree .vjs-value__number{color:#a291f5!important}.vjs-tree .vjs-value__string{color:#c3e88d!important}.vjs-tree .vjs-key{color:#c3cbd3!important}.hljs-addition,.hljs-attr,.hljs-keyword,.hljs-selector-tag{color:#13ce66}.hljs-bullet,.hljs-meta,.hljs-name,.hljs-string,.hljs-symbol,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable{color:#c3e88d}.hljs-comment,.hljs-deletion,.hljs-quote{color:#bfcbd9}.hljs-literal,.hljs-number,.hljs-title{color:#a291f5!important}body{padding-bottom:20px}.container{max-width:1440px}html{min-width:1140px}[v-cloak]{display:none}svg.icon{height:1rem;width:1rem}.header{border-bottom:1px solid #e5e7eb}.header .logo{color:#374151;text-decoration:none}.header .logo svg{height:1.7rem;width:1.7rem}.sidebar .nav-item a{border-radius:6px;color:#4b5563;margin-bottom:4px;padding:.5rem .75rem}.sidebar .nav-item a svg{fill:#9ca3af;height:1.25rem;margin-right:15px;width:1.25rem}.sidebar .nav-item a.active,.sidebar .nav-item a:hover{background-color:#e5e7eb;color:#4040c8}.sidebar .nav-item a.active svg{fill:#4040c8}.card{border:none;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1)}.card .bottom-radius{border-bottom-left-radius:6px;border-bottom-right-radius:6px}.card .card-header{background-color:#fff;border-bottom:none;min-height:60px;padding-bottom:.7rem;padding-top:.7rem}.card .card-header .btn-group .btn{padding:.2rem .5rem}.card .card-header .form-control-with-icon{position:relative}.card .card-header .form-control-with-icon .icon-wrapper{align-items:center;bottom:0;display:flex;justify-content:center;left:.75rem;position:absolute;top:0}.card .card-header .form-control-with-icon .icon-wrapper .icon{fill:#6b7280}.card .card-header .form-control-with-icon .form-control{border-radius:9999px;font-size:.875rem;padding-left:2.25rem}.card .table td,.card .table th{padding:.75rem 1.25rem}.card .table th{background-color:#f3f4f6;border-bottom:0;font-size:.875rem;padding:.5rem 1.25rem}.card .table:not(.table-borderless) td{border-top:1px solid #e5e7eb}.card .table.penultimate-column-right td:nth-last-child(2),.card .table.penultimate-column-right th:nth-last-child(2){text-align:right}.card .table td.table-fit,.card .table th.table-fit{white-space:nowrap;width:1%}.fill-text-color{fill:#111827}.fill-danger{fill:#dc2626}.fill-warning{fill:#d97706}.fill-info{fill:#2563eb}.fill-success{fill:#059669}.fill-primary{fill:#4040c8}button:hover .fill-primary{fill:#fff}.btn-outline-primary.active .fill-primary{fill:#f3f4f6}.btn-outline-primary:not(:disabled):not(.disabled).active:focus{box-shadow:none!important}.btn-muted{background:#e5e7eb;color:#4b5563}.btn-muted:focus,.btn-muted:hover{background:#d1d5db;color:#111827}.btn-muted.active{background:#4040c8;color:#fff}.badge-secondary{background:#e5e7eb;color:#4b5563}.badge-success{background:#d1fae5;color:#059669}.badge-info{background:#dbeafe;color:#2563eb}.badge-warning{background:#fef3c7;color:#d97706}.badge-danger{background:#fee2e2;color:#dc2626}.control-action svg{fill:#d1d5db;height:1.2rem;width:1.2rem}.control-action svg:hover{fill:#4f46e5}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.spin{animation:spin 2s linear infinite}.card .nav-pills{background:#fff}.card .nav-pills .nav-link{border-radius:0;color:#4b5563;font-size:.9rem;padding:.75rem 1.25rem}.card .nav-pills .nav-link:focus,.card .nav-pills .nav-link:hover{color:#1f2937}.card .nav-pills .nav-link.active{background:none;border-bottom:2px solid #4f46e5;color:#4f46e5}.list-enter-active:not(.dontanimate){transition:background 1s linear}.list-enter:not(.dontanimate),.list-leave-to:not(.dontanimate){background:#eef2ff}.code-bg .list-enter:not(.dontanimate),.code-bg .list-leave-to:not(.dontanimate){background:#4b5563}#indexScreen td{vertical-align:middle!important}.card-bg-secondary{background:#f3f4f6}.code-bg{background:#292d3e}.disabled-watcher{background:#dc2626;color:#fff;padding:.75rem}.copy-to-clipboard{--tw-text-opacity:1;color:rgb(231 232 242/var(--tw-text-opacity));opacity:.7;outline:2px solid transparent;outline-offset:2px;position:absolute;right:0;top:0;z-index:10} diff --git a/public/vendor/telescope/app.js b/public/vendor/telescope/app.js index 778774921..e5d173afc 100644 --- a/public/vendor/telescope/app.js +++ b/public/vendor/telescope/app.js @@ -1,2 +1,2 @@ /*! For license information please see app.js.LICENSE.txt */ -(()=>{var t,e={2465:(t,e,n)=>{"use strict";var o=Object.freeze({}),p=Array.isArray;function M(t){return null==t}function b(t){return null!=t}function c(t){return!0===t}function r(t){return"string"==typeof t||"number"==typeof t||"symbol"==typeof t||"boolean"==typeof t}function z(t){return"function"==typeof t}function a(t){return null!==t&&"object"==typeof t}var i=Object.prototype.toString;function O(t){return"[object Object]"===i.call(t)}function s(t){return"[object RegExp]"===i.call(t)}function A(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function u(t){return b(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function l(t){return null==t?"":Array.isArray(t)||O(t)&&t.toString===i?JSON.stringify(t,null,2):String(t)}function d(t){var e=parseFloat(t);return isNaN(e)?t:e}function f(t,e){for(var n=Object.create(null),o=t.split(","),p=0;p-1)return t.splice(o,1)}}var v=Object.prototype.hasOwnProperty;function R(t,e){return v.call(t,e)}function m(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var g=/-(\w)/g,L=m((function(t){return t.replace(g,(function(t,e){return e?e.toUpperCase():""}))})),y=m((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),_=/\B([A-Z])/g,N=m((function(t){return t.replace(_,"-$1").toLowerCase()}));var E=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var o=arguments.length;return o?o>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function T(t,e){e=e||0;for(var n=t.length-e,o=new Array(n);n--;)o[n]=t[n+e];return o}function B(t,e){for(var n in e)t[n]=e[n];return t}function C(t){for(var e={},n=0;n0,tt=Q&&Q.indexOf("edge/")>0;Q&&Q.indexOf("android");var et=Q&&/iphone|ipad|ipod|ios/.test(Q);Q&&/chrome\/\d+/.test(Q),Q&&/phantomjs/.test(Q);var nt,ot=Q&&Q.match(/firefox\/(\d+)/),pt={}.watch,Mt=!1;if(K)try{var bt={};Object.defineProperty(bt,"passive",{get:function(){Mt=!0}}),window.addEventListener("test-passive",null,bt)}catch(t){}var ct=function(){return void 0===nt&&(nt=!K&&void 0!==n.g&&(n.g.process&&"server"===n.g.process.env.VUE_ENV)),nt},rt=K&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function zt(t){return"function"==typeof t&&/native code/.test(t.toString())}var at,it="undefined"!=typeof Symbol&&zt(Symbol)&&"undefined"!=typeof Reflect&&zt(Reflect.ownKeys);at="undefined"!=typeof Set&&zt(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var Ot=null;function st(t){void 0===t&&(t=null),t||Ot&&Ot._scope.off(),Ot=t,t&&t._scope.on()}var At=function(){function t(t,e,n,o,p,M,b,c){this.tag=t,this.data=e,this.children=n,this.text=o,this.elm=p,this.ns=void 0,this.context=M,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.componentOptions=b,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=c,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1}return Object.defineProperty(t.prototype,"child",{get:function(){return this.componentInstance},enumerable:!1,configurable:!0}),t}(),ut=function(t){void 0===t&&(t="");var e=new At;return e.text=t,e.isComment=!0,e};function lt(t){return new At(void 0,void 0,void 0,String(t))}function dt(t){var e=new At(t.tag,t.data,t.children&&t.children.slice(),t.text,t.elm,t.context,t.componentOptions,t.asyncFactory);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.fnContext=t.fnContext,e.fnOptions=t.fnOptions,e.fnScopeId=t.fnScopeId,e.asyncMeta=t.asyncMeta,e.isCloned=!0,e}var ft=0,qt=[],ht=function(){for(var t=0;t0&&(Vt((o=Kt(o,"".concat(e||"","_").concat(n)))[0])&&Vt(a)&&(i[z]=lt(a.text+o[0].text),o.shift()),i.push.apply(i,o)):r(o)?Vt(a)?i[z]=lt(a.text+o):""!==o&&i.push(lt(o)):Vt(o)&&Vt(a)?i[z]=lt(a.text+o.text):(c(t._isVList)&&b(o.tag)&&M(o.key)&&b(e)&&(o.key="__vlist".concat(e,"_").concat(n,"__")),i.push(o)));return i}var Qt=1,Jt=2;function Zt(t,e,n,o,M,i){return(p(n)||r(n))&&(M=o,o=n,n=void 0),c(i)&&(M=Jt),function(t,e,n,o,M){if(b(n)&&b(n.__ob__))return ut();b(n)&&b(n.is)&&(e=n.is);if(!e)return ut();0;p(o)&&z(o[0])&&((n=n||{}).scopedSlots={default:o[0]},o.length=0);M===Jt?o=$t(o):M===Qt&&(o=function(t){for(var e=0;e0,c=e?!!e.$stable:!b,r=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(c&&p&&p!==o&&r===p.$key&&!b&&!p.$hasNormal)return p;for(var z in M={},e)e[z]&&"$"!==z[0]&&(M[z]=he(t,n,z,e[z]))}else M={};for(var a in n)a in M||(M[a]=We(n,a));return e&&Object.isExtensible(e)&&(e._normalized=M),Y(M,"$stable",c),Y(M,"$key",r),Y(M,"$hasNormal",b),M}function he(t,e,n,o){var M=function(){var e=Ot;st(t);var n=arguments.length?o.apply(null,arguments):o({}),M=(n=n&&"object"==typeof n&&!p(n)?[n]:$t(n))&&n[0];return st(e),n&&(!M||1===n.length&&M.isComment&&!fe(M))?void 0:n};return o.proxy&&Object.defineProperty(e,n,{get:M,enumerable:!0,configurable:!0}),M}function We(t,e){return function(){return t[e]}}function ve(t){return{get attrs(){if(!t._attrsProxy){var e=t._attrsProxy={};Y(e,"_v_attr_proxy",!0),Re(e,t.$attrs,o,t,"$attrs")}return t._attrsProxy},get listeners(){t._listenersProxy||Re(t._listenersProxy={},t.$listeners,o,t,"$listeners");return t._listenersProxy},get slots(){return function(t){t._slotsProxy||ge(t._slotsProxy={},t.$scopedSlots);return t._slotsProxy}(t)},emit:E(t.$emit,t),expose:function(e){e&&Object.keys(e).forEach((function(n){return Ut(t,e,n)}))}}}function Re(t,e,n,o,p){var M=!1;for(var b in e)b in t?e[b]!==n[b]&&(M=!0):(M=!0,me(t,b,o,p));for(var b in t)b in e||(M=!0,delete t[b]);return M}function me(t,e,n,o){Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){return n[o][e]}})}function ge(t,e){for(var n in e)t[n]=e[n];for(var n in t)n in e||delete t[n]}var Le,ye=null;function _e(t,e){return(t.__esModule||it&&"Module"===t[Symbol.toStringTag])&&(t=t.default),a(t)?e.extend(t):t}function Ne(t){if(p(t))for(var e=0;edocument.createEvent("Event").timeStamp&&(Ye=function(){return $e.now()})}var Ve=function(t,e){if(t.post){if(!e.post)return 1}else if(e.post)return-1;return t.id-e.id};function Ke(){var t,e;for(Ge=Ye(),He=!0,De.sort(Ve),Fe=0;FeFe&&De[n].id>t.id;)n--;De.splice(n+1,0,t)}else De.push(t);je||(je=!0,ln(Ke))}}var Je="watcher";"".concat(Je," callback"),"".concat(Je," getter"),"".concat(Je," cleanup");var Ze;var tn=function(){function t(t){void 0===t&&(t=!1),this.detached=t,this.active=!0,this.effects=[],this.cleanups=[],this.parent=Ze,!t&&Ze&&(this.index=(Ze.scopes||(Ze.scopes=[])).push(this)-1)}return t.prototype.run=function(t){if(this.active){var e=Ze;try{return Ze=this,t()}finally{Ze=e}}else 0},t.prototype.on=function(){Ze=this},t.prototype.off=function(){Ze=this.parent},t.prototype.stop=function(t){if(this.active){var e=void 0,n=void 0;for(e=0,n=this.effects.length;e-1)if(M&&!R(p,"default"))b=!1;else if(""===b||b===N(t)){var r=eo(String,p.type);(r<0||c-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!s(t)&&t.test(e)}function bo(t,e){var n=t.cache,o=t.keys,p=t._vnode;for(var M in n){var b=n[M];if(b){var c=b.name;c&&!e(c)&&co(n,M,o,p)}}}function co(t,e,n,o){var p=t[e];!p||o&&p.tag===o.tag||p.componentInstance.$destroy(),t[e]=null,W(n,e)}!function(t){t.prototype._init=function(t){var e=this;e._uid=Bn++,e._isVue=!0,e.__v_skip=!0,e._scope=new tn(!0),e._scope._vm=!0,t&&t._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),o=e._parentVnode;n.parent=e.parent,n._parentVnode=o;var p=o.componentOptions;n.propsData=p.propsData,n._parentListeners=p.listeners,n._renderChildren=p.children,n._componentTag=p.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=Vn(Cn(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._provided=n?n._provided:Object.create(null),t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Ce(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;var e=t.$options,n=t.$vnode=e._parentVnode,p=n&&n.context;t.$slots=le(e._renderChildren,p),t.$scopedSlots=n?qe(t.$parent,n.data.scopedSlots,t.$slots):o,t._c=function(e,n,o,p){return Zt(t,e,n,o,p,!1)},t.$createElement=function(e,n,o,p){return Zt(t,e,n,o,p,!0)};var M=n&&n.data;wt(t,"$attrs",M&&M.attrs||o,null,!0),wt(t,"$listeners",e._parentListeners||o,null,!0)}(e),Ie(e,"beforeCreate",void 0,!1),function(t){var e=Tn(t.$options.inject,t);e&&(Et(!1),Object.keys(e).forEach((function(n){wt(t,n,e[n])})),Et(!0))}(e),gn(e),function(t){var e=t.$options.provide;if(e){var n=z(e)?e.call(t):e;if(!a(n))return;for(var o=en(t),p=it?Reflect.ownKeys(n):Object.keys(n),M=0;M1?T(n):n;for(var o=T(arguments,1),p='event handler for "'.concat(t,'"'),M=0,b=n.length;MparseInt(this.max)&&co(e,n[0],n,this._vnode),this.vnodeToCache=null}}},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var t in this.cache)co(this.cache,t,this.keys)},mounted:function(){var t=this;this.cacheVNode(),this.$watch("include",(function(e){bo(t,(function(t){return Mo(e,t)}))})),this.$watch("exclude",(function(e){bo(t,(function(t){return!Mo(e,t)}))}))},updated:function(){this.cacheVNode()},render:function(){var t=this.$slots.default,e=Ne(t),n=e&&e.componentOptions;if(n){var o=po(n),p=this.include,M=this.exclude;if(p&&(!o||!Mo(p,o))||M&&o&&Mo(M,o))return e;var b=this.cache,c=this.keys,r=null==e.key?n.Ctor.cid+(n.tag?"::".concat(n.tag):""):e.key;b[r]?(e.componentInstance=b[r].componentInstance,W(c,r),c.push(r)):(this.vnodeToCache=e,this.keyToCache=r),e.data.keepAlive=!0}return e||t&&t[0]}},ao={KeepAlive:zo};!function(t){var e={get:function(){return H}};Object.defineProperty(t,"config",e),t.util={warn:Un,extend:B,mergeOptions:Vn,defineReactive:wt},t.set=St,t.delete=Xt,t.nextTick=ln,t.observable=function(t){return Ct(t),t},t.options=Object.create(null),U.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,B(t.options.components,ao),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=T(arguments,1);return n.unshift(this),z(t.install)?t.install.apply(t,n):z(t)&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=Vn(this.options,t),this}}(t),oo(t),function(t){U.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&O(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&z(n)&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}(no),Object.defineProperty(no.prototype,"$isServer",{get:ct}),Object.defineProperty(no.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(no,"FunctionalRenderContext",{value:wn}),no.version="2.7.14";var io=f("style,class"),Oo=f("input,textarea,option,select,progress"),so=function(t,e,n){return"value"===n&&Oo(t)&&"button"!==e||"selected"===n&&"option"===t||"checked"===n&&"input"===t||"muted"===n&&"video"===t},Ao=f("contenteditable,draggable,spellcheck"),uo=f("events,caret,typing,plaintext-only"),lo=function(t,e){return vo(e)||"false"===e?"false":"contenteditable"===t&&uo(e)?e:"true"},fo=f("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),qo="http://www.w3.org/1999/xlink",ho=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},Wo=function(t){return ho(t)?t.slice(6,t.length):""},vo=function(t){return null==t||!1===t};function Ro(t){for(var e=t.data,n=t,o=t;b(o.componentInstance);)(o=o.componentInstance._vnode)&&o.data&&(e=mo(o.data,e));for(;b(n=n.parent);)n&&n.data&&(e=mo(e,n.data));return function(t,e){if(b(t)||b(e))return go(t,Lo(e));return""}(e.staticClass,e.class)}function mo(t,e){return{staticClass:go(t.staticClass,e.staticClass),class:b(t.class)?[t.class,e.class]:e.class}}function go(t,e){return t?e?t+" "+e:t:e||""}function Lo(t){return Array.isArray(t)?function(t){for(var e,n="",o=0,p=t.length;o-1?Jo(t,e,n):fo(e)?vo(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):Ao(e)?t.setAttribute(e,lo(e,n)):ho(e)?vo(n)?t.removeAttributeNS(qo,Wo(e)):t.setAttributeNS(qo,e,n):Jo(t,e,n)}function Jo(t,e,n){if(vo(n))t.removeAttribute(e);else{if(J&&!Z&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var o=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",o)};t.addEventListener("input",o),t.__ieph=!0}t.setAttribute(e,n)}}var Zo={create:Ko,update:Ko};function tp(t,e){var n=e.elm,o=e.data,p=t.data;if(!(M(o.staticClass)&&M(o.class)&&(M(p)||M(p.staticClass)&&M(p.class)))){var c=Ro(e),r=n._transitionClasses;b(r)&&(c=go(c,Lo(r))),c!==n._prevClass&&(n.setAttribute("class",c),n._prevClass=c)}}var ep,np,op,pp,Mp,bp,cp={create:tp,update:tp},rp=/[\w).+\-_$\]]/;function zp(t){var e,n,o,p,M,b=!1,c=!1,r=!1,z=!1,a=0,i=0,O=0,s=0;for(o=0;o=0&&" "===(u=t.charAt(A));A--);u&&rp.test(u)||(z=!0)}}else void 0===p?(s=o+1,p=t.slice(0,o).trim()):l();function l(){(M||(M=[])).push(t.slice(s,o).trim()),s=o+1}if(void 0===p?p=t.slice(0,o).trim():0!==s&&l(),M)for(o=0;o-1?{exp:t.slice(0,pp),key:'"'+t.slice(pp+1)+'"'}:{exp:t,key:null};np=t,pp=Mp=bp=0;for(;!Lp();)yp(op=gp())?Np(op):91===op&&_p(op);return{exp:t.slice(0,Mp),key:t.slice(Mp+1,bp)}}(t);return null===n.key?"".concat(t,"=").concat(e):"$set(".concat(n.exp,", ").concat(n.key,", ").concat(e,")")}function gp(){return np.charCodeAt(++pp)}function Lp(){return pp>=ep}function yp(t){return 34===t||39===t}function _p(t){var e=1;for(Mp=pp;!Lp();)if(yp(t=gp()))Np(t);else if(91===t&&e++,93===t&&e--,0===e){bp=pp;break}}function Np(t){for(var e=t;!Lp()&&(t=gp())!==e;);}var Ep,Tp="__r",Bp="__c";function Cp(t,e,n){var o=Ep;return function p(){null!==e.apply(null,arguments)&&Xp(t,p,n,o)}}var wp=cn&&!(ot&&Number(ot[1])<=53);function Sp(t,e,n,o){if(wp){var p=Ge,M=e;e=M._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=p||t.timeStamp<=0||t.target.ownerDocument!==document)return M.apply(this,arguments)}}Ep.addEventListener(t,e,Mt?{capture:n,passive:o}:n)}function Xp(t,e,n,o){(o||Ep).removeEventListener(t,e._wrapper||e,n)}function xp(t,e){if(!M(t.data.on)||!M(e.data.on)){var n=e.data.on||{},o=t.data.on||{};Ep=e.elm||t.elm,function(t){if(b(t[Tp])){var e=J?"change":"input";t[e]=[].concat(t[Tp],t[e]||[]),delete t[Tp]}b(t[Bp])&&(t.change=[].concat(t[Bp],t.change||[]),delete t[Bp])}(n),Ft(n,o,Sp,Xp,Cp,e.context),Ep=void 0}}var kp,Ip={create:xp,update:xp,destroy:function(t){return xp(t,Io)}};function Dp(t,e){if(!M(t.data.domProps)||!M(e.data.domProps)){var n,o,p=e.elm,r=t.data.domProps||{},z=e.data.domProps||{};for(n in(b(z.__ob__)||c(z._v_attr_proxy))&&(z=e.data.domProps=B({},z)),r)n in z||(p[n]="");for(n in z){if(o=z[n],"textContent"===n||"innerHTML"===n){if(e.children&&(e.children.length=0),o===r[n])continue;1===p.childNodes.length&&p.removeChild(p.childNodes[0])}if("value"===n&&"PROGRESS"!==p.tagName){p._value=o;var a=M(o)?"":String(o);Pp(p,a)&&(p.value=a)}else if("innerHTML"===n&&No(p.tagName)&&M(p.innerHTML)){(kp=kp||document.createElement("div")).innerHTML="".concat(o,"");for(var i=kp.firstChild;p.firstChild;)p.removeChild(p.firstChild);for(;i.firstChild;)p.appendChild(i.firstChild)}else if(o!==r[n])try{p[n]=o}catch(t){}}}}function Pp(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,o=t._vModifiers;if(b(o)){if(o.number)return d(n)!==d(e);if(o.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Up={create:Dp,update:Dp},jp=m((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var o=t.split(n);o.length>1&&(e[o[0].trim()]=o[1].trim())}})),e}));function Hp(t){var e=Fp(t.style);return t.staticStyle?B(t.staticStyle,e):e}function Fp(t){return Array.isArray(t)?C(t):"string"==typeof t?jp(t):t}var Gp,Yp=/^--/,$p=/\s*!important$/,Vp=function(t,e,n){if(Yp.test(e))t.style.setProperty(e,n);else if($p.test(n))t.style.setProperty(N(e),n.replace($p,""),"important");else{var o=Qp(e);if(Array.isArray(n))for(var p=0,M=n.length;p-1?e.split(tM).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" ".concat(t.getAttribute("class")||""," ");n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function nM(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(tM).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" ".concat(t.getAttribute("class")||""," "),o=" "+e+" ";n.indexOf(o)>=0;)n=n.replace(o," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function oM(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&B(e,pM(t.name||"v")),B(e,t),e}return"string"==typeof t?pM(t):void 0}}var pM=m((function(t){return{enterClass:"".concat(t,"-enter"),enterToClass:"".concat(t,"-enter-to"),enterActiveClass:"".concat(t,"-enter-active"),leaveClass:"".concat(t,"-leave"),leaveToClass:"".concat(t,"-leave-to"),leaveActiveClass:"".concat(t,"-leave-active")}})),MM=K&&!Z,bM="transition",cM="animation",rM="transition",zM="transitionend",aM="animation",iM="animationend";MM&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(rM="WebkitTransition",zM="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(aM="WebkitAnimation",iM="webkitAnimationEnd"));var OM=K?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function sM(t){OM((function(){OM(t)}))}function AM(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),eM(t,e))}function uM(t,e){t._transitionClasses&&W(t._transitionClasses,e),nM(t,e)}function lM(t,e,n){var o=fM(t,e),p=o.type,M=o.timeout,b=o.propCount;if(!p)return n();var c=p===bM?zM:iM,r=0,z=function(){t.removeEventListener(c,a),n()},a=function(e){e.target===t&&++r>=b&&z()};setTimeout((function(){r0&&(n=bM,a=b,i=M.length):e===cM?z>0&&(n=cM,a=z,i=r.length):i=(n=(a=Math.max(b,z))>0?b>z?bM:cM:null)?n===bM?M.length:r.length:0,{type:n,timeout:a,propCount:i,hasTransform:n===bM&&dM.test(o[rM+"Property"])}}function qM(t,e){for(;t.length1}function gM(t,e){!0!==e.data.show&&WM(e)}var LM=function(t){var e,n,o={},z=t.modules,a=t.nodeOps;for(e=0;eA?h(t,M(n[d+1])?null:n[d+1].elm,n,s,d,o):s>d&&v(e,i,A)}(i,u,d,n,z):b(d)?(b(t.text)&&a.setTextContent(i,""),h(i,null,d,0,d.length-1,n)):b(u)?v(u,0,u.length-1):b(t.text)&&a.setTextContent(i,""):t.text!==e.text&&a.setTextContent(i,e.text),b(A)&&b(s=A.hook)&&b(s=s.postpatch)&&s(t,e)}}}function L(t,e,n){if(c(n)&&b(t.parent))t.parent.data.pendingInsert=e;else for(var o=0;o-1,b.selected!==M&&(b.selected=M);else if(x(TM(b),o))return void(t.selectedIndex!==c&&(t.selectedIndex=c));p||(t.selectedIndex=-1)}}function EM(t,e){return e.every((function(e){return!x(e,t)}))}function TM(t){return"_value"in t?t._value:t.value}function BM(t){t.target.composing=!0}function CM(t){t.target.composing&&(t.target.composing=!1,wM(t.target,"input"))}function wM(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function SM(t){return!t.componentInstance||t.data&&t.data.transition?t:SM(t.componentInstance._vnode)}var XM={bind:function(t,e,n){var o=e.value,p=(n=SM(n)).data&&n.data.transition,M=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;o&&p?(n.data.show=!0,WM(n,(function(){t.style.display=M}))):t.style.display=o?M:"none"},update:function(t,e,n){var o=e.value;!o!=!e.oldValue&&((n=SM(n)).data&&n.data.transition?(n.data.show=!0,o?WM(n,(function(){t.style.display=t.__vOriginalDisplay})):vM(n,(function(){t.style.display="none"}))):t.style.display=o?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,o,p){p||(t.style.display=t.__vOriginalDisplay)}},xM={model:yM,show:XM},kM={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function IM(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?IM(Ne(e.children)):t}function DM(t){var e={},n=t.$options;for(var o in n.propsData)e[o]=t[o];var p=n._parentListeners;for(var o in p)e[L(o)]=p[o];return e}function PM(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var UM=function(t){return t.tag||fe(t)},jM=function(t){return"show"===t.name},HM={name:"transition",props:kM,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(UM)).length){0;var o=this.mode;0;var p=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return p;var M=IM(p);if(!M)return p;if(this._leaving)return PM(t,p);var b="__transition-".concat(this._uid,"-");M.key=null==M.key?M.isComment?b+"comment":b+M.tag:r(M.key)?0===String(M.key).indexOf(b)?M.key:b+M.key:M.key;var c=(M.data||(M.data={})).transition=DM(this),z=this._vnode,a=IM(z);if(M.data.directives&&M.data.directives.some(jM)&&(M.data.show=!0),a&&a.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(M,a)&&!fe(a)&&(!a.componentInstance||!a.componentInstance._vnode.isComment)){var i=a.data.transition=B({},c);if("out-in"===o)return this._leaving=!0,Gt(i,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),PM(t,p);if("in-out"===o){if(fe(M))return z;var O,s=function(){O()};Gt(c,"afterEnter",s),Gt(c,"enterCancelled",s),Gt(i,"delayLeave",(function(t){O=t}))}}return p}}},FM=B({tag:String,moveClass:String},kM);delete FM.mode;var GM={props:FM,beforeMount:function(){var t=this,e=this._update;this._update=function(n,o){var p=Se(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,p(),e.call(t,n,o)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),o=this.prevChildren=this.children,p=this.$slots.default||[],M=this.children=[],b=DM(this),c=0;c-1?Bo[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:Bo[t]=/HTMLUnknownElement/.test(e.toString())},B(no.options.directives,xM),B(no.options.components,KM),no.prototype.__patch__=K?LM:w,no.prototype.$mount=function(t,e){return function(t,e,n){var o;t.$el=e,t.$options.render||(t.$options.render=ut),Ie(t,"beforeMount"),o=function(){t._update(t._render(),n)},new vn(t,o,w,{before:function(){t._isMounted&&!t._isDestroyed&&Ie(t,"beforeUpdate")}},!0),n=!1;var p=t._preWatchers;if(p)for(var M=0;M\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,rb=/^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,zb="[a-zA-Z_][\\-\\.0-9_a-zA-Z".concat(F.source,"]*"),ab="((?:".concat(zb,"\\:)?").concat(zb,")"),ib=new RegExp("^<".concat(ab)),Ob=/^\s*(\/?)>/,sb=new RegExp("^<\\/".concat(ab,"[^>]*>")),Ab=/^]+>/i,ub=/^",""":'"',"&":"&"," ":"\n"," ":"\t","'":"'"},hb=/&(?:lt|gt|quot|amp|#39);/g,Wb=/&(?:lt|gt|quot|amp|#39|#10|#9);/g,vb=f("pre,textarea",!0),Rb=function(t,e){return t&&vb(t)&&"\n"===e[0]};function mb(t,e){var n=e?Wb:hb;return t.replace(n,(function(t){return qb[t]}))}function gb(t,e){for(var n,o,p=[],M=e.expectHTML,b=e.isUnaryTag||S,c=e.canBeLeftOpenTag||S,r=0,z=function(){if(n=t,o&&db(o)){var z=0,O=o.toLowerCase(),s=fb[O]||(fb[O]=new RegExp("([\\s\\S]*?)(]*>)","i"));v=t.replace(s,(function(t,n,o){return z=o.length,db(O)||"noscript"===O||(n=n.replace(//g,"$1").replace(//g,"$1")),Rb(O,n)&&(n=n.slice(1)),e.chars&&e.chars(n),""}));r+=t.length-v.length,t=v,i(O,r-z,r)}else{var A=t.indexOf("<");if(0===A){if(ub.test(t)){var u=t.indexOf("--\x3e");if(u>=0)return e.shouldKeepComment&&e.comment&&e.comment(t.substring(4,u),r,r+u+3),a(u+3),"continue"}if(lb.test(t)){var l=t.indexOf("]>");if(l>=0)return a(l+2),"continue"}var d=t.match(Ab);if(d)return a(d[0].length),"continue";var f=t.match(sb);if(f){var q=r;return a(f[0].length),i(f[1],q,r),"continue"}var h=function(){var e=t.match(ib);if(e){var n={tagName:e[1],attrs:[],start:r};a(e[0].length);for(var o=void 0,p=void 0;!(o=t.match(Ob))&&(p=t.match(rb)||t.match(cb));)p.start=r,a(p[0].length),p.end=r,n.attrs.push(p);if(o)return n.unarySlash=o[1],a(o[0].length),n.end=r,n}}();if(h)return function(t){var n=t.tagName,r=t.unarySlash;M&&("p"===o&&bb(n)&&i(o),c(n)&&o===n&&i(n));for(var z=b(n)||!!r,a=t.attrs.length,O=new Array(a),s=0;s=0){for(v=t.slice(A);!(sb.test(v)||ib.test(v)||ub.test(v)||lb.test(v)||(R=v.indexOf("<",1))<0);)A+=R,v=t.slice(A);W=t.substring(0,A)}A<0&&(W=t),W&&a(W.length),e.chars&&W&&e.chars(W,r-W.length,r)}if(t===n)return e.chars&&e.chars(t),"break"};t;){if("break"===z())break}function a(e){r+=e,t=t.substring(e)}function i(t,n,M){var b,c;if(null==n&&(n=r),null==M&&(M=r),t)for(c=t.toLowerCase(),b=p.length-1;b>=0&&p[b].lowerCasedTag!==c;b--);else b=0;if(b>=0){for(var z=p.length-1;z>=b;z--)e.end&&e.end(p[z].tag,n,M);p.length=b,o=b&&p[b-1].tag}else"br"===c?e.start&&e.start(t,[],!0,n,M):"p"===c&&(e.start&&e.start(t,[],!1,n,M),e.end&&e.end(t,n,M))}i()}var Lb,yb,_b,Nb,Eb,Tb,Bb,Cb,wb=/^@|^v-on:/,Sb=/^v-|^@|^:|^#/,Xb=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,xb=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,kb=/^\(|\)$/g,Ib=/^\[.*\]$/,Db=/:(.*)$/,Pb=/^:|^\.|^v-bind:/,Ub=/\.[^.\]]+(?=[^\]]*$)/g,jb=/^v-slot(:|$)|^#/,Hb=/[\r\n]/,Fb=/[ \f\t\r\n]+/g,Gb=m(ob),Yb="_empty_";function $b(t,e,n){return{type:1,tag:t,attrsList:e,attrsMap:ec(e),rawAttrsMap:{},parent:n,children:[]}}function Vb(t,e){Lb=e.warn||ip,Tb=e.isPreTag||S,Bb=e.mustUseProp||S,Cb=e.getTagNamespace||S;var n=e.isReservedTag||S;_b=Op(e.modules,"transformNode"),Nb=Op(e.modules,"preTransformNode"),Eb=Op(e.modules,"postTransformNode"),yb=e.delimiters;var o,p,M=[],b=!1!==e.preserveWhitespace,c=e.whitespace,r=!1,z=!1;function a(t){if(i(t),r||t.processed||(t=Kb(t,e)),M.length||t===o||o.if&&(t.elseif||t.else)&&Jb(o,{exp:t.elseif,block:t}),p&&!t.forbidden)if(t.elseif||t.else)b=t,c=function(t){for(var e=t.length;e--;){if(1===t[e].type)return t[e];t.pop()}}(p.children),c&&c.if&&Jb(c,{exp:b.elseif,block:b});else{if(t.slotScope){var n=t.slotTarget||'"default"';(p.scopedSlots||(p.scopedSlots={}))[n]=t}p.children.push(t),t.parent=p}var b,c;t.children=t.children.filter((function(t){return!t.slotScope})),i(t),t.pre&&(r=!1),Tb(t.tag)&&(z=!1);for(var a=0;ar&&(c.push(M=t.slice(r,p)),b.push(JSON.stringify(M)));var z=zp(o[1].trim());b.push("_s(".concat(z,")")),c.push({"@binding":z}),r=p+o[0].length}return r-1")+("true"===M?":(".concat(e,")"):":_q(".concat(e,",").concat(M,")"))),fp(t,"change","var $$a=".concat(e,",")+"$$el=$event.target,"+"$$c=$$el.checked?(".concat(M,"):(").concat(b,");")+"if(Array.isArray($$a)){"+"var $$v=".concat(o?"_n("+p+")":p,",")+"$$i=_i($$a,$$v);"+"if($$el.checked){$$i<0&&(".concat(mp(e,"$$a.concat([$$v])"),")}")+"else{$$i>-1&&(".concat(mp(e,"$$a.slice(0,$$i).concat($$a.slice($$i+1))"),")}")+"}else{".concat(mp(e,"$$c"),"}"),null,!0)}(t,o,p);else if("input"===M&&"radio"===b)!function(t,e,n){var o=n&&n.number,p=qp(t,"value")||"null";p=o?"_n(".concat(p,")"):p,sp(t,"checked","_q(".concat(e,",").concat(p,")")),fp(t,"change",mp(e,p),null,!0)}(t,o,p);else if("input"===M||"textarea"===M)!function(t,e,n){var o=t.attrsMap.type;0;var p=n||{},M=p.lazy,b=p.number,c=p.trim,r=!M&&"range"!==o,z=M?"change":"range"===o?Tp:"input",a="$event.target.value";c&&(a="$event.target.value.trim()");b&&(a="_n(".concat(a,")"));var i=mp(e,a);r&&(i="if($event.target.composing)return;".concat(i));sp(t,"value","(".concat(e,")")),fp(t,z,i,null,!0),(c||b)&&fp(t,"blur","$forceUpdate()")}(t,o,p);else{if(!H.isReservedTag(M))return Rp(t,o,p),!1}return!0},text:function(t,e){e.value&&sp(t,"textContent","_s(".concat(e.value,")"),e)},html:function(t,e){e.value&&sp(t,"innerHTML","_s(".concat(e.value,")"),e)}},ac={expectHTML:!0,modules:bc,directives:zc,isPreTag:function(t){return"pre"===t},isUnaryTag:pb,mustUseProp:so,canBeLeftOpenTag:Mb,isReservedTag:Eo,getTagNamespace:To,staticKeys:function(t){return t.reduce((function(t,e){return t.concat(e.staticKeys||[])}),[]).join(",")}(bc)},ic=m((function(t){return f("type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap"+(t?","+t:""))}));function Oc(t,e){t&&(cc=ic(e.staticKeys||""),rc=e.isReservedTag||S,sc(t),Ac(t,!1))}function sc(t){if(t.static=function(t){if(2===t.type)return!1;if(3===t.type)return!0;return!(!t.pre&&(t.hasBindings||t.if||t.for||q(t.tag)||!rc(t.tag)||function(t){for(;t.parent;){if("template"!==(t=t.parent).tag)return!1;if(t.for)return!0}return!1}(t)||!Object.keys(t).every(cc)))}(t),1===t.type){if(!rc(t.tag)&&"slot"!==t.tag&&null==t.attrsMap["inline-template"])return;for(var e=0,n=t.children.length;e|^function(?:\s+[\w$]+)?\s*\(/,lc=/\([^)]*?\);*$/,dc=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,fc={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},qc={esc:["Esc","Escape"],tab:"Tab",enter:"Enter",space:[" ","Spacebar"],up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete","Del"]},hc=function(t){return"if(".concat(t,")return null;")},Wc={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:hc("$event.target !== $event.currentTarget"),ctrl:hc("!$event.ctrlKey"),shift:hc("!$event.shiftKey"),alt:hc("!$event.altKey"),meta:hc("!$event.metaKey"),left:hc("'button' in $event && $event.button !== 0"),middle:hc("'button' in $event && $event.button !== 1"),right:hc("'button' in $event && $event.button !== 2")};function vc(t,e){var n=e?"nativeOn:":"on:",o="",p="";for(var M in t){var b=Rc(t[M]);t[M]&&t[M].dynamic?p+="".concat(M,",").concat(b,","):o+='"'.concat(M,'":').concat(b,",")}return o="{".concat(o.slice(0,-1),"}"),p?n+"_d(".concat(o,",[").concat(p.slice(0,-1),"])"):n+o}function Rc(t){if(!t)return"function(){}";if(Array.isArray(t))return"[".concat(t.map((function(t){return Rc(t)})).join(","),"]");var e=dc.test(t.value),n=uc.test(t.value),o=dc.test(t.value.replace(lc,""));if(t.modifiers){var p="",M="",b=[],c=function(e){if(Wc[e])M+=Wc[e],fc[e]&&b.push(e);else if("exact"===e){var n=t.modifiers;M+=hc(["ctrl","shift","alt","meta"].filter((function(t){return!n[t]})).map((function(t){return"$event.".concat(t,"Key")})).join("||"))}else b.push(e)};for(var r in t.modifiers)c(r);b.length&&(p+=function(t){return"if(!$event.type.indexOf('key')&&"+"".concat(t.map(mc).join("&&"),")return null;")}(b)),M&&(p+=M);var z=e?"return ".concat(t.value,".apply(null, arguments)"):n?"return (".concat(t.value,").apply(null, arguments)"):o?"return ".concat(t.value):t.value;return"function($event){".concat(p).concat(z,"}")}return e||n?t.value:"function($event){".concat(o?"return ".concat(t.value):t.value,"}")}function mc(t){var e=parseInt(t,10);if(e)return"$event.keyCode!==".concat(e);var n=fc[t],o=qc[t];return"_k($event.keyCode,"+"".concat(JSON.stringify(t),",")+"".concat(JSON.stringify(n),",")+"$event.key,"+"".concat(JSON.stringify(o))+")"}var gc={on:function(t,e){t.wrapListeners=function(t){return"_g(".concat(t,",").concat(e.value,")")}},bind:function(t,e){t.wrapData=function(n){return"_b(".concat(n,",'").concat(t.tag,"',").concat(e.value,",").concat(e.modifiers&&e.modifiers.prop?"true":"false").concat(e.modifiers&&e.modifiers.sync?",true":"",")")}},cloak:w},Lc=function(t){this.options=t,this.warn=t.warn||ip,this.transforms=Op(t.modules,"transformCode"),this.dataGenFns=Op(t.modules,"genData"),this.directives=B(B({},gc),t.directives);var e=t.isReservedTag||S;this.maybeComponent=function(t){return!!t.component||!e(t.tag)},this.onceId=0,this.staticRenderFns=[],this.pre=!1};function yc(t,e){var n=new Lc(e),o=t?"script"===t.tag?"null":_c(t,n):'_c("div")';return{render:"with(this){return ".concat(o,"}"),staticRenderFns:n.staticRenderFns}}function _c(t,e){if(t.parent&&(t.pre=t.pre||t.parent.pre),t.staticRoot&&!t.staticProcessed)return Nc(t,e);if(t.once&&!t.onceProcessed)return Ec(t,e);if(t.for&&!t.forProcessed)return Cc(t,e);if(t.if&&!t.ifProcessed)return Tc(t,e);if("template"!==t.tag||t.slotTarget||e.pre){if("slot"===t.tag)return function(t,e){var n=t.slotName||'"default"',o=xc(t,e),p="_t(".concat(n).concat(o?",function(){return ".concat(o,"}"):""),M=t.attrs||t.dynamicAttrs?Dc((t.attrs||[]).concat(t.dynamicAttrs||[]).map((function(t){return{name:L(t.name),value:t.value,dynamic:t.dynamic}}))):null,b=t.attrsMap["v-bind"];!M&&!b||o||(p+=",null");M&&(p+=",".concat(M));b&&(p+="".concat(M?"":",null",",").concat(b));return p+")"}(t,e);var n=void 0;if(t.component)n=function(t,e,n){var o=e.inlineTemplate?null:xc(e,n,!0);return"_c(".concat(t,",").concat(wc(e,n)).concat(o?",".concat(o):"",")")}(t.component,t,e);else{var o=void 0,p=e.maybeComponent(t);(!t.plain||t.pre&&p)&&(o=wc(t,e));var M=void 0,b=e.options.bindings;p&&b&&!1!==b.__isScriptSetup&&(M=function(t,e){var n=L(e),o=y(n),p=function(p){return t[e]===p?e:t[n]===p?n:t[o]===p?o:void 0},M=p("setup-const")||p("setup-reactive-const");if(M)return M;var b=p("setup-let")||p("setup-ref")||p("setup-maybe-ref");if(b)return b}(b,t.tag)),M||(M="'".concat(t.tag,"'"));var c=t.inlineTemplate?null:xc(t,e,!0);n="_c(".concat(M).concat(o?",".concat(o):"").concat(c?",".concat(c):"",")")}for(var r=0;r>>0}(b)):"",")")}(t,t.scopedSlots,e),",")),t.model&&(n+="model:{value:".concat(t.model.value,",callback:").concat(t.model.callback,",expression:").concat(t.model.expression,"},")),t.inlineTemplate){var M=function(t,e){var n=t.children[0];0;if(n&&1===n.type){var o=yc(n,e.options);return"inlineTemplate:{render:function(){".concat(o.render,"},staticRenderFns:[").concat(o.staticRenderFns.map((function(t){return"function(){".concat(t,"}")})).join(","),"]}")}}(t,e);M&&(n+="".concat(M,","))}return n=n.replace(/,$/,"")+"}",t.dynamicAttrs&&(n="_b(".concat(n,',"').concat(t.tag,'",').concat(Dc(t.dynamicAttrs),")")),t.wrapData&&(n=t.wrapData(n)),t.wrapListeners&&(n=t.wrapListeners(n)),n}function Sc(t){return 1===t.type&&("slot"===t.tag||t.children.some(Sc))}function Xc(t,e){var n=t.attrsMap["slot-scope"];if(t.if&&!t.ifProcessed&&!n)return Tc(t,e,Xc,"null");if(t.for&&!t.forProcessed)return Cc(t,e,Xc);var o=t.slotScope===Yb?"":String(t.slotScope),p="function(".concat(o,"){")+"return ".concat("template"===t.tag?t.if&&n?"(".concat(t.if,")?").concat(xc(t,e)||"undefined",":undefined"):xc(t,e)||"undefined":_c(t,e),"}"),M=o?"":",proxy:true";return"{key:".concat(t.slotTarget||'"default"',",fn:").concat(p).concat(M,"}")}function xc(t,e,n,o,p){var M=t.children;if(M.length){var b=M[0];if(1===M.length&&b.for&&"template"!==b.tag&&"slot"!==b.tag){var c=n?e.maybeComponent(b)?",1":",0":"";return"".concat((o||_c)(b,e)).concat(c)}var r=n?function(t,e){for(var n=0,o=0;o':'

',Fc.innerHTML.indexOf(" ")>0}var Vc=!!K&&$c(!1),Kc=!!K&&$c(!0),Qc=m((function(t){var e=wo(t);return e&&e.innerHTML})),Jc=no.prototype.$mount;no.prototype.$mount=function(t,e){if((t=t&&wo(t))===document.body||t===document.documentElement)return this;var n=this.$options;if(!n.render){var o=n.template;if(o)if("string"==typeof o)"#"===o.charAt(0)&&(o=Qc(o));else{if(!o.nodeType)return this;o=o.innerHTML}else t&&(o=function(t){if(t.outerHTML)return t.outerHTML;var e=document.createElement("div");return e.appendChild(t.cloneNode(!0)),e.innerHTML}(t));if(o){0;var p=Yc(o,{outputSourceRange:!1,shouldDecodeNewlines:Vc,shouldDecodeNewlinesForHref:Kc,delimiters:n.delimiters,comments:n.comments},this),M=p.render,b=p.staticRenderFns;n.render=M,n.staticRenderFns=b}}return Jc.call(this,t,e)},no.compile=Yc;var Zc=n(2543),tr=n.n(Zc),er=n(4743),nr=n.n(er);const or={computed:{Telescope:function(t){function e(){return t.apply(this,arguments)}return e.toString=function(){return t.toString()},e}((function(){return Telescope}))},methods:{timeAgo:function(t){nr().updateLocale("en",{relativeTime:{future:"in %s",past:"%s ago",s:function(t){return t+"s ago"},ss:"%ds ago",m:"1m ago",mm:"%dm ago",h:"1h ago",hh:"%dh ago",d:"1d ago",dd:"%dd ago",M:"a month ago",MM:"%d months ago",y:"a year ago",yy:"%d years ago"}});var e=nr()().diff(t,"seconds"),n=nr()("2018-01-01").startOf("day").seconds(e);return e>300?nr()(t).fromNow(!0):e<60?n.format("s")+"s ago":n.format("m:ss")+"m ago"},localTime:function(t){return nr()(t).local().format("MMMM Do YYYY, h:mm:ss A")},truncate:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:70;return tr().truncate(t,{length:e,separator:/,? +/})},debouncer:tr().debounce((function(t){return t()}),500),alertError:function(t){this.$root.alert.type="error",this.$root.alert.autoClose=!1,this.$root.alert.message=t},alertSuccess:function(t,e){this.$root.alert.type="success",this.$root.alert.autoClose=e,this.$root.alert.message=t},alertConfirm:function(t,e,n){this.$root.alert.type="confirmation",this.$root.alert.autoClose=!1,this.$root.alert.message=t,this.$root.alert.confirmationProceed=e,this.$root.alert.confirmationCancel=n}}};var pr=n(4335);const Mr=[{path:"/",redirect:"/requests"},{path:"/mail/:id",name:"mail-preview",component:n(583).A},{path:"/mail",name:"mail",component:n(1574).A},{path:"/exceptions/:id",name:"exception-preview",component:n(3781).A},{path:"/exceptions",name:"exceptions",component:n(2977).A},{path:"/dumps",name:"dumps",component:n(93).A},{path:"/logs/:id",name:"log-preview",component:n(5356).A},{path:"/logs",name:"logs",component:n(8170).A},{path:"/notifications/:id",name:"notification-preview",component:n(5841).A},{path:"/notifications",name:"notifications",component:n(4969).A},{path:"/jobs/:id",name:"job-preview",component:n(8813).A},{path:"/jobs",name:"jobs",component:n(1202).A},{path:"/batches/:id",name:"batch-preview",component:n(9622).A},{path:"/batches",name:"batches",component:n(8888).A},{path:"/events/:id",name:"event-preview",component:n(1119).A},{path:"/events",name:"events",component:n(7380).A},{path:"/cache/:id",name:"cache-preview",component:n(7362).A},{path:"/cache",name:"cache",component:n(8613).A},{path:"/queries/:id",name:"query-preview",component:n(1891).A},{path:"/queries",name:"queries",component:n(5873).A},{path:"/models/:id",name:"model-preview",component:n(5333).A},{path:"/models",name:"models",component:n(9440).A},{path:"/requests/:id",name:"request-preview",component:n(8827).A},{path:"/requests",name:"requests",component:n(2806).A},{path:"/commands/:id",name:"command-preview",component:n(4145).A},{path:"/commands",name:"commands",component:n(346).A},{path:"/schedule/:id",name:"schedule-preview",component:n(9655).A},{path:"/schedule",name:"schedule",component:n(3524).A},{path:"/redis/:id",name:"redis-preview",component:n(6393).A},{path:"/redis",name:"redis",component:n(8872).A},{path:"/monitored-tags",name:"monitored-tags",component:n(5441).A},{path:"/gates/:id",name:"gate-preview",component:n(1905).A},{path:"/gates",name:"gates",component:n(2707).A},{path:"/views/:id",name:"view-preview",component:n(6703).A},{path:"/views",name:"views",component:n(3308).A},{path:"/client-requests/:id",name:"client-request-preview",component:n(6204).A},{path:"/client-requests",name:"client-requests",component:n(5899).A}];function br(t,e){for(var n in e)t[n]=e[n];return t}var cr=/[!'()*]/g,rr=function(t){return"%"+t.charCodeAt(0).toString(16)},zr=/%2C/g,ar=function(t){return encodeURIComponent(t).replace(cr,rr).replace(zr,",")};function ir(t){try{return decodeURIComponent(t)}catch(t){0}return t}var Or=function(t){return null==t||"object"==typeof t?t:String(t)};function sr(t){var e={};return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach((function(t){var n=t.replace(/\+/g," ").split("="),o=ir(n.shift()),p=n.length>0?ir(n.join("=")):null;void 0===e[o]?e[o]=p:Array.isArray(e[o])?e[o].push(p):e[o]=[e[o],p]})),e):e}function Ar(t){var e=t?Object.keys(t).map((function(e){var n=t[e];if(void 0===n)return"";if(null===n)return ar(e);if(Array.isArray(n)){var o=[];return n.forEach((function(t){void 0!==t&&(null===t?o.push(ar(e)):o.push(ar(e)+"="+ar(t)))})),o.join("&")}return ar(e)+"="+ar(n)})).filter((function(t){return t.length>0})).join("&"):null;return e?"?"+e:""}var ur=/\/?$/;function lr(t,e,n,o){var p=o&&o.options.stringifyQuery,M=e.query||{};try{M=dr(M)}catch(t){}var b={name:e.name||t&&t.name,meta:t&&t.meta||{},path:e.path||"/",hash:e.hash||"",query:M,params:e.params||{},fullPath:hr(e,p),matched:t?qr(t):[]};return n&&(b.redirectedFrom=hr(n,p)),Object.freeze(b)}function dr(t){if(Array.isArray(t))return t.map(dr);if(t&&"object"==typeof t){var e={};for(var n in t)e[n]=dr(t[n]);return e}return t}var fr=lr(null,{path:"/"});function qr(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function hr(t,e){var n=t.path,o=t.query;void 0===o&&(o={});var p=t.hash;return void 0===p&&(p=""),(n||"/")+(e||Ar)(o)+p}function Wr(t,e,n){return e===fr?t===e:!!e&&(t.path&&e.path?t.path.replace(ur,"")===e.path.replace(ur,"")&&(n||t.hash===e.hash&&vr(t.query,e.query)):!(!t.name||!e.name)&&(t.name===e.name&&(n||t.hash===e.hash&&vr(t.query,e.query)&&vr(t.params,e.params))))}function vr(t,e){if(void 0===t&&(t={}),void 0===e&&(e={}),!t||!e)return t===e;var n=Object.keys(t).sort(),o=Object.keys(e).sort();return n.length===o.length&&n.every((function(n,p){var M=t[n];if(o[p]!==n)return!1;var b=e[n];return null==M||null==b?M===b:"object"==typeof M&&"object"==typeof b?vr(M,b):String(M)===String(b)}))}function Rr(t){for(var e=0;e=0&&(e=t.slice(o),t=t.slice(0,o));var p=t.indexOf("?");return p>=0&&(n=t.slice(p+1),t=t.slice(0,p)),{path:t,query:n,hash:e}}(p.path||""),z=e&&e.path||"/",a=r.path?Lr(r.path,z,n||p.append):z,i=function(t,e,n){void 0===e&&(e={});var o,p=n||sr;try{o=p(t||"")}catch(t){o={}}for(var M in e){var b=e[M];o[M]=Array.isArray(b)?b.map(Or):Or(b)}return o}(r.query,p.query,o&&o.options.parseQuery),O=p.hash||r.hash;return O&&"#"!==O.charAt(0)&&(O="#"+O),{_normalized:!0,path:a,query:i,hash:O}}var $r,Vr=function(){},Kr={name:"RouterLink",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},custom:Boolean,exact:Boolean,exactPath:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,ariaCurrentValue:{type:String,default:"page"},event:{type:[String,Array],default:"click"}},render:function(t){var e=this,n=this.$router,o=this.$route,p=n.resolve(this.to,o,this.append),M=p.location,b=p.route,c=p.href,r={},z=n.options.linkActiveClass,a=n.options.linkExactActiveClass,i=null==z?"router-link-active":z,O=null==a?"router-link-exact-active":a,s=null==this.activeClass?i:this.activeClass,A=null==this.exactActiveClass?O:this.exactActiveClass,u=b.redirectedFrom?lr(null,Yr(b.redirectedFrom),null,n):b;r[A]=Wr(o,u,this.exactPath),r[s]=this.exact||this.exactPath?r[A]:function(t,e){return 0===t.path.replace(ur,"/").indexOf(e.path.replace(ur,"/"))&&(!e.hash||t.hash===e.hash)&&function(t,e){for(var n in e)if(!(n in t))return!1;return!0}(t.query,e.query)}(o,u);var l=r[A]?this.ariaCurrentValue:null,d=function(t){Qr(t)&&(e.replace?n.replace(M,Vr):n.push(M,Vr))},f={click:Qr};Array.isArray(this.event)?this.event.forEach((function(t){f[t]=d})):f[this.event]=d;var q={class:r},h=!this.$scopedSlots.$hasNormal&&this.$scopedSlots.default&&this.$scopedSlots.default({href:c,route:b,navigate:d,isActive:r[s],isExactActive:r[A]});if(h){if(1===h.length)return h[0];if(h.length>1||!h.length)return 0===h.length?t():t("span",{},h)}if("a"===this.tag)q.on=f,q.attrs={href:c,"aria-current":l};else{var W=Jr(this.$slots.default);if(W){W.isStatic=!1;var v=W.data=br({},W.data);for(var R in v.on=v.on||{},v.on){var m=v.on[R];R in f&&(v.on[R]=Array.isArray(m)?m:[m])}for(var g in f)g in v.on?v.on[g].push(f[g]):v.on[g]=d;var L=W.data.attrs=br({},W.data.attrs);L.href=c,L["aria-current"]=l}else q.on=f}return t(this.tag,q,this.$slots.default)}};function Qr(t){if(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||void 0!==t.button&&0!==t.button)){if(t.currentTarget&&t.currentTarget.getAttribute){var e=t.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(e))return}return t.preventDefault&&t.preventDefault(),!0}}function Jr(t){if(t)for(var e,n=0;n-1&&(c.params[O]=n.params[O]);return c.path=Gr(a.path,c.params),r(a,c,b)}if(c.path){c.params={};for(var s=0;s-1}function Ez(t,e){return Nz(t)&&t._isRouter&&(null==e||t.type===e)}function Tz(t,e,n){var o=function(p){p>=t.length?n():t[p]?e(t[p],(function(){o(p+1)})):o(p+1)};o(0)}function Bz(t){return function(e,n,o){var p=!1,M=0,b=null;Cz(t,(function(t,e,n,c){if("function"==typeof t&&void 0===t.cid){p=!0,M++;var r,z=Xz((function(e){var p;((p=e).__esModule||Sz&&"Module"===p[Symbol.toStringTag])&&(e=e.default),t.resolved="function"==typeof e?e:$r.extend(e),n.components[c]=e,--M<=0&&o()})),a=Xz((function(t){var e="Failed to resolve async component "+c+": "+t;b||(b=Nz(t)?t:new Error(e),o(b))}));try{r=t(z,a)}catch(t){a(t)}if(r)if("function"==typeof r.then)r.then(z,a);else{var i=r.component;i&&"function"==typeof i.then&&i.then(z,a)}}})),p||o()}}function Cz(t,e){return wz(t.map((function(t){return Object.keys(t.components).map((function(n){return e(t.components[n],t.instances[n],t,n)}))})))}function wz(t){return Array.prototype.concat.apply([],t)}var Sz="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;function Xz(t){var e=!1;return function(){for(var n=[],o=arguments.length;o--;)n[o]=arguments[o];if(!e)return e=!0,t.apply(this,n)}}var xz=function(t,e){this.router=t,this.base=function(t){if(!t)if(Zr){var e=document.querySelector("base");t=(t=e&&e.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else t="/";"/"!==t.charAt(0)&&(t="/"+t);return t.replace(/\/$/,"")}(e),this.current=fr,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function kz(t,e,n,o){var p=Cz(t,(function(t,o,p,M){var b=function(t,e){"function"!=typeof t&&(t=$r.extend(t));return t.options[e]}(t,e);if(b)return Array.isArray(b)?b.map((function(t){return n(t,o,p,M)})):n(b,o,p,M)}));return wz(o?p.reverse():p)}function Iz(t,e){if(e)return function(){return t.apply(e,arguments)}}xz.prototype.listen=function(t){this.cb=t},xz.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},xz.prototype.onError=function(t){this.errorCbs.push(t)},xz.prototype.transitionTo=function(t,e,n){var o,p=this;try{o=this.router.match(t,this.current)}catch(t){throw this.errorCbs.forEach((function(e){e(t)})),t}var M=this.current;this.confirmTransition(o,(function(){p.updateRoute(o),e&&e(o),p.ensureURL(),p.router.afterHooks.forEach((function(t){t&&t(o,M)})),p.ready||(p.ready=!0,p.readyCbs.forEach((function(t){t(o)})))}),(function(t){n&&n(t),t&&!p.ready&&(Ez(t,mz.redirected)&&M===fr||(p.ready=!0,p.readyErrorCbs.forEach((function(e){e(t)}))))}))},xz.prototype.confirmTransition=function(t,e,n){var o=this,p=this.current;this.pending=t;var M,b,c=function(t){!Ez(t)&&Nz(t)&&o.errorCbs.length&&o.errorCbs.forEach((function(e){e(t)})),n&&n(t)},r=t.matched.length-1,z=p.matched.length-1;if(Wr(t,p)&&r===z&&t.matched[r]===p.matched[z])return this.ensureURL(),t.hash&&Oz(this.router,p,t,!1),c(((b=yz(M=p,t,mz.duplicated,'Avoided redundant navigation to current location: "'+M.fullPath+'".')).name="NavigationDuplicated",b));var a=function(t,e){var n,o=Math.max(t.length,e.length);for(n=0;n0)){var e=this.router,n=e.options.scrollBehavior,o=Wz&&n;o&&this.listeners.push(iz());var p=function(){var n=t.current,p=Pz(t.base);t.current===fr&&p===t._startLocation||t.transitionTo(p,(function(t){o&&Oz(e,t,n,!0)}))};window.addEventListener("popstate",p),this.listeners.push((function(){window.removeEventListener("popstate",p)}))}},e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var o=this,p=this.current;this.transitionTo(t,(function(t){vz(yr(o.base+t.fullPath)),Oz(o.router,t,p,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var o=this,p=this.current;this.transitionTo(t,(function(t){Rz(yr(o.base+t.fullPath)),Oz(o.router,t,p,!1),e&&e(t)}),n)},e.prototype.ensureURL=function(t){if(Pz(this.base)!==this.current.fullPath){var e=yr(this.base+this.current.fullPath);t?vz(e):Rz(e)}},e.prototype.getCurrentLocation=function(){return Pz(this.base)},e}(xz);function Pz(t){var e=window.location.pathname,n=e.toLowerCase(),o=t.toLowerCase();return!t||n!==o&&0!==n.indexOf(yr(o+"/"))||(e=e.slice(t.length)),(e||"/")+window.location.search+window.location.hash}var Uz=function(t){function e(e,n,o){t.call(this,e,n),o&&function(t){var e=Pz(t);if(!/^\/#/.test(e))return window.location.replace(yr(t+"/#"+e)),!0}(this.base)||jz()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;if(!(this.listeners.length>0)){var e=this.router.options.scrollBehavior,n=Wz&&e;n&&this.listeners.push(iz());var o=function(){var e=t.current;jz()&&t.transitionTo(Hz(),(function(o){n&&Oz(t.router,o,e,!0),Wz||Yz(o.fullPath)}))},p=Wz?"popstate":"hashchange";window.addEventListener(p,o),this.listeners.push((function(){window.removeEventListener(p,o)}))}},e.prototype.push=function(t,e,n){var o=this,p=this.current;this.transitionTo(t,(function(t){Gz(t.fullPath),Oz(o.router,t,p,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var o=this,p=this.current;this.transitionTo(t,(function(t){Yz(t.fullPath),Oz(o.router,t,p,!1),e&&e(t)}),n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;Hz()!==e&&(t?Gz(e):Yz(e))},e.prototype.getCurrentLocation=function(){return Hz()},e}(xz);function jz(){var t=Hz();return"/"===t.charAt(0)||(Yz("/"+t),!1)}function Hz(){var t=window.location.href,e=t.indexOf("#");return e<0?"":t=t.slice(e+1)}function Fz(t){var e=window.location.href,n=e.indexOf("#");return(n>=0?e.slice(0,n):e)+"#"+t}function Gz(t){Wz?vz(Fz(t)):window.location.hash=t}function Yz(t){Wz?Rz(Fz(t)):window.location.replace(Fz(t))}var $z=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var o=this;this.transitionTo(t,(function(t){o.stack=o.stack.slice(0,o.index+1).concat(t),o.index++,e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var o=this;this.transitionTo(t,(function(t){o.stack=o.stack.slice(0,o.index).concat(t),e&&e(t)}),n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var o=this.stack[n];this.confirmTransition(o,(function(){var t=e.current;e.index=n,e.updateRoute(o),e.router.afterHooks.forEach((function(e){e&&e(o,t)}))}),(function(t){Ez(t,mz.duplicated)&&(e.index=n)}))}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(xz),Vz=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=oz(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!Wz&&!1!==t.fallback,this.fallback&&(e="hash"),Zr||(e="abstract"),this.mode=e,e){case"history":this.history=new Dz(this,t.base);break;case"hash":this.history=new Uz(this,t.base,this.fallback);break;case"abstract":this.history=new $z(this,t.base)}},Kz={currentRoute:{configurable:!0}};Vz.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},Kz.currentRoute.get=function(){return this.history&&this.history.current},Vz.prototype.init=function(t){var e=this;if(this.apps.push(t),t.$once("hook:destroyed",(function(){var n=e.apps.indexOf(t);n>-1&&e.apps.splice(n,1),e.app===t&&(e.app=e.apps[0]||null),e.app||e.history.teardown()})),!this.app){this.app=t;var n=this.history;if(n instanceof Dz||n instanceof Uz){var o=function(t){n.setupListeners(),function(t){var o=n.current,p=e.options.scrollBehavior;Wz&&p&&"fullPath"in t&&Oz(e,t,o,!1)}(t)};n.transitionTo(n.getCurrentLocation(),o,o)}n.listen((function(t){e.apps.forEach((function(e){e._route=t}))}))}},Vz.prototype.beforeEach=function(t){return Jz(this.beforeHooks,t)},Vz.prototype.beforeResolve=function(t){return Jz(this.resolveHooks,t)},Vz.prototype.afterEach=function(t){return Jz(this.afterHooks,t)},Vz.prototype.onReady=function(t,e){this.history.onReady(t,e)},Vz.prototype.onError=function(t){this.history.onError(t)},Vz.prototype.push=function(t,e,n){var o=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){o.history.push(t,e,n)}));this.history.push(t,e,n)},Vz.prototype.replace=function(t,e,n){var o=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){o.history.replace(t,e,n)}));this.history.replace(t,e,n)},Vz.prototype.go=function(t){this.history.go(t)},Vz.prototype.back=function(){this.go(-1)},Vz.prototype.forward=function(){this.go(1)},Vz.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map((function(t){return Object.keys(t.components).map((function(e){return t.components[e]}))}))):[]},Vz.prototype.resolve=function(t,e,n){var o=Yr(t,e=e||this.history.current,n,this),p=this.match(o,e),M=p.redirectedFrom||p.fullPath,b=function(t,e,n){var o="hash"===n?"#"+e:e;return t?yr(t+"/"+o):o}(this.history.base,M,this.mode);return{location:o,route:p,href:b,normalizedTo:o,resolved:p}},Vz.prototype.getRoutes=function(){return this.matcher.getRoutes()},Vz.prototype.addRoute=function(t,e){this.matcher.addRoute(t,e),this.history.current!==fr&&this.history.transitionTo(this.history.getCurrentLocation())},Vz.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==fr&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(Vz.prototype,Kz);var Qz=Vz;function Jz(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}Vz.install=function t(e){if(!t.installed||$r!==e){t.installed=!0,$r=e;var n=function(t){return void 0!==t},o=function(t,e){var o=t.$options._parentVnode;n(o)&&n(o=o.data)&&n(o=o.registerRouteInstance)&&o(t,e)};e.mixin({beforeCreate:function(){n(this.$options.router)?(this._routerRoot=this,this._router=this.$options.router,this._router.init(this),e.util.defineReactive(this,"_route",this._router.history.current)):this._routerRoot=this.$parent&&this.$parent._routerRoot||this,o(this,this)},destroyed:function(){o(this)}}),Object.defineProperty(e.prototype,"$router",{get:function(){return this._routerRoot._router}}),Object.defineProperty(e.prototype,"$route",{get:function(){return this._routerRoot._route}}),e.component("RouterView",mr),e.component("RouterLink",Kr);var p=e.config.optionMergeStrategies;p.beforeRouteEnter=p.beforeRouteLeave=p.beforeRouteUpdate=p.created}},Vz.version="3.6.5",Vz.isNavigationFailure=Ez,Vz.NavigationFailureType=mz,Vz.START_LOCATION=fr,Zr&&window.Vue&&window.Vue.use(Vz);var Zz=n(7551),ta=n.n(Zz),ea=n(5072),na=n.n(ea),oa=n(2930),pa={insert:"head",singleton:!1};na()(oa.A,pa);oa.A.locals;n(2754);var Ma=document.head.querySelector('meta[name="csrf-token"]');Ma&&(pr.A.defaults.headers.common["X-CSRF-TOKEN"]=Ma.content),no.use(Qz),window.Popper=n(8851).default,nr().tz.setDefault(Telescope.timezone),window.Telescope.basePath="/"+window.Telescope.path;var ba=window.Telescope.basePath+"/";""!==window.Telescope.path&&"/"!==window.Telescope.path||(ba="/",window.Telescope.basePath="");var ca=new Qz({routes:Mr,mode:"history",base:ba});no.component("vue-json-pretty",ta()),no.component("related-entries",n(8117).A),no.component("index-screen",n(4980).A),no.component("preview-screen",n(9416).A),no.component("alert",n(4445).A),no.component("copy-clipboard",n(1858).A),no.mixin(or),new no({el:"#telescope",router:ca,data:function(){return{alert:{type:null,autoClose:0,message:"",confirmationProceed:null,confirmationCancel:null},autoLoadsNewEntries:"1"===localStorage.autoLoadsNewEntries,recording:Telescope.recording}},created:function(){window.addEventListener("keydown",this.keydownListener)},destroyed:function(){window.removeEventListener("keydown",this.keydownListener)},methods:{autoLoadNewEntries:function(){this.autoLoadsNewEntries?(this.autoLoadsNewEntries=!1,localStorage.autoLoadsNewEntries=0):(this.autoLoadsNewEntries=!0,localStorage.autoLoadsNewEntries=1)},toggleRecording:function(){pr.A.post(Telescope.basePath+"/telescope-api/toggle-recording"),window.Telescope.recording=!Telescope.recording,this.recording=!this.recording},clearEntries:function(){(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&!confirm("Are you sure you want to delete all Telescope data?")||pr.A.delete(Telescope.basePath+"/telescope-api/entries").then((function(t){return location.reload()}))},keydownListener:function(t){t.metaKey&&"k"===t.key&&this.clearEntries(!1)}}})},8217:(t,e,n)=>{"use strict";n.d(e,{A:()=>o});const o={methods:{cacheActionTypeClass:function(t){return"hit"===t?"success":"set"===t?"info":"forget"===t?"warning":"missed"===t?"danger":void 0},composerTypeClass:function(t){return"composer"===t?"info":"creator"===t?"success":void 0},gateResultClass:function(t){return"allowed"===t?"success":"denied"===t?"danger":void 0},jobStatusClass:function(t){return"pending"===t?"secondary":"processed"===t?"success":"failed"===t?"danger":void 0},logLevelClass:function(t){return"debug"===t?"success":"info"===t?"info":"notice"===t?"secondary":"warning"===t?"warning":"error"===t||"critical"===t||"alert"===t||"emergency"===t?"danger":void 0},modelActionClass:function(t){return"created"==t?"success":"updated"==t?"info":"retrieved"==t?"secondary":"deleted"==t||"forceDeleted"==t?"danger":void 0},requestStatusClass:function(t){return t?t<300?"success":t<400?"info":t<500?"warning":t>=500?"danger":void 0:"danger"},requestMethodClass:function(t){return"GET"==t||"OPTIONS"==t?"secondary":"POST"==t||"PATCH"==t||"PUT"==t?"info":"DELETE"==t?"danger":void 0}}}},7526:(t,e)=>{"use strict";e.byteLength=function(t){var e=c(t),n=e[0],o=e[1];return 3*(n+o)/4-o},e.toByteArray=function(t){var e,n,M=c(t),b=M[0],r=M[1],z=new p(function(t,e,n){return 3*(e+n)/4-n}(0,b,r)),a=0,i=r>0?b-4:b;for(n=0;n>16&255,z[a++]=e>>8&255,z[a++]=255&e;2===r&&(e=o[t.charCodeAt(n)]<<2|o[t.charCodeAt(n+1)]>>4,z[a++]=255&e);1===r&&(e=o[t.charCodeAt(n)]<<10|o[t.charCodeAt(n+1)]<<4|o[t.charCodeAt(n+2)]>>2,z[a++]=e>>8&255,z[a++]=255&e);return z},e.fromByteArray=function(t){for(var e,o=t.length,p=o%3,M=[],b=16383,c=0,z=o-p;cz?z:c+b));1===p?(e=t[o-1],M.push(n[e>>2]+n[e<<4&63]+"==")):2===p&&(e=(t[o-2]<<8)+t[o-1],M.push(n[e>>10]+n[e>>4&63]+n[e<<2&63]+"="));return M.join("")};for(var n=[],o=[],p="undefined"!=typeof Uint8Array?Uint8Array:Array,M="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b=0;b<64;++b)n[b]=M[b],o[M.charCodeAt(b)]=b;function c(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var n=t.indexOf("=");return-1===n&&(n=e),[n,n===e?0:4-n%4]}function r(t,e,o){for(var p,M,b=[],c=e;c>18&63]+n[M>>12&63]+n[M>>6&63]+n[63&M]);return b.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},2754:function(t,e,n){!function(t,e,n){"use strict";function o(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var p=o(e),M=o(n);function b(t,e){for(var n=0;n=b)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};f.jQueryDetection(),d();var q="alert",h="4.6.2",W="bs.alert",v="."+W,R=".data-api",m=p.default.fn[q],g="alert",L="fade",y="show",_="close"+v,N="closed"+v,E="click"+v+R,T='[data-dismiss="alert"]',B=function(){function t(t){this._element=t}var e=t.prototype;return e.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},e.dispose=function(){p.default.removeData(this._element,W),this._element=null},e._getRootElement=function(t){var e=f.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=p.default(t).closest("."+g)[0]),n},e._triggerCloseEvent=function(t){var e=p.default.Event(_);return p.default(t).trigger(e),e},e._removeElement=function(t){var e=this;if(p.default(t).removeClass(y),p.default(t).hasClass(L)){var n=f.getTransitionDurationFromElement(t);p.default(t).one(f.TRANSITION_END,(function(n){return e._destroyElement(t,n)})).emulateTransitionEnd(n)}else this._destroyElement(t)},e._destroyElement=function(t){p.default(t).detach().trigger(N).remove()},t._jQueryInterface=function(e){return this.each((function(){var n=p.default(this),o=n.data(W);o||(o=new t(this),n.data(W,o)),"close"===e&&o[e](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},c(t,null,[{key:"VERSION",get:function(){return h}}]),t}();p.default(document).on(E,T,B._handleDismiss(new B)),p.default.fn[q]=B._jQueryInterface,p.default.fn[q].Constructor=B,p.default.fn[q].noConflict=function(){return p.default.fn[q]=m,B._jQueryInterface};var C="button",w="4.6.2",S="bs.button",X="."+S,x=".data-api",k=p.default.fn[C],I="active",D="btn",P="focus",U="click"+X+x,j="focus"+X+x+" blur"+X+x,H="load"+X+x,F='[data-toggle^="button"]',G='[data-toggle="buttons"]',Y='[data-toggle="button"]',$='[data-toggle="buttons"] .btn',V='input:not([type="hidden"])',K=".active",Q=".btn",J=function(){function t(t){this._element=t,this.shouldAvoidTriggerChange=!1}var e=t.prototype;return e.toggle=function(){var t=!0,e=!0,n=p.default(this._element).closest(G)[0];if(n){var o=this._element.querySelector(V);if(o){if("radio"===o.type)if(o.checked&&this._element.classList.contains(I))t=!1;else{var M=n.querySelector(K);M&&p.default(M).removeClass(I)}t&&("checkbox"!==o.type&&"radio"!==o.type||(o.checked=!this._element.classList.contains(I)),this.shouldAvoidTriggerChange||p.default(o).trigger("change")),o.focus(),e=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(I)),t&&p.default(this._element).toggleClass(I))},e.dispose=function(){p.default.removeData(this._element,S),this._element=null},t._jQueryInterface=function(e,n){return this.each((function(){var o=p.default(this),M=o.data(S);M||(M=new t(this),o.data(S,M)),M.shouldAvoidTriggerChange=n,"toggle"===e&&M[e]()}))},c(t,null,[{key:"VERSION",get:function(){return w}}]),t}();p.default(document).on(U,F,(function(t){var e=t.target,n=e;if(p.default(e).hasClass(D)||(e=p.default(e).closest(Q)[0]),!e||e.hasAttribute("disabled")||e.classList.contains("disabled"))t.preventDefault();else{var o=e.querySelector(V);if(o&&(o.hasAttribute("disabled")||o.classList.contains("disabled")))return void t.preventDefault();"INPUT"!==n.tagName&&"LABEL"===e.tagName||J._jQueryInterface.call(p.default(e),"toggle","INPUT"===n.tagName)}})).on(j,F,(function(t){var e=p.default(t.target).closest(Q)[0];p.default(e).toggleClass(P,/^focus(in)?$/.test(t.type))})),p.default(window).on(H,(function(){for(var t=[].slice.call(document.querySelectorAll($)),e=0,n=t.length;e0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var e=t.prototype;return e.next=function(){this._isSliding||this._slide(dt)},e.nextWhenVisible=function(){var t=p.default(this._element);!document.hidden&&t.is(":visible")&&"hidden"!==t.css("visibility")&&this.next()},e.prev=function(){this._isSliding||this._slide(ft)},e.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(kt)&&(f.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},e.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},e.to=function(t){var e=this;this._activeElement=this._element.querySelector(St);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)p.default(this._element).one(vt,(function(){return e.to(t)}));else{if(n===t)return this.pause(),void this.cycle();var o=t>n?dt:ft;this._slide(o,this._items[t])}},e.dispose=function(){p.default(this._element).off(nt),p.default.removeData(this._element,et),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},e._getConfig=function(t){return t=r({},Ut,t),f.typeCheckConfig(Z,t,jt),t},e._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=rt)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},e._addEventListeners=function(){var t=this;this._config.keyboard&&p.default(this._element).on(Rt,(function(e){return t._keydown(e)})),"hover"===this._config.pause&&p.default(this._element).on(mt,(function(e){return t.pause(e)})).on(gt,(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},e._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var e=function(e){t._pointerEvent&&Ht[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},n=function(e){t.touchDeltaX=e.originalEvent.touches&&e.originalEvent.touches.length>1?0:e.originalEvent.touches[0].clientX-t.touchStartX},o=function(e){t._pointerEvent&&Ht[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),ct+t._config.interval))};p.default(this._element.querySelectorAll(xt)).on(Tt,(function(t){return t.preventDefault()})),this._pointerEvent?(p.default(this._element).on(Nt,(function(t){return e(t)})),p.default(this._element).on(Et,(function(t){return o(t)})),this._element.classList.add(lt)):(p.default(this._element).on(Lt,(function(t){return e(t)})),p.default(this._element).on(yt,(function(t){return n(t)})),p.default(this._element).on(_t,(function(t){return o(t)})))}},e._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case Mt:t.preventDefault(),this.prev();break;case bt:t.preventDefault(),this.next()}},e._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(Xt)):[],this._items.indexOf(t)},e._getItemByDirection=function(t,e){var n=t===dt,o=t===ft,p=this._getItemIndex(e),M=this._items.length-1;if((o&&0===p||n&&p===M)&&!this._config.wrap)return e;var b=(p+(t===ft?-1:1))%this._items.length;return-1===b?this._items[this._items.length-1]:this._items[b]},e._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),o=this._getItemIndex(this._element.querySelector(St)),M=p.default.Event(Wt,{relatedTarget:t,direction:e,from:o,to:n});return p.default(this._element).trigger(M),M},e._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(wt));p.default(e).removeClass(at);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&p.default(n).addClass(at)}},e._updateInterval=function(){var t=this._activeElement||this._element.querySelector(St);if(t){var e=parseInt(t.getAttribute("data-interval"),10);e?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=e):this._config.interval=this._config.defaultInterval||this._config.interval}},e._slide=function(t,e){var n,o,M,b=this,c=this._element.querySelector(St),r=this._getItemIndex(c),z=e||c&&this._getItemByDirection(t,c),a=this._getItemIndex(z),i=Boolean(this._interval);if(t===dt?(n=st,o=At,M=qt):(n=Ot,o=ut,M=ht),z&&p.default(z).hasClass(at))this._isSliding=!1;else if(!this._triggerSlideEvent(z,M).isDefaultPrevented()&&c&&z){this._isSliding=!0,i&&this.pause(),this._setActiveIndicatorElement(z),this._activeElement=z;var O=p.default.Event(vt,{relatedTarget:z,direction:M,from:r,to:a});if(p.default(this._element).hasClass(it)){p.default(z).addClass(o),f.reflow(z),p.default(c).addClass(n),p.default(z).addClass(n);var s=f.getTransitionDurationFromElement(c);p.default(c).one(f.TRANSITION_END,(function(){p.default(z).removeClass(n+" "+o).addClass(at),p.default(c).removeClass(at+" "+o+" "+n),b._isSliding=!1,setTimeout((function(){return p.default(b._element).trigger(O)}),0)})).emulateTransitionEnd(s)}else p.default(c).removeClass(at),p.default(z).addClass(at),this._isSliding=!1,p.default(this._element).trigger(O);i&&this.cycle()}},t._jQueryInterface=function(e){return this.each((function(){var n=p.default(this).data(et),o=r({},Ut,p.default(this).data());"object"==typeof e&&(o=r({},o,e));var M="string"==typeof e?e:o.slide;if(n||(n=new t(this,o),p.default(this).data(et,n)),"number"==typeof e)n.to(e);else if("string"==typeof M){if(void 0===n[M])throw new TypeError('No method named "'+M+'"');n[M]()}else o.interval&&o.ride&&(n.pause(),n.cycle())}))},t._dataApiClickHandler=function(e){var n=f.getSelectorFromElement(this);if(n){var o=p.default(n)[0];if(o&&p.default(o).hasClass(zt)){var M=r({},p.default(o).data(),p.default(this).data()),b=this.getAttribute("data-slide-to");b&&(M.interval=!1),t._jQueryInterface.call(p.default(o),M),b&&p.default(o).data(et).to(b),e.preventDefault()}}},c(t,null,[{key:"VERSION",get:function(){return tt}},{key:"Default",get:function(){return Ut}}]),t}();p.default(document).on(Ct,Dt,Ft._dataApiClickHandler),p.default(window).on(Bt,(function(){for(var t=[].slice.call(document.querySelectorAll(Pt)),e=0,n=t.length;e0&&(this._selector=b,this._triggerArray.push(M))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var e=t.prototype;return e.toggle=function(){p.default(this._element).hasClass(Jt)?this.hide():this.show()},e.show=function(){var e,n,o=this;if(!(this._isTransitioning||p.default(this._element).hasClass(Jt)||(this._parent&&0===(e=[].slice.call(this._parent.querySelectorAll(ze)).filter((function(t){return"string"==typeof o._config.parent?t.getAttribute("data-parent")===o._config.parent:t.classList.contains(Zt)}))).length&&(e=null),e&&(n=p.default(e).not(this._selector).data($t))&&n._isTransitioning))){var M=p.default.Event(pe);if(p.default(this._element).trigger(M),!M.isDefaultPrevented()){e&&(t._jQueryInterface.call(p.default(e).not(this._selector),"hide"),n||p.default(e).data($t,null));var b=this._getDimension();p.default(this._element).removeClass(Zt).addClass(te),this._element.style[b]=0,this._triggerArray.length&&p.default(this._triggerArray).removeClass(ee).attr("aria-expanded",!0),this.setTransitioning(!0);var c=function(){p.default(o._element).removeClass(te).addClass(Zt+" "+Jt),o._element.style[b]="",o.setTransitioning(!1),p.default(o._element).trigger(Me)},r="scroll"+(b[0].toUpperCase()+b.slice(1)),z=f.getTransitionDurationFromElement(this._element);p.default(this._element).one(f.TRANSITION_END,c).emulateTransitionEnd(z),this._element.style[b]=this._element[r]+"px"}}},e.hide=function(){var t=this;if(!this._isTransitioning&&p.default(this._element).hasClass(Jt)){var e=p.default.Event(be);if(p.default(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",f.reflow(this._element),p.default(this._element).addClass(te).removeClass(Zt+" "+Jt);var o=this._triggerArray.length;if(o>0)for(var M=0;M0},e._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t._config.offset(e.offsets,t._element)),e}:e.offset=this._config.offset,e},e._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),r({},t,this._config.popperConfig)},t._jQueryInterface=function(e){return this.each((function(){var n=p.default(this).data(le);if(n||(n=new t(this,"object"==typeof e?e:null),p.default(this).data(le,n)),"string"==typeof e){if(void 0===n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},t._clearMenus=function(e){if(!e||e.which!==ge&&("keyup"!==e.type||e.which===ve))for(var n=[].slice.call(document.querySelectorAll(Ue)),o=0,M=n.length;o0&&b--,e.which===me&&bdocument.documentElement.clientHeight;n||(this._element.style.overflowY="hidden"),this._element.classList.add(ln);var o=f.getTransitionDurationFromElement(this._dialog);p.default(this._element).off(f.TRANSITION_END),p.default(this._element).one(f.TRANSITION_END,(function(){t._element.classList.remove(ln),n||p.default(t._element).one(f.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,o)})).emulateTransitionEnd(o),this._element.focus()}},e._showElement=function(t){var e=this,n=p.default(this._element).hasClass(An),o=this._dialog?this._dialog.querySelector(En):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),p.default(this._dialog).hasClass(zn)&&o?o.scrollTop=0:this._element.scrollTop=0,n&&f.reflow(this._element),p.default(this._element).addClass(un),this._config.focus&&this._enforceFocus();var M=p.default.Event(Wn,{relatedTarget:t}),b=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,p.default(e._element).trigger(M)};if(n){var c=f.getTransitionDurationFromElement(this._dialog);p.default(this._dialog).one(f.TRANSITION_END,b).emulateTransitionEnd(c)}else b()},e._enforceFocus=function(){var t=this;p.default(document).off(vn).on(vn,(function(e){document!==e.target&&t._element!==e.target&&0===p.default(t._element).has(e.target).length&&t._element.focus()}))},e._setEscapeEvent=function(){var t=this;this._isShown?p.default(this._element).on(gn,(function(e){t._config.keyboard&&e.which===rn?(e.preventDefault(),t.hide()):t._config.keyboard||e.which!==rn||t._triggerBackdropTransition()})):this._isShown||p.default(this._element).off(gn)},e._setResizeEvent=function(){var t=this;this._isShown?p.default(window).on(Rn,(function(e){return t.handleUpdate(e)})):p.default(window).off(Rn)},e._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){p.default(document.body).removeClass(sn),t._resetAdjustments(),t._resetScrollbar(),p.default(t._element).trigger(qn)}))},e._removeBackdrop=function(){this._backdrop&&(p.default(this._backdrop).remove(),this._backdrop=null)},e._showBackdrop=function(t){var e=this,n=p.default(this._element).hasClass(An)?An:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className=On,n&&this._backdrop.classList.add(n),p.default(this._backdrop).appendTo(document.body),p.default(this._element).on(mn,(function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._triggerBackdropTransition():e.hide())})),n&&f.reflow(this._backdrop),p.default(this._backdrop).addClass(un),!t)return;if(!n)return void t();var o=f.getTransitionDurationFromElement(this._backdrop);p.default(this._backdrop).one(f.TRANSITION_END,t).emulateTransitionEnd(o)}else if(!this._isShown&&this._backdrop){p.default(this._backdrop).removeClass(un);var M=function(){e._removeBackdrop(),t&&t()};if(p.default(this._element).hasClass(An)){var b=f.getTransitionDurationFromElement(this._backdrop);p.default(this._backdrop).one(f.TRANSITION_END,M).emulateTransitionEnd(b)}else M()}else t&&t()},e._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",customClass:"",sanitize:!0,sanitizeFn:null,whiteList:In,popperConfig:null},ao={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},io={HIDE:"hide"+Yn,HIDDEN:"hidden"+Yn,SHOW:"show"+Yn,SHOWN:"shown"+Yn,INSERTED:"inserted"+Yn,CLICK:"click"+Yn,FOCUSIN:"focusin"+Yn,FOCUSOUT:"focusout"+Yn,MOUSEENTER:"mouseenter"+Yn,MOUSELEAVE:"mouseleave"+Yn},Oo=function(){function t(t,e){if(void 0===M.default)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var e=t.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=p.default(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),p.default(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(p.default(this.getTipElement()).hasClass(Zn))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),p.default.removeData(this.element,this.constructor.DATA_KEY),p.default(this.element).off(this.constructor.EVENT_KEY),p.default(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&p.default(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===p.default(this.element).css("display"))throw new Error("Please use show on visible elements");var e=p.default.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){p.default(this.element).trigger(e);var n=f.findShadowRoot(this.element),o=p.default.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!o)return;var b=this.getTipElement(),c=f.getUID(this.constructor.NAME);b.setAttribute("id",c),this.element.setAttribute("aria-describedby",c),this.setContent(),this.config.animation&&p.default(b).addClass(Jn);var r="function"==typeof this.config.placement?this.config.placement.call(this,b,this.element):this.config.placement,z=this._getAttachment(r);this.addAttachmentClass(z);var a=this._getContainer();p.default(b).data(this.constructor.DATA_KEY,this),p.default.contains(this.element.ownerDocument.documentElement,this.tip)||p.default(b).appendTo(a),p.default(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new M.default(this.element,b,this._getPopperConfig(z)),p.default(b).addClass(Zn),p.default(b).addClass(this.config.customClass),"ontouchstart"in document.documentElement&&p.default(document.body).children().on("mouseover",null,p.default.noop);var i=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,p.default(t.element).trigger(t.constructor.Event.SHOWN),e===eo&&t._leave(null,t)};if(p.default(this.tip).hasClass(Jn)){var O=f.getTransitionDurationFromElement(this.tip);p.default(this.tip).one(f.TRANSITION_END,i).emulateTransitionEnd(O)}else i()}},e.hide=function(t){var e=this,n=this.getTipElement(),o=p.default.Event(this.constructor.Event.HIDE),M=function(){e._hoverState!==to&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),p.default(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(p.default(this.element).trigger(o),!o.isDefaultPrevented()){if(p.default(n).removeClass(Zn),"ontouchstart"in document.documentElement&&p.default(document.body).children().off("mouseover",null,p.default.noop),this._activeTrigger[bo]=!1,this._activeTrigger[Mo]=!1,this._activeTrigger[po]=!1,p.default(this.tip).hasClass(Jn)){var b=f.getTransitionDurationFromElement(n);p.default(n).one(f.TRANSITION_END,M).emulateTransitionEnd(b)}else M();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(t){p.default(this.getTipElement()).addClass(Vn+"-"+t)},e.getTipElement=function(){return this.tip=this.tip||p.default(this.config.template)[0],this.tip},e.setContent=function(){var t=this.getTipElement();this.setElementContent(p.default(t.querySelectorAll(no)),this.getTitle()),p.default(t).removeClass(Jn+" "+Zn)},e.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=jn(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?p.default(e).parent().is(t)||t.empty().append(e):t.text(p.default(e).text())},e.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},e._getPopperConfig=function(t){var e=this;return r({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:oo},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t.config.offset(e.offsets,t.element)),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:f.isElement(this.config.container)?p.default(this.config.container):p.default(document).find(this.config.container)},e._getAttachment=function(t){return ro[t.toUpperCase()]},e._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)p.default(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if(e!==co){var n=e===po?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,o=e===po?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;p.default(t.element).on(n,t.config.selector,(function(e){return t._enter(e)})).on(o,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},p.default(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=r({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||p.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),p.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Mo:po]=!0),p.default(e.getTipElement()).hasClass(Zn)||e._hoverState===to?e._hoverState=to:(clearTimeout(e._timeout),e._hoverState=to,e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){e._hoverState===to&&e.show()}),e.config.delay.show):e.show())},e._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||p.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),p.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Mo:po]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=eo,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){e._hoverState===eo&&e.hide()}),e.config.delay.hide):e.hide())},e._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},e._getConfig=function(t){var e=p.default(this.element).data();return Object.keys(e).forEach((function(t){-1!==Qn.indexOf(t)&&delete e[t]})),"number"==typeof(t=r({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),f.typeCheckConfig(Hn,t,this.constructor.DefaultType),t.sanitize&&(t.template=jn(t.template,t.whiteList,t.sanitizeFn)),t},e._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},e._cleanTipClass=function(){var t=p.default(this.getTipElement()),e=t.attr("class").match(Kn);null!==e&&e.length&&t.removeClass(e.join(""))},e._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},e._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(p.default(t).removeClass(Jn),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},t._jQueryInterface=function(e){return this.each((function(){var n=p.default(this),o=n.data(Gn),M="object"==typeof e&&e;if((o||!/dispose|hide/.test(e))&&(o||(o=new t(this,M),n.data(Gn,o)),"string"==typeof e)){if(void 0===o[e])throw new TypeError('No method named "'+e+'"');o[e]()}}))},c(t,null,[{key:"VERSION",get:function(){return Fn}},{key:"Default",get:function(){return zo}},{key:"NAME",get:function(){return Hn}},{key:"DATA_KEY",get:function(){return Gn}},{key:"Event",get:function(){return io}},{key:"EVENT_KEY",get:function(){return Yn}},{key:"DefaultType",get:function(){return ao}}]),t}();p.default.fn[Hn]=Oo._jQueryInterface,p.default.fn[Hn].Constructor=Oo,p.default.fn[Hn].noConflict=function(){return p.default.fn[Hn]=$n,Oo._jQueryInterface};var so="popover",Ao="4.6.2",uo="bs.popover",lo="."+uo,fo=p.default.fn[so],qo="bs-popover",ho=new RegExp("(^|\\s)"+qo+"\\S+","g"),Wo="fade",vo="show",Ro=".popover-header",mo=".popover-body",go=r({},Oo.Default,{placement:"right",trigger:"click",content:"",template:''}),Lo=r({},Oo.DefaultType,{content:"(string|element|function)"}),yo={HIDE:"hide"+lo,HIDDEN:"hidden"+lo,SHOW:"show"+lo,SHOWN:"shown"+lo,INSERTED:"inserted"+lo,CLICK:"click"+lo,FOCUSIN:"focusin"+lo,FOCUSOUT:"focusout"+lo,MOUSEENTER:"mouseenter"+lo,MOUSELEAVE:"mouseleave"+lo},_o=function(t){function e(){return t.apply(this,arguments)||this}z(e,t);var n=e.prototype;return n.isWithContent=function(){return this.getTitle()||this._getContent()},n.addAttachmentClass=function(t){p.default(this.getTipElement()).addClass(qo+"-"+t)},n.getTipElement=function(){return this.tip=this.tip||p.default(this.config.template)[0],this.tip},n.setContent=function(){var t=p.default(this.getTipElement());this.setElementContent(t.find(Ro),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(mo),e),t.removeClass(Wo+" "+vo)},n._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},n._cleanTipClass=function(){var t=p.default(this.getTipElement()),e=t.attr("class").match(ho);null!==e&&e.length>0&&t.removeClass(e.join(""))},e._jQueryInterface=function(t){return this.each((function(){var n=p.default(this).data(uo),o="object"==typeof t?t:null;if((n||!/dispose|hide/.test(t))&&(n||(n=new e(this,o),p.default(this).data(uo,n)),"string"==typeof t)){if(void 0===n[t])throw new TypeError('No method named "'+t+'"');n[t]()}}))},c(e,null,[{key:"VERSION",get:function(){return Ao}},{key:"Default",get:function(){return go}},{key:"NAME",get:function(){return so}},{key:"DATA_KEY",get:function(){return uo}},{key:"Event",get:function(){return yo}},{key:"EVENT_KEY",get:function(){return lo}},{key:"DefaultType",get:function(){return Lo}}]),e}(Oo);p.default.fn[so]=_o._jQueryInterface,p.default.fn[so].Constructor=_o,p.default.fn[so].noConflict=function(){return p.default.fn[so]=fo,_o._jQueryInterface};var No="scrollspy",Eo="4.6.2",To="bs.scrollspy",Bo="."+To,Co=".data-api",wo=p.default.fn[No],So="dropdown-item",Xo="active",xo="activate"+Bo,ko="scroll"+Bo,Io="load"+Bo+Co,Do="offset",Po="position",Uo='[data-spy="scroll"]',jo=".nav, .list-group",Ho=".nav-link",Fo=".nav-item",Go=".list-group-item",Yo=".dropdown",$o=".dropdown-item",Vo=".dropdown-toggle",Ko={offset:10,method:"auto",target:""},Qo={offset:"number",method:"string",target:"(string|element)"},Jo=function(){function t(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" "+Ho+","+this._config.target+" "+Go+","+this._config.target+" "+$o,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,p.default(this._scrollElement).on(ko,(function(t){return n._process(t)})),this.refresh(),this._process()}var e=t.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?Do:Po,n="auto"===this._config.method?e:this._config.method,o=n===Po?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var e,M=f.getSelectorFromElement(t);if(M&&(e=document.querySelector(M)),e){var b=e.getBoundingClientRect();if(b.width||b.height)return[p.default(e)[n]().top+o,M]}return null})).filter(Boolean).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},e.dispose=function(){p.default.removeData(this._element,To),p.default(this._scrollElement).off(Bo),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},e._getConfig=function(t){if("string"!=typeof(t=r({},Ko,"object"==typeof t&&t?t:{})).target&&f.isElement(t.target)){var e=p.default(t.target).attr("id");e||(e=f.getUID(No),p.default(t.target).attr("id",e)),t.target="#"+e}return f.typeCheckConfig(No,t,Qo),t},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var o=this._targets[this._targets.length-1];this._activeTarget!==o&&this._activate(o)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var p=this._offsets.length;p--;)this._activeTarget!==this._targets[p]&&t>=this._offsets[p]&&(void 0===this._offsets[p+1]||t{"use strict";var o=n(7526),p=n(251),M=n(4634);function b(){return r.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function c(t,e){if(b()=b())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+b().toString(16)+" bytes");return 0|t}function A(t,e){if(r.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var n=t.length;if(0===n)return 0;for(var o=!1;;)switch(e){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return P(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return U(t).length;default:if(o)return P(t).length;e=(""+e).toLowerCase(),o=!0}}function u(t,e,n){var o=!1;if((void 0===e||e<0)&&(e=0),e>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return E(this,e,n);case"utf8":case"utf-8":return L(this,e,n);case"ascii":return _(this,e,n);case"latin1":case"binary":return N(this,e,n);case"base64":return g(this,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return T(this,e,n);default:if(o)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),o=!0}}function l(t,e,n){var o=t[e];t[e]=t[n],t[n]=o}function d(t,e,n,o,p){if(0===t.length)return-1;if("string"==typeof n?(o=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=p?0:t.length-1),n<0&&(n=t.length+n),n>=t.length){if(p)return-1;n=t.length-1}else if(n<0){if(!p)return-1;n=0}if("string"==typeof e&&(e=r.from(e,o)),r.isBuffer(e))return 0===e.length?-1:f(t,e,n,o,p);if("number"==typeof e)return e&=255,r.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?p?Uint8Array.prototype.indexOf.call(t,e,n):Uint8Array.prototype.lastIndexOf.call(t,e,n):f(t,[e],n,o,p);throw new TypeError("val must be string, number or Buffer")}function f(t,e,n,o,p){var M,b=1,c=t.length,r=e.length;if(void 0!==o&&("ucs2"===(o=String(o).toLowerCase())||"ucs-2"===o||"utf16le"===o||"utf-16le"===o)){if(t.length<2||e.length<2)return-1;b=2,c/=2,r/=2,n/=2}function z(t,e){return 1===b?t[e]:t.readUInt16BE(e*b)}if(p){var a=-1;for(M=n;Mc&&(n=c-r),M=n;M>=0;M--){for(var i=!0,O=0;Op&&(o=p):o=p;var M=e.length;if(M%2!=0)throw new TypeError("Invalid hex string");o>M/2&&(o=M/2);for(var b=0;b>8,p=n%256,M.push(p),M.push(o);return M}(e,t.length-n),t,n,o)}function g(t,e,n){return 0===e&&n===t.length?o.fromByteArray(t):o.fromByteArray(t.slice(e,n))}function L(t,e,n){n=Math.min(t.length,n);for(var o=[],p=e;p239?4:z>223?3:z>191?2:1;if(p+i<=n)switch(i){case 1:z<128&&(a=z);break;case 2:128==(192&(M=t[p+1]))&&(r=(31&z)<<6|63&M)>127&&(a=r);break;case 3:M=t[p+1],b=t[p+2],128==(192&M)&&128==(192&b)&&(r=(15&z)<<12|(63&M)<<6|63&b)>2047&&(r<55296||r>57343)&&(a=r);break;case 4:M=t[p+1],b=t[p+2],c=t[p+3],128==(192&M)&&128==(192&b)&&128==(192&c)&&(r=(15&z)<<18|(63&M)<<12|(63&b)<<6|63&c)>65535&&r<1114112&&(a=r)}null===a?(a=65533,i=1):a>65535&&(a-=65536,o.push(a>>>10&1023|55296),a=56320|1023&a),o.push(a),p+=i}return function(t){var e=t.length;if(e<=y)return String.fromCharCode.apply(String,t);var n="",o=0;for(;o0&&(t=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(t+=" ... ")),""},r.prototype.compare=function(t,e,n,o,p){if(!r.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===n&&(n=t?t.length:0),void 0===o&&(o=0),void 0===p&&(p=this.length),e<0||n>t.length||o<0||p>this.length)throw new RangeError("out of range index");if(o>=p&&e>=n)return 0;if(o>=p)return-1;if(e>=n)return 1;if(this===t)return 0;for(var M=(p>>>=0)-(o>>>=0),b=(n>>>=0)-(e>>>=0),c=Math.min(M,b),z=this.slice(o,p),a=t.slice(e,n),i=0;ip)&&(n=p),t.length>0&&(n<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");o||(o="utf8");for(var M=!1;;)switch(o){case"hex":return q(this,t,e,n);case"utf8":case"utf-8":return h(this,t,e,n);case"ascii":return W(this,t,e,n);case"latin1":case"binary":return v(this,t,e,n);case"base64":return R(this,t,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return m(this,t,e,n);default:if(M)throw new TypeError("Unknown encoding: "+o);o=(""+o).toLowerCase(),M=!0}},r.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var y=4096;function _(t,e,n){var o="";n=Math.min(t.length,n);for(var p=e;po)&&(n=o);for(var p="",M=e;Mn)throw new RangeError("Trying to access beyond buffer length")}function C(t,e,n,o,p,M){if(!r.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>p||et.length)throw new RangeError("Index out of range")}function w(t,e,n,o){e<0&&(e=65535+e+1);for(var p=0,M=Math.min(t.length-n,2);p>>8*(o?p:1-p)}function S(t,e,n,o){e<0&&(e=4294967295+e+1);for(var p=0,M=Math.min(t.length-n,4);p>>8*(o?p:3-p)&255}function X(t,e,n,o,p,M){if(n+o>t.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function x(t,e,n,o,M){return M||X(t,0,n,4),p.write(t,e,n,o,23,4),n+4}function k(t,e,n,o,M){return M||X(t,0,n,8),p.write(t,e,n,o,52,8),n+8}r.prototype.slice=function(t,e){var n,o=this.length;if((t=~~t)<0?(t+=o)<0&&(t=0):t>o&&(t=o),(e=void 0===e?o:~~e)<0?(e+=o)<0&&(e=0):e>o&&(e=o),e0&&(p*=256);)o+=this[t+--e]*p;return o},r.prototype.readUInt8=function(t,e){return e||B(t,1,this.length),this[t]},r.prototype.readUInt16LE=function(t,e){return e||B(t,2,this.length),this[t]|this[t+1]<<8},r.prototype.readUInt16BE=function(t,e){return e||B(t,2,this.length),this[t]<<8|this[t+1]},r.prototype.readUInt32LE=function(t,e){return e||B(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},r.prototype.readUInt32BE=function(t,e){return e||B(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},r.prototype.readIntLE=function(t,e,n){t|=0,e|=0,n||B(t,e,this.length);for(var o=this[t],p=1,M=0;++M=(p*=128)&&(o-=Math.pow(2,8*e)),o},r.prototype.readIntBE=function(t,e,n){t|=0,e|=0,n||B(t,e,this.length);for(var o=e,p=1,M=this[t+--o];o>0&&(p*=256);)M+=this[t+--o]*p;return M>=(p*=128)&&(M-=Math.pow(2,8*e)),M},r.prototype.readInt8=function(t,e){return e||B(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},r.prototype.readInt16LE=function(t,e){e||B(t,2,this.length);var n=this[t]|this[t+1]<<8;return 32768&n?4294901760|n:n},r.prototype.readInt16BE=function(t,e){e||B(t,2,this.length);var n=this[t+1]|this[t]<<8;return 32768&n?4294901760|n:n},r.prototype.readInt32LE=function(t,e){return e||B(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},r.prototype.readInt32BE=function(t,e){return e||B(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},r.prototype.readFloatLE=function(t,e){return e||B(t,4,this.length),p.read(this,t,!0,23,4)},r.prototype.readFloatBE=function(t,e){return e||B(t,4,this.length),p.read(this,t,!1,23,4)},r.prototype.readDoubleLE=function(t,e){return e||B(t,8,this.length),p.read(this,t,!0,52,8)},r.prototype.readDoubleBE=function(t,e){return e||B(t,8,this.length),p.read(this,t,!1,52,8)},r.prototype.writeUIntLE=function(t,e,n,o){(t=+t,e|=0,n|=0,o)||C(this,t,e,n,Math.pow(2,8*n)-1,0);var p=1,M=0;for(this[e]=255&t;++M=0&&(M*=256);)this[e+p]=t/M&255;return e+n},r.prototype.writeUInt8=function(t,e,n){return t=+t,e|=0,n||C(this,t,e,1,255,0),r.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},r.prototype.writeUInt16LE=function(t,e,n){return t=+t,e|=0,n||C(this,t,e,2,65535,0),r.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):w(this,t,e,!0),e+2},r.prototype.writeUInt16BE=function(t,e,n){return t=+t,e|=0,n||C(this,t,e,2,65535,0),r.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):w(this,t,e,!1),e+2},r.prototype.writeUInt32LE=function(t,e,n){return t=+t,e|=0,n||C(this,t,e,4,4294967295,0),r.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):S(this,t,e,!0),e+4},r.prototype.writeUInt32BE=function(t,e,n){return t=+t,e|=0,n||C(this,t,e,4,4294967295,0),r.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):S(this,t,e,!1),e+4},r.prototype.writeIntLE=function(t,e,n,o){if(t=+t,e|=0,!o){var p=Math.pow(2,8*n-1);C(this,t,e,n,p-1,-p)}var M=0,b=1,c=0;for(this[e]=255&t;++M=0&&(b*=256);)t<0&&0===c&&0!==this[e+M+1]&&(c=1),this[e+M]=(t/b|0)-c&255;return e+n},r.prototype.writeInt8=function(t,e,n){return t=+t,e|=0,n||C(this,t,e,1,127,-128),r.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},r.prototype.writeInt16LE=function(t,e,n){return t=+t,e|=0,n||C(this,t,e,2,32767,-32768),r.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):w(this,t,e,!0),e+2},r.prototype.writeInt16BE=function(t,e,n){return t=+t,e|=0,n||C(this,t,e,2,32767,-32768),r.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):w(this,t,e,!1),e+2},r.prototype.writeInt32LE=function(t,e,n){return t=+t,e|=0,n||C(this,t,e,4,2147483647,-2147483648),r.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):S(this,t,e,!0),e+4},r.prototype.writeInt32BE=function(t,e,n){return t=+t,e|=0,n||C(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),r.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):S(this,t,e,!1),e+4},r.prototype.writeFloatLE=function(t,e,n){return x(this,t,e,!0,n)},r.prototype.writeFloatBE=function(t,e,n){return x(this,t,e,!1,n)},r.prototype.writeDoubleLE=function(t,e,n){return k(this,t,e,!0,n)},r.prototype.writeDoubleBE=function(t,e,n){return k(this,t,e,!1,n)},r.prototype.copy=function(t,e,n,o){if(n||(n=0),o||0===o||(o=this.length),e>=t.length&&(e=t.length),e||(e=0),o>0&&o=this.length)throw new RangeError("sourceStart out of bounds");if(o<0)throw new RangeError("sourceEnd out of bounds");o>this.length&&(o=this.length),t.length-e=0;--p)t[p+e]=this[p+n];else if(M<1e3||!r.TYPED_ARRAY_SUPPORT)for(p=0;p>>=0,n=void 0===n?this.length:n>>>0,t||(t=0),"number"==typeof t)for(M=e;M55295&&n<57344){if(!p){if(n>56319){(e-=3)>-1&&M.push(239,191,189);continue}if(b+1===o){(e-=3)>-1&&M.push(239,191,189);continue}p=n;continue}if(n<56320){(e-=3)>-1&&M.push(239,191,189),p=n;continue}n=65536+(p-55296<<10|n-56320)}else p&&(e-=3)>-1&&M.push(239,191,189);if(p=null,n<128){if((e-=1)<0)break;M.push(n)}else if(n<2048){if((e-=2)<0)break;M.push(n>>6|192,63&n|128)}else if(n<65536){if((e-=3)<0)break;M.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;M.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return M}function U(t){return o.toByteArray(function(t){if((t=function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}(t).replace(I,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function j(t,e,n,o){for(var p=0;p=e.length||p>=t.length);++p)e[p+n]=t[p];return p}},7965:(t,e,n)=>{"use strict";var o=n(6426),p={"text/plain":"Text","text/html":"Url",default:"Text"};t.exports=function(t,e){var n,M,b,c,r,z=!1;e||(e={}),e.debug;try{if(M=o(),b=document.createRange(),c=document.getSelection(),(r=document.createElement("span")).textContent=t,r.ariaHidden="true",r.style.all="unset",r.style.position="fixed",r.style.top=0,r.style.clip="rect(0, 0, 0, 0)",r.style.whiteSpace="pre",r.style.webkitUserSelect="text",r.style.MozUserSelect="text",r.style.msUserSelect="text",r.style.userSelect="text",r.addEventListener("copy",(function(n){if(n.stopPropagation(),e.format)if(n.preventDefault(),void 0===n.clipboardData){window.clipboardData.clearData();var o=p[e.format]||p.default;window.clipboardData.setData(o,t)}else n.clipboardData.clearData(),n.clipboardData.setData(e.format,t);e.onCopy&&(n.preventDefault(),e.onCopy(n.clipboardData))})),document.body.appendChild(r),b.selectNodeContents(r),c.addRange(b),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");z=!0}catch(o){try{window.clipboardData.setData(e.format||"text",t),e.onCopy&&e.onCopy(window.clipboardData),z=!0}catch(o){n=function(t){var e=(/mac os x/i.test(navigator.userAgent)?"โŒ˜":"Ctrl")+"+C";return t.replace(/#{\s*key\s*}/g,e)}("message"in e?e.message:"Copy to clipboard: #{key}, Enter"),window.prompt(n,t)}}finally{c&&("function"==typeof c.removeRange?c.removeRange(b):c.removeAllRanges()),r&&document.body.removeChild(r),M()}return z}},251:(t,e)=>{e.read=function(t,e,n,o,p){var M,b,c=8*p-o-1,r=(1<>1,a=-7,i=n?p-1:0,O=n?-1:1,s=t[e+i];for(i+=O,M=s&(1<<-a)-1,s>>=-a,a+=c;a>0;M=256*M+t[e+i],i+=O,a-=8);for(b=M&(1<<-a)-1,M>>=-a,a+=o;a>0;b=256*b+t[e+i],i+=O,a-=8);if(0===M)M=1-z;else{if(M===r)return b?NaN:1/0*(s?-1:1);b+=Math.pow(2,o),M-=z}return(s?-1:1)*b*Math.pow(2,M-o)},e.write=function(t,e,n,o,p,M){var b,c,r,z=8*M-p-1,a=(1<>1,O=23===p?Math.pow(2,-24)-Math.pow(2,-77):0,s=o?0:M-1,A=o?1:-1,u=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(c=isNaN(e)?1:0,b=a):(b=Math.floor(Math.log(e)/Math.LN2),e*(r=Math.pow(2,-b))<1&&(b--,r*=2),(e+=b+i>=1?O/r:O*Math.pow(2,1-i))*r>=2&&(b++,r/=2),b+i>=a?(c=0,b=a):b+i>=1?(c=(e*r-1)*Math.pow(2,p),b+=i):(c=e*Math.pow(2,i-1)*Math.pow(2,p),b=0));p>=8;t[n+s]=255&c,s+=A,c/=256,p-=8);for(b=b<0;t[n+s]=255&b,s+=A,b/=256,z-=8);t[n+s-A]|=128*u}},4634:t=>{var e={}.toString;t.exports=Array.isArray||function(t){return"[object Array]"==e.call(t)}},4692:function(t,e){var n;!function(e,n){"use strict";"object"==typeof t.exports?t.exports=e.document?n(e,!0):function(t){if(!t.document)throw new Error("jQuery requires a window with a document");return n(t)}:n(e)}("undefined"!=typeof window?window:this,(function(o,p){"use strict";var M=[],b=Object.getPrototypeOf,c=M.slice,r=M.flat?function(t){return M.flat.call(t)}:function(t){return M.concat.apply([],t)},z=M.push,a=M.indexOf,i={},O=i.toString,s=i.hasOwnProperty,A=s.toString,u=A.call(Object),l={},d=function(t){return"function"==typeof t&&"number"!=typeof t.nodeType&&"function"!=typeof t.item},f=function(t){return null!=t&&t===t.window},q=o.document,h={type:!0,src:!0,nonce:!0,noModule:!0};function W(t,e,n){var o,p,M=(n=n||q).createElement("script");if(M.text=t,e)for(o in h)(p=e[o]||e.getAttribute&&e.getAttribute(o))&&M.setAttribute(o,p);n.head.appendChild(M).parentNode.removeChild(M)}function v(t){return null==t?t+"":"object"==typeof t||"function"==typeof t?i[O.call(t)]||"object":typeof t}var R="3.7.1",m=/HTML$/i,g=function(t,e){return new g.fn.init(t,e)};function L(t){var e=!!t&&"length"in t&&t.length,n=v(t);return!d(t)&&!f(t)&&("array"===n||0===e||"number"==typeof e&&e>0&&e-1 in t)}function y(t,e){return t.nodeName&&t.nodeName.toLowerCase()===e.toLowerCase()}g.fn=g.prototype={jquery:R,constructor:g,length:0,toArray:function(){return c.call(this)},get:function(t){return null==t?c.call(this):t<0?this[t+this.length]:this[t]},pushStack:function(t){var e=g.merge(this.constructor(),t);return e.prevObject=this,e},each:function(t){return g.each(this,t)},map:function(t){return this.pushStack(g.map(this,(function(e,n){return t.call(e,n,e)})))},slice:function(){return this.pushStack(c.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(g.grep(this,(function(t,e){return(e+1)%2})))},odd:function(){return this.pushStack(g.grep(this,(function(t,e){return e%2})))},eq:function(t){var e=this.length,n=+t+(t<0?e:0);return this.pushStack(n>=0&&n+~]|"+T+")"+T+"*"),P=new RegExp(T+"|>"),U=new RegExp(x),j=new RegExp("^"+C+"$"),H={ID:new RegExp("^#("+C+")"),CLASS:new RegExp("^\\.("+C+")"),TAG:new RegExp("^("+C+"|[*])"),ATTR:new RegExp("^"+w),PSEUDO:new RegExp("^"+x),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+T+"*(even|odd|(([+-]|)(\\d*)n|)"+T+"*(?:([+-]|)"+T+"*(\\d+)|))"+T+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+T+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+T+"*((?:-\\d)?\\d*)"+T+"*\\)|)(?=[^-]|$)","i")},F=/^(?:input|select|textarea|button)$/i,G=/^h\d$/i,Y=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,V=new RegExp("\\\\[\\da-fA-F]{1,6}"+T+"?|\\\\([^\\r\\n\\f])","g"),K=function(t,e){var n="0x"+t.slice(1)-65536;return e||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},Q=function(){rt()},J=Ot((function(t){return!0===t.disabled&&y(t,"fieldset")}),{dir:"parentNode",next:"legend"});try{u.apply(M=c.call(S.childNodes),S.childNodes),M[S.childNodes.length].nodeType}catch(t){u={apply:function(t,e){X.apply(t,c.call(e))},call:function(t){X.apply(t,c.call(arguments,1))}}}function Z(t,e,n,o){var p,M,b,c,z,a,s,A=e&&e.ownerDocument,f=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==f&&9!==f&&11!==f)return n;if(!o&&(rt(e),e=e||r,i)){if(11!==f&&(z=Y.exec(t)))if(p=z[1]){if(9===f){if(!(b=e.getElementById(p)))return n;if(b.id===p)return u.call(n,b),n}else if(A&&(b=A.getElementById(p))&&Z.contains(e,b)&&b.id===p)return u.call(n,b),n}else{if(z[2])return u.apply(n,e.getElementsByTagName(t)),n;if((p=z[3])&&e.getElementsByClassName)return u.apply(n,e.getElementsByClassName(p)),n}if(!(R[t+" "]||O&&O.test(t))){if(s=t,A=e,1===f&&(P.test(t)||D.test(t))){for((A=$.test(t)&&ct(e.parentNode)||e)==e&&l.scope||((c=e.getAttribute("id"))?c=g.escapeSelector(c):e.setAttribute("id",c=d)),M=(a=at(t)).length;M--;)a[M]=(c?"#"+c:":scope")+" "+it(a[M]);s=a.join(",")}try{return u.apply(n,A.querySelectorAll(s)),n}catch(e){R(t,!0)}finally{c===d&&e.removeAttribute("id")}}}return ft(t.replace(B,"$1"),e,n,o)}function tt(){var t=[];return function n(o,p){return t.push(o+" ")>e.cacheLength&&delete n[t.shift()],n[o+" "]=p}}function et(t){return t[d]=!0,t}function nt(t){var e=r.createElement("fieldset");try{return!!t(e)}catch(t){return!1}finally{e.parentNode&&e.parentNode.removeChild(e),e=null}}function ot(t){return function(e){return y(e,"input")&&e.type===t}}function pt(t){return function(e){return(y(e,"input")||y(e,"button"))&&e.type===t}}function Mt(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&J(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function bt(t){return et((function(e){return e=+e,et((function(n,o){for(var p,M=t([],n.length,e),b=M.length;b--;)n[p=M[b]]&&(n[p]=!(o[p]=n[p]))}))}))}function ct(t){return t&&void 0!==t.getElementsByTagName&&t}function rt(t){var n,o=t?t.ownerDocument||t:S;return o!=r&&9===o.nodeType&&o.documentElement?(z=(r=o).documentElement,i=!g.isXMLDoc(r),A=z.matches||z.webkitMatchesSelector||z.msMatchesSelector,z.msMatchesSelector&&S!=r&&(n=r.defaultView)&&n.top!==n&&n.addEventListener("unload",Q),l.getById=nt((function(t){return z.appendChild(t).id=g.expando,!r.getElementsByName||!r.getElementsByName(g.expando).length})),l.disconnectedMatch=nt((function(t){return A.call(t,"*")})),l.scope=nt((function(){return r.querySelectorAll(":scope")})),l.cssHas=nt((function(){try{return r.querySelector(":has(*,:jqfake)"),!1}catch(t){return!0}})),l.getById?(e.filter.ID=function(t){var e=t.replace(V,K);return function(t){return t.getAttribute("id")===e}},e.find.ID=function(t,e){if(void 0!==e.getElementById&&i){var n=e.getElementById(t);return n?[n]:[]}}):(e.filter.ID=function(t){var e=t.replace(V,K);return function(t){var n=void 0!==t.getAttributeNode&&t.getAttributeNode("id");return n&&n.value===e}},e.find.ID=function(t,e){if(void 0!==e.getElementById&&i){var n,o,p,M=e.getElementById(t);if(M){if((n=M.getAttributeNode("id"))&&n.value===t)return[M];for(p=e.getElementsByName(t),o=0;M=p[o++];)if((n=M.getAttributeNode("id"))&&n.value===t)return[M]}return[]}}),e.find.TAG=function(t,e){return void 0!==e.getElementsByTagName?e.getElementsByTagName(t):e.querySelectorAll(t)},e.find.CLASS=function(t,e){if(void 0!==e.getElementsByClassName&&i)return e.getElementsByClassName(t)},O=[],nt((function(t){var e;z.appendChild(t).innerHTML="",t.querySelectorAll("[selected]").length||O.push("\\["+T+"*(?:value|"+L+")"),t.querySelectorAll("[id~="+d+"-]").length||O.push("~="),t.querySelectorAll("a#"+d+"+*").length||O.push(".#.+[+~]"),t.querySelectorAll(":checked").length||O.push(":checked"),(e=r.createElement("input")).setAttribute("type","hidden"),t.appendChild(e).setAttribute("name","D"),z.appendChild(t).disabled=!0,2!==t.querySelectorAll(":disabled").length&&O.push(":enabled",":disabled"),(e=r.createElement("input")).setAttribute("name",""),t.appendChild(e),t.querySelectorAll("[name='']").length||O.push("\\["+T+"*name"+T+"*="+T+"*(?:''|\"\")")})),l.cssHas||O.push(":has"),O=O.length&&new RegExp(O.join("|")),m=function(t,e){if(t===e)return b=!0,0;var n=!t.compareDocumentPosition-!e.compareDocumentPosition;return n||(1&(n=(t.ownerDocument||t)==(e.ownerDocument||e)?t.compareDocumentPosition(e):1)||!l.sortDetached&&e.compareDocumentPosition(t)===n?t===r||t.ownerDocument==S&&Z.contains(S,t)?-1:e===r||e.ownerDocument==S&&Z.contains(S,e)?1:p?a.call(p,t)-a.call(p,e):0:4&n?-1:1)},r):r}for(t in Z.matches=function(t,e){return Z(t,null,null,e)},Z.matchesSelector=function(t,e){if(rt(t),i&&!R[e+" "]&&(!O||!O.test(e)))try{var n=A.call(t,e);if(n||l.disconnectedMatch||t.document&&11!==t.document.nodeType)return n}catch(t){R(e,!0)}return Z(e,r,null,[t]).length>0},Z.contains=function(t,e){return(t.ownerDocument||t)!=r&&rt(t),g.contains(t,e)},Z.attr=function(t,n){(t.ownerDocument||t)!=r&&rt(t);var o=e.attrHandle[n.toLowerCase()],p=o&&s.call(e.attrHandle,n.toLowerCase())?o(t,n,!i):void 0;return void 0!==p?p:t.getAttribute(n)},Z.error=function(t){throw new Error("Syntax error, unrecognized expression: "+t)},g.uniqueSort=function(t){var e,n=[],o=0,M=0;if(b=!l.sortStable,p=!l.sortStable&&c.call(t,0),N.call(t,m),b){for(;e=t[M++];)e===t[M]&&(o=n.push(M));for(;o--;)E.call(t,n[o],1)}return p=null,t},g.fn.uniqueSort=function(){return this.pushStack(g.uniqueSort(c.apply(this)))},e=g.expr={cacheLength:50,createPseudo:et,match:H,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(t){return t[1]=t[1].replace(V,K),t[3]=(t[3]||t[4]||t[5]||"").replace(V,K),"~="===t[2]&&(t[3]=" "+t[3]+" "),t.slice(0,4)},CHILD:function(t){return t[1]=t[1].toLowerCase(),"nth"===t[1].slice(0,3)?(t[3]||Z.error(t[0]),t[4]=+(t[4]?t[5]+(t[6]||1):2*("even"===t[3]||"odd"===t[3])),t[5]=+(t[7]+t[8]||"odd"===t[3])):t[3]&&Z.error(t[0]),t},PSEUDO:function(t){var e,n=!t[6]&&t[2];return H.CHILD.test(t[0])?null:(t[3]?t[2]=t[4]||t[5]||"":n&&U.test(n)&&(e=at(n,!0))&&(e=n.indexOf(")",n.length-e)-n.length)&&(t[0]=t[0].slice(0,e),t[2]=n.slice(0,e)),t.slice(0,3))}},filter:{TAG:function(t){var e=t.replace(V,K).toLowerCase();return"*"===t?function(){return!0}:function(t){return y(t,e)}},CLASS:function(t){var e=h[t+" "];return e||(e=new RegExp("(^|"+T+")"+t+"("+T+"|$)"))&&h(t,(function(t){return e.test("string"==typeof t.className&&t.className||void 0!==t.getAttribute&&t.getAttribute("class")||"")}))},ATTR:function(t,e,n){return function(o){var p=Z.attr(o,t);return null==p?"!="===e:!e||(p+="","="===e?p===n:"!="===e?p!==n:"^="===e?n&&0===p.indexOf(n):"*="===e?n&&p.indexOf(n)>-1:"$="===e?n&&p.slice(-n.length)===n:"~="===e?(" "+p.replace(k," ")+" ").indexOf(n)>-1:"|="===e&&(p===n||p.slice(0,n.length+1)===n+"-"))}},CHILD:function(t,e,n,o,p){var M="nth"!==t.slice(0,3),b="last"!==t.slice(-4),c="of-type"===e;return 1===o&&0===p?function(t){return!!t.parentNode}:function(e,n,r){var z,a,i,O,s,A=M!==b?"nextSibling":"previousSibling",u=e.parentNode,l=c&&e.nodeName.toLowerCase(),q=!r&&!c,h=!1;if(u){if(M){for(;A;){for(i=e;i=i[A];)if(c?y(i,l):1===i.nodeType)return!1;s=A="only"===t&&!s&&"nextSibling"}return!0}if(s=[b?u.firstChild:u.lastChild],b&&q){for(h=(O=(z=(a=u[d]||(u[d]={}))[t]||[])[0]===f&&z[1])&&z[2],i=O&&u.childNodes[O];i=++O&&i&&i[A]||(h=O=0)||s.pop();)if(1===i.nodeType&&++h&&i===e){a[t]=[f,O,h];break}}else if(q&&(h=O=(z=(a=e[d]||(e[d]={}))[t]||[])[0]===f&&z[1]),!1===h)for(;(i=++O&&i&&i[A]||(h=O=0)||s.pop())&&(!(c?y(i,l):1===i.nodeType)||!++h||(q&&((a=i[d]||(i[d]={}))[t]=[f,h]),i!==e)););return(h-=p)===o||h%o==0&&h/o>=0}}},PSEUDO:function(t,n){var o,p=e.pseudos[t]||e.setFilters[t.toLowerCase()]||Z.error("unsupported pseudo: "+t);return p[d]?p(n):p.length>1?(o=[t,t,"",n],e.setFilters.hasOwnProperty(t.toLowerCase())?et((function(t,e){for(var o,M=p(t,n),b=M.length;b--;)t[o=a.call(t,M[b])]=!(e[o]=M[b])})):function(t){return p(t,0,o)}):p}},pseudos:{not:et((function(t){var e=[],n=[],o=dt(t.replace(B,"$1"));return o[d]?et((function(t,e,n,p){for(var M,b=o(t,null,p,[]),c=t.length;c--;)(M=b[c])&&(t[c]=!(e[c]=M))})):function(t,p,M){return e[0]=t,o(e,null,M,n),e[0]=null,!n.pop()}})),has:et((function(t){return function(e){return Z(t,e).length>0}})),contains:et((function(t){return t=t.replace(V,K),function(e){return(e.textContent||g.text(e)).indexOf(t)>-1}})),lang:et((function(t){return j.test(t||"")||Z.error("unsupported lang: "+t),t=t.replace(V,K).toLowerCase(),function(e){var n;do{if(n=i?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(n=n.toLowerCase())===t||0===n.indexOf(t+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}})),target:function(t){var e=o.location&&o.location.hash;return e&&e.slice(1)===t.id},root:function(t){return t===z},focus:function(t){return t===function(){try{return r.activeElement}catch(t){}}()&&r.hasFocus()&&!!(t.type||t.href||~t.tabIndex)},enabled:Mt(!1),disabled:Mt(!0),checked:function(t){return y(t,"input")&&!!t.checked||y(t,"option")&&!!t.selected},selected:function(t){return t.parentNode&&t.parentNode.selectedIndex,!0===t.selected},empty:function(t){for(t=t.firstChild;t;t=t.nextSibling)if(t.nodeType<6)return!1;return!0},parent:function(t){return!e.pseudos.empty(t)},header:function(t){return G.test(t.nodeName)},input:function(t){return F.test(t.nodeName)},button:function(t){return y(t,"input")&&"button"===t.type||y(t,"button")},text:function(t){var e;return y(t,"input")&&"text"===t.type&&(null==(e=t.getAttribute("type"))||"text"===e.toLowerCase())},first:bt((function(){return[0]})),last:bt((function(t,e){return[e-1]})),eq:bt((function(t,e,n){return[n<0?n+e:n]})),even:bt((function(t,e){for(var n=0;ne?e:n;--o>=0;)t.push(o);return t})),gt:bt((function(t,e,n){for(var o=n<0?n+e:n;++o1?function(e,n,o){for(var p=t.length;p--;)if(!t[p](e,n,o))return!1;return!0}:t[0]}function At(t,e,n,o,p){for(var M,b=[],c=0,r=t.length,z=null!=e;c-1&&(M[z]=!(b[z]=O))}}else s=At(s===b?s.splice(d,s.length):s),p?p(null,b,s,r):u.apply(b,s)}))}function lt(t){for(var o,p,M,b=t.length,c=e.relative[t[0].type],r=c||e.relative[" "],z=c?1:0,i=Ot((function(t){return t===o}),r,!0),O=Ot((function(t){return a.call(o,t)>-1}),r,!0),s=[function(t,e,p){var M=!c&&(p||e!=n)||((o=e).nodeType?i(t,e,p):O(t,e,p));return o=null,M}];z1&&st(s),z>1&&it(t.slice(0,z-1).concat({value:" "===t[z-2].type?"*":""})).replace(B,"$1"),p,z0,M=t.length>0,b=function(b,c,z,a,O){var s,A,l,d=0,q="0",h=b&&[],W=[],v=n,R=b||M&&e.find.TAG("*",O),m=f+=null==v?1:Math.random()||.1,L=R.length;for(O&&(n=c==r||c||O);q!==L&&null!=(s=R[q]);q++){if(M&&s){for(A=0,c||s.ownerDocument==r||(rt(s),z=!i);l=t[A++];)if(l(s,c||r,z)){u.call(a,s);break}O&&(f=m)}p&&((s=!l&&s)&&d--,b&&h.push(s))}if(d+=q,p&&q!==d){for(A=0;l=o[A++];)l(h,W,c,z);if(b){if(d>0)for(;q--;)h[q]||W[q]||(W[q]=_.call(a));W=At(W)}u.apply(a,W),O&&!b&&W.length>0&&d+o.length>1&&g.uniqueSort(a)}return O&&(f=m,n=v),h};return p?et(b):b}(b,M)),c.selector=t}return c}function ft(t,n,o,p){var M,b,c,r,z,a="function"==typeof t&&t,O=!p&&at(t=a.selector||t);if(o=o||[],1===O.length){if((b=O[0]=O[0].slice(0)).length>2&&"ID"===(c=b[0]).type&&9===n.nodeType&&i&&e.relative[b[1].type]){if(!(n=(e.find.ID(c.matches[0].replace(V,K),n)||[])[0]))return o;a&&(n=n.parentNode),t=t.slice(b.shift().value.length)}for(M=H.needsContext.test(t)?0:b.length;M--&&(c=b[M],!e.relative[r=c.type]);)if((z=e.find[r])&&(p=z(c.matches[0].replace(V,K),$.test(b[0].type)&&ct(n.parentNode)||n))){if(b.splice(M,1),!(t=p.length&&it(b)))return u.apply(o,p),o;break}}return(a||dt(t,O))(p,n,!i,o,!n||$.test(t)&&ct(n.parentNode)||n),o}zt.prototype=e.filters=e.pseudos,e.setFilters=new zt,l.sortStable=d.split("").sort(m).join("")===d,rt(),l.sortDetached=nt((function(t){return 1&t.compareDocumentPosition(r.createElement("fieldset"))})),g.find=Z,g.expr[":"]=g.expr.pseudos,g.unique=g.uniqueSort,Z.compile=dt,Z.select=ft,Z.setDocument=rt,Z.tokenize=at,Z.escape=g.escapeSelector,Z.getText=g.text,Z.isXML=g.isXMLDoc,Z.selectors=g.expr,Z.support=g.support,Z.uniqueSort=g.uniqueSort}();var x=function(t,e,n){for(var o=[],p=void 0!==n;(t=t[e])&&9!==t.nodeType;)if(1===t.nodeType){if(p&&g(t).is(n))break;o.push(t)}return o},k=function(t,e){for(var n=[];t;t=t.nextSibling)1===t.nodeType&&t!==e&&n.push(t);return n},I=g.expr.match.needsContext,D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function P(t,e,n){return d(e)?g.grep(t,(function(t,o){return!!e.call(t,o,t)!==n})):e.nodeType?g.grep(t,(function(t){return t===e!==n})):"string"!=typeof e?g.grep(t,(function(t){return a.call(e,t)>-1!==n})):g.filter(e,t,n)}g.filter=function(t,e,n){var o=e[0];return n&&(t=":not("+t+")"),1===e.length&&1===o.nodeType?g.find.matchesSelector(o,t)?[o]:[]:g.find.matches(t,g.grep(e,(function(t){return 1===t.nodeType})))},g.fn.extend({find:function(t){var e,n,o=this.length,p=this;if("string"!=typeof t)return this.pushStack(g(t).filter((function(){for(e=0;e1?g.uniqueSort(n):n},filter:function(t){return this.pushStack(P(this,t||[],!1))},not:function(t){return this.pushStack(P(this,t||[],!0))},is:function(t){return!!P(this,"string"==typeof t&&I.test(t)?g(t):t||[],!1).length}});var U,j=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(g.fn.init=function(t,e,n){var o,p;if(!t)return this;if(n=n||U,"string"==typeof t){if(!(o="<"===t[0]&&">"===t[t.length-1]&&t.length>=3?[null,t,null]:j.exec(t))||!o[1]&&e)return!e||e.jquery?(e||n).find(t):this.constructor(e).find(t);if(o[1]){if(e=e instanceof g?e[0]:e,g.merge(this,g.parseHTML(o[1],e&&e.nodeType?e.ownerDocument||e:q,!0)),D.test(o[1])&&g.isPlainObject(e))for(o in e)d(this[o])?this[o](e[o]):this.attr(o,e[o]);return this}return(p=q.getElementById(o[2]))&&(this[0]=p,this.length=1),this}return t.nodeType?(this[0]=t,this.length=1,this):d(t)?void 0!==n.ready?n.ready(t):t(g):g.makeArray(t,this)}).prototype=g.fn,U=g(q);var H=/^(?:parents|prev(?:Until|All))/,F={children:!0,contents:!0,next:!0,prev:!0};function G(t,e){for(;(t=t[e])&&1!==t.nodeType;);return t}g.fn.extend({has:function(t){var e=g(t,this),n=e.length;return this.filter((function(){for(var t=0;t-1:1===n.nodeType&&g.find.matchesSelector(n,t))){M.push(n);break}return this.pushStack(M.length>1?g.uniqueSort(M):M)},index:function(t){return t?"string"==typeof t?a.call(g(t),this[0]):a.call(this,t.jquery?t[0]:t):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(t,e){return this.pushStack(g.uniqueSort(g.merge(this.get(),g(t,e))))},addBack:function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}}),g.each({parent:function(t){var e=t.parentNode;return e&&11!==e.nodeType?e:null},parents:function(t){return x(t,"parentNode")},parentsUntil:function(t,e,n){return x(t,"parentNode",n)},next:function(t){return G(t,"nextSibling")},prev:function(t){return G(t,"previousSibling")},nextAll:function(t){return x(t,"nextSibling")},prevAll:function(t){return x(t,"previousSibling")},nextUntil:function(t,e,n){return x(t,"nextSibling",n)},prevUntil:function(t,e,n){return x(t,"previousSibling",n)},siblings:function(t){return k((t.parentNode||{}).firstChild,t)},children:function(t){return k(t.firstChild)},contents:function(t){return null!=t.contentDocument&&b(t.contentDocument)?t.contentDocument:(y(t,"template")&&(t=t.content||t),g.merge([],t.childNodes))}},(function(t,e){g.fn[t]=function(n,o){var p=g.map(this,e,n);return"Until"!==t.slice(-5)&&(o=n),o&&"string"==typeof o&&(p=g.filter(o,p)),this.length>1&&(F[t]||g.uniqueSort(p),H.test(t)&&p.reverse()),this.pushStack(p)}}));var Y=/[^\x20\t\r\n\f]+/g;function $(t){return t}function V(t){throw t}function K(t,e,n,o){var p;try{t&&d(p=t.promise)?p.call(t).done(e).fail(n):t&&d(p=t.then)?p.call(t,e,n):e.apply(void 0,[t].slice(o))}catch(t){n.apply(void 0,[t])}}g.Callbacks=function(t){t="string"==typeof t?function(t){var e={};return g.each(t.match(Y)||[],(function(t,n){e[n]=!0})),e}(t):g.extend({},t);var e,n,o,p,M=[],b=[],c=-1,r=function(){for(p=p||t.once,o=e=!0;b.length;c=-1)for(n=b.shift();++c-1;)M.splice(n,1),n<=c&&c--})),this},has:function(t){return t?g.inArray(t,M)>-1:M.length>0},empty:function(){return M&&(M=[]),this},disable:function(){return p=b=[],M=n="",this},disabled:function(){return!M},lock:function(){return p=b=[],n||e||(M=n=""),this},locked:function(){return!!p},fireWith:function(t,n){return p||(n=[t,(n=n||[]).slice?n.slice():n],b.push(n),e||r()),this},fire:function(){return z.fireWith(this,arguments),this},fired:function(){return!!o}};return z},g.extend({Deferred:function(t){var e=[["notify","progress",g.Callbacks("memory"),g.Callbacks("memory"),2],["resolve","done",g.Callbacks("once memory"),g.Callbacks("once memory"),0,"resolved"],["reject","fail",g.Callbacks("once memory"),g.Callbacks("once memory"),1,"rejected"]],n="pending",p={state:function(){return n},always:function(){return M.done(arguments).fail(arguments),this},catch:function(t){return p.then(null,t)},pipe:function(){var t=arguments;return g.Deferred((function(n){g.each(e,(function(e,o){var p=d(t[o[4]])&&t[o[4]];M[o[1]]((function(){var t=p&&p.apply(this,arguments);t&&d(t.promise)?t.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+"With"](this,p?[t]:arguments)}))})),t=null})).promise()},then:function(t,n,p){var M=0;function b(t,e,n,p){return function(){var c=this,r=arguments,z=function(){var o,z;if(!(t=M&&(n!==V&&(c=void 0,r=[o]),e.rejectWith(c,r))}};t?a():(g.Deferred.getErrorHook?a.error=g.Deferred.getErrorHook():g.Deferred.getStackHook&&(a.error=g.Deferred.getStackHook()),o.setTimeout(a))}}return g.Deferred((function(o){e[0][3].add(b(0,o,d(p)?p:$,o.notifyWith)),e[1][3].add(b(0,o,d(t)?t:$)),e[2][3].add(b(0,o,d(n)?n:V))})).promise()},promise:function(t){return null!=t?g.extend(t,p):p}},M={};return g.each(e,(function(t,o){var b=o[2],c=o[5];p[o[1]]=b.add,c&&b.add((function(){n=c}),e[3-t][2].disable,e[3-t][3].disable,e[0][2].lock,e[0][3].lock),b.add(o[3].fire),M[o[0]]=function(){return M[o[0]+"With"](this===M?void 0:this,arguments),this},M[o[0]+"With"]=b.fireWith})),p.promise(M),t&&t.call(M,M),M},when:function(t){var e=arguments.length,n=e,o=Array(n),p=c.call(arguments),M=g.Deferred(),b=function(t){return function(n){o[t]=this,p[t]=arguments.length>1?c.call(arguments):n,--e||M.resolveWith(o,p)}};if(e<=1&&(K(t,M.done(b(n)).resolve,M.reject,!e),"pending"===M.state()||d(p[n]&&p[n].then)))return M.then();for(;n--;)K(p[n],b(n),M.reject);return M.promise()}});var Q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;g.Deferred.exceptionHook=function(t,e){o.console&&o.console.warn&&t&&Q.test(t.name)&&o.console.warn("jQuery.Deferred exception: "+t.message,t.stack,e)},g.readyException=function(t){o.setTimeout((function(){throw t}))};var J=g.Deferred();function Z(){q.removeEventListener("DOMContentLoaded",Z),o.removeEventListener("load",Z),g.ready()}g.fn.ready=function(t){return J.then(t).catch((function(t){g.readyException(t)})),this},g.extend({isReady:!1,readyWait:1,ready:function(t){(!0===t?--g.readyWait:g.isReady)||(g.isReady=!0,!0!==t&&--g.readyWait>0||J.resolveWith(q,[g]))}}),g.ready.then=J.then,"complete"===q.readyState||"loading"!==q.readyState&&!q.documentElement.doScroll?o.setTimeout(g.ready):(q.addEventListener("DOMContentLoaded",Z),o.addEventListener("load",Z));var tt=function(t,e,n,o,p,M,b){var c=0,r=t.length,z=null==n;if("object"===v(n))for(c in p=!0,n)tt(t,e,c,n[c],!0,M,b);else if(void 0!==o&&(p=!0,d(o)||(b=!0),z&&(b?(e.call(t,o),e=null):(z=e,e=function(t,e,n){return z.call(g(t),n)})),e))for(;c1,null,!0)},removeData:function(t){return this.each((function(){rt.remove(this,t)}))}}),g.extend({queue:function(t,e,n){var o;if(t)return e=(e||"fx")+"queue",o=ct.get(t,e),n&&(!o||Array.isArray(n)?o=ct.access(t,e,g.makeArray(n)):o.push(n)),o||[]},dequeue:function(t,e){e=e||"fx";var n=g.queue(t,e),o=n.length,p=n.shift(),M=g._queueHooks(t,e);"inprogress"===p&&(p=n.shift(),o--),p&&("fx"===e&&n.unshift("inprogress"),delete M.stop,p.call(t,(function(){g.dequeue(t,e)}),M)),!o&&M&&M.empty.fire()},_queueHooks:function(t,e){var n=e+"queueHooks";return ct.get(t,n)||ct.access(t,n,{empty:g.Callbacks("once memory").add((function(){ct.remove(t,[e+"queue",n])}))})}}),g.fn.extend({queue:function(t,e){var n=2;return"string"!=typeof t&&(e=t,t="fx",n--),arguments.length\x20\t\r\n\f]*)/i,yt=/^$|^module$|\/(?:java|ecma)script/i;Rt=q.createDocumentFragment().appendChild(q.createElement("div")),(mt=q.createElement("input")).setAttribute("type","radio"),mt.setAttribute("checked","checked"),mt.setAttribute("name","t"),Rt.appendChild(mt),l.checkClone=Rt.cloneNode(!0).cloneNode(!0).lastChild.checked,Rt.innerHTML="",l.noCloneChecked=!!Rt.cloneNode(!0).lastChild.defaultValue,Rt.innerHTML="",l.option=!!Rt.lastChild;var _t={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function Nt(t,e){var n;return n=void 0!==t.getElementsByTagName?t.getElementsByTagName(e||"*"):void 0!==t.querySelectorAll?t.querySelectorAll(e||"*"):[],void 0===e||e&&y(t,e)?g.merge([t],n):n}function Et(t,e){for(var n=0,o=t.length;n",""]);var Tt=/<|&#?\w+;/;function Bt(t,e,n,o,p){for(var M,b,c,r,z,a,i=e.createDocumentFragment(),O=[],s=0,A=t.length;s-1)p&&p.push(M);else if(z=lt(M),b=Nt(i.appendChild(M),"script"),z&&Et(b),n)for(a=0;M=b[a++];)yt.test(M.type||"")&&n.push(M);return i}var Ct=/^([^.]*)(?:\.(.+)|)/;function wt(){return!0}function St(){return!1}function Xt(t,e,n,o,p,M){var b,c;if("object"==typeof e){for(c in"string"!=typeof n&&(o=o||n,n=void 0),e)Xt(t,c,n,o,e[c],M);return t}if(null==o&&null==p?(p=n,o=n=void 0):null==p&&("string"==typeof n?(p=o,o=void 0):(p=o,o=n,n=void 0)),!1===p)p=St;else if(!p)return t;return 1===M&&(b=p,p=function(t){return g().off(t),b.apply(this,arguments)},p.guid=b.guid||(b.guid=g.guid++)),t.each((function(){g.event.add(this,e,p,o,n)}))}function xt(t,e,n){n?(ct.set(t,e,!1),g.event.add(t,e,{namespace:!1,handler:function(t){var n,o=ct.get(this,e);if(1&t.isTrigger&&this[e]){if(o)(g.event.special[e]||{}).delegateType&&t.stopPropagation();else if(o=c.call(arguments),ct.set(this,e,o),this[e](),n=ct.get(this,e),ct.set(this,e,!1),o!==n)return t.stopImmediatePropagation(),t.preventDefault(),n}else o&&(ct.set(this,e,g.event.trigger(o[0],o.slice(1),this)),t.stopPropagation(),t.isImmediatePropagationStopped=wt)}})):void 0===ct.get(t,e)&&g.event.add(t,e,wt)}g.event={global:{},add:function(t,e,n,o,p){var M,b,c,r,z,a,i,O,s,A,u,l=ct.get(t);if(Mt(t))for(n.handler&&(n=(M=n).handler,p=M.selector),p&&g.find.matchesSelector(ut,p),n.guid||(n.guid=g.guid++),(r=l.events)||(r=l.events=Object.create(null)),(b=l.handle)||(b=l.handle=function(e){return void 0!==g&&g.event.triggered!==e.type?g.event.dispatch.apply(t,arguments):void 0}),z=(e=(e||"").match(Y)||[""]).length;z--;)s=u=(c=Ct.exec(e[z])||[])[1],A=(c[2]||"").split(".").sort(),s&&(i=g.event.special[s]||{},s=(p?i.delegateType:i.bindType)||s,i=g.event.special[s]||{},a=g.extend({type:s,origType:u,data:o,handler:n,guid:n.guid,selector:p,needsContext:p&&g.expr.match.needsContext.test(p),namespace:A.join(".")},M),(O=r[s])||((O=r[s]=[]).delegateCount=0,i.setup&&!1!==i.setup.call(t,o,A,b)||t.addEventListener&&t.addEventListener(s,b)),i.add&&(i.add.call(t,a),a.handler.guid||(a.handler.guid=n.guid)),p?O.splice(O.delegateCount++,0,a):O.push(a),g.event.global[s]=!0)},remove:function(t,e,n,o,p){var M,b,c,r,z,a,i,O,s,A,u,l=ct.hasData(t)&&ct.get(t);if(l&&(r=l.events)){for(z=(e=(e||"").match(Y)||[""]).length;z--;)if(s=u=(c=Ct.exec(e[z])||[])[1],A=(c[2]||"").split(".").sort(),s){for(i=g.event.special[s]||{},O=r[s=(o?i.delegateType:i.bindType)||s]||[],c=c[2]&&new RegExp("(^|\\.)"+A.join("\\.(?:.*\\.|)")+"(\\.|$)"),b=M=O.length;M--;)a=O[M],!p&&u!==a.origType||n&&n.guid!==a.guid||c&&!c.test(a.namespace)||o&&o!==a.selector&&("**"!==o||!a.selector)||(O.splice(M,1),a.selector&&O.delegateCount--,i.remove&&i.remove.call(t,a));b&&!O.length&&(i.teardown&&!1!==i.teardown.call(t,A,l.handle)||g.removeEvent(t,s,l.handle),delete r[s])}else for(s in r)g.event.remove(t,s+e[z],n,o,!0);g.isEmptyObject(r)&&ct.remove(t,"handle events")}},dispatch:function(t){var e,n,o,p,M,b,c=new Array(arguments.length),r=g.event.fix(t),z=(ct.get(this,"events")||Object.create(null))[r.type]||[],a=g.event.special[r.type]||{};for(c[0]=r,e=1;e=1))for(;z!==this;z=z.parentNode||this)if(1===z.nodeType&&("click"!==t.type||!0!==z.disabled)){for(M=[],b={},n=0;n-1:g.find(p,this,null,[z]).length),b[p]&&M.push(o);M.length&&c.push({elem:z,handlers:M})}return z=this,r\s*$/g;function Pt(t,e){return y(t,"table")&&y(11!==e.nodeType?e:e.firstChild,"tr")&&g(t).children("tbody")[0]||t}function Ut(t){return t.type=(null!==t.getAttribute("type"))+"/"+t.type,t}function jt(t){return"true/"===(t.type||"").slice(0,5)?t.type=t.type.slice(5):t.removeAttribute("type"),t}function Ht(t,e){var n,o,p,M,b,c;if(1===e.nodeType){if(ct.hasData(t)&&(c=ct.get(t).events))for(p in ct.remove(e,"handle events"),c)for(n=0,o=c[p].length;n1&&"string"==typeof A&&!l.checkClone&&It.test(A))return t.each((function(p){var M=t.eq(p);u&&(e[0]=A.call(this,p,M.html())),Gt(M,e,n,o)}));if(O&&(M=(p=Bt(e,t[0].ownerDocument,!1,t,o)).firstChild,1===p.childNodes.length&&(p=M),M||o)){for(c=(b=g.map(Nt(p,"script"),Ut)).length;i0&&Et(b,!r&&Nt(t,"script")),c},cleanData:function(t){for(var e,n,o,p=g.event.special,M=0;void 0!==(n=t[M]);M++)if(Mt(n)){if(e=n[ct.expando]){if(e.events)for(o in e.events)p[o]?g.event.remove(n,o):g.removeEvent(n,o,e.handle);n[ct.expando]=void 0}n[rt.expando]&&(n[rt.expando]=void 0)}}}),g.fn.extend({detach:function(t){return Yt(this,t,!0)},remove:function(t){return Yt(this,t)},text:function(t){return tt(this,(function(t){return void 0===t?g.text(this):this.empty().each((function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=t)}))}),null,t,arguments.length)},append:function(){return Gt(this,arguments,(function(t){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Pt(this,t).appendChild(t)}))},prepend:function(){return Gt(this,arguments,(function(t){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var e=Pt(this,t);e.insertBefore(t,e.firstChild)}}))},before:function(){return Gt(this,arguments,(function(t){this.parentNode&&this.parentNode.insertBefore(t,this)}))},after:function(){return Gt(this,arguments,(function(t){this.parentNode&&this.parentNode.insertBefore(t,this.nextSibling)}))},empty:function(){for(var t,e=0;null!=(t=this[e]);e++)1===t.nodeType&&(g.cleanData(Nt(t,!1)),t.textContent="");return this},clone:function(t,e){return t=null!=t&&t,e=null==e?t:e,this.map((function(){return g.clone(this,t,e)}))},html:function(t){return tt(this,(function(t){var e=this[0]||{},n=0,o=this.length;if(void 0===t&&1===e.nodeType)return e.innerHTML;if("string"==typeof t&&!kt.test(t)&&!_t[(Lt.exec(t)||["",""])[1].toLowerCase()]){t=g.htmlPrefilter(t);try{for(;n=0&&(r+=Math.max(0,Math.ceil(t["offset"+e[0].toUpperCase()+e.slice(1)]-M-r-c-.5))||0),r+z}function ae(t,e,n){var o=Kt(t),p=(!l.boxSizingReliable()||n)&&"border-box"===g.css(t,"boxSizing",!1,o),M=p,b=Zt(t,e,o),c="offset"+e[0].toUpperCase()+e.slice(1);if($t.test(b)){if(!n)return b;b="auto"}return(!l.boxSizingReliable()&&p||!l.reliableTrDimensions()&&y(t,"tr")||"auto"===b||!parseFloat(b)&&"inline"===g.css(t,"display",!1,o))&&t.getClientRects().length&&(p="border-box"===g.css(t,"boxSizing",!1,o),(M=c in t)&&(b=t[c])),(b=parseFloat(b)||0)+ze(t,e,n||(p?"border":"content"),M,o,b)+"px"}function ie(t,e,n,o,p){return new ie.prototype.init(t,e,n,o,p)}g.extend({cssHooks:{opacity:{get:function(t,e){if(e){var n=Zt(t,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,aspectRatio:!0,borderImageSlice:!0,columnCount:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,scale:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeMiterlimit:!0,strokeOpacity:!0},cssProps:{},style:function(t,e,n,o){if(t&&3!==t.nodeType&&8!==t.nodeType&&t.style){var p,M,b,c=pt(e),r=Vt.test(e),z=t.style;if(r||(e=pe(c)),b=g.cssHooks[e]||g.cssHooks[c],void 0===n)return b&&"get"in b&&void 0!==(p=b.get(t,!1,o))?p:z[e];"string"===(M=typeof n)&&(p=st.exec(n))&&p[1]&&(n=qt(t,e,p),M="number"),null!=n&&n==n&&("number"!==M||r||(n+=p&&p[3]||(g.cssNumber[c]?"":"px")),l.clearCloneStyle||""!==n||0!==e.indexOf("background")||(z[e]="inherit"),b&&"set"in b&&void 0===(n=b.set(t,n,o))||(r?z.setProperty(e,n):z[e]=n))}},css:function(t,e,n,o){var p,M,b,c=pt(e);return Vt.test(e)||(e=pe(c)),(b=g.cssHooks[e]||g.cssHooks[c])&&"get"in b&&(p=b.get(t,!0,n)),void 0===p&&(p=Zt(t,e,o)),"normal"===p&&e in ce&&(p=ce[e]),""===n||n?(M=parseFloat(p),!0===n||isFinite(M)?M||0:p):p}}),g.each(["height","width"],(function(t,e){g.cssHooks[e]={get:function(t,n,o){if(n)return!Me.test(g.css(t,"display"))||t.getClientRects().length&&t.getBoundingClientRect().width?ae(t,e,o):Qt(t,be,(function(){return ae(t,e,o)}))},set:function(t,n,o){var p,M=Kt(t),b=!l.scrollboxSize()&&"absolute"===M.position,c=(b||o)&&"border-box"===g.css(t,"boxSizing",!1,M),r=o?ze(t,e,o,c,M):0;return c&&b&&(r-=Math.ceil(t["offset"+e[0].toUpperCase()+e.slice(1)]-parseFloat(M[e])-ze(t,e,"border",!1,M)-.5)),r&&(p=st.exec(n))&&"px"!==(p[3]||"px")&&(t.style[e]=n,n=g.css(t,e)),re(0,n,r)}}})),g.cssHooks.marginLeft=te(l.reliableMarginLeft,(function(t,e){if(e)return(parseFloat(Zt(t,"marginLeft"))||t.getBoundingClientRect().left-Qt(t,{marginLeft:0},(function(){return t.getBoundingClientRect().left})))+"px"})),g.each({margin:"",padding:"",border:"Width"},(function(t,e){g.cssHooks[t+e]={expand:function(n){for(var o=0,p={},M="string"==typeof n?n.split(" "):[n];o<4;o++)p[t+At[o]+e]=M[o]||M[o-2]||M[0];return p}},"margin"!==t&&(g.cssHooks[t+e].set=re)})),g.fn.extend({css:function(t,e){return tt(this,(function(t,e,n){var o,p,M={},b=0;if(Array.isArray(e)){for(o=Kt(t),p=e.length;b1)}}),g.Tween=ie,ie.prototype={constructor:ie,init:function(t,e,n,o,p,M){this.elem=t,this.prop=n,this.easing=p||g.easing._default,this.options=e,this.start=this.now=this.cur(),this.end=o,this.unit=M||(g.cssNumber[n]?"":"px")},cur:function(){var t=ie.propHooks[this.prop];return t&&t.get?t.get(this):ie.propHooks._default.get(this)},run:function(t){var e,n=ie.propHooks[this.prop];return this.options.duration?this.pos=e=g.easing[this.easing](t,this.options.duration*t,0,1,this.options.duration):this.pos=e=t,this.now=(this.end-this.start)*e+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):ie.propHooks._default.set(this),this}},ie.prototype.init.prototype=ie.prototype,ie.propHooks={_default:{get:function(t){var e;return 1!==t.elem.nodeType||null!=t.elem[t.prop]&&null==t.elem.style[t.prop]?t.elem[t.prop]:(e=g.css(t.elem,t.prop,""))&&"auto"!==e?e:0},set:function(t){g.fx.step[t.prop]?g.fx.step[t.prop](t):1!==t.elem.nodeType||!g.cssHooks[t.prop]&&null==t.elem.style[pe(t.prop)]?t.elem[t.prop]=t.now:g.style(t.elem,t.prop,t.now+t.unit)}}},ie.propHooks.scrollTop=ie.propHooks.scrollLeft={set:function(t){t.elem.nodeType&&t.elem.parentNode&&(t.elem[t.prop]=t.now)}},g.easing={linear:function(t){return t},swing:function(t){return.5-Math.cos(t*Math.PI)/2},_default:"swing"},g.fx=ie.prototype.init,g.fx.step={};var Oe,se,Ae=/^(?:toggle|show|hide)$/,ue=/queueHooks$/;function le(){se&&(!1===q.hidden&&o.requestAnimationFrame?o.requestAnimationFrame(le):o.setTimeout(le,g.fx.interval),g.fx.tick())}function de(){return o.setTimeout((function(){Oe=void 0})),Oe=Date.now()}function fe(t,e){var n,o=0,p={height:t};for(e=e?1:0;o<4;o+=2-e)p["margin"+(n=At[o])]=p["padding"+n]=t;return e&&(p.opacity=p.width=t),p}function qe(t,e,n){for(var o,p=(he.tweeners[e]||[]).concat(he.tweeners["*"]),M=0,b=p.length;M1)},removeAttr:function(t){return this.each((function(){g.removeAttr(this,t)}))}}),g.extend({attr:function(t,e,n){var o,p,M=t.nodeType;if(3!==M&&8!==M&&2!==M)return void 0===t.getAttribute?g.prop(t,e,n):(1===M&&g.isXMLDoc(t)||(p=g.attrHooks[e.toLowerCase()]||(g.expr.match.bool.test(e)?We:void 0)),void 0!==n?null===n?void g.removeAttr(t,e):p&&"set"in p&&void 0!==(o=p.set(t,n,e))?o:(t.setAttribute(e,n+""),n):p&&"get"in p&&null!==(o=p.get(t,e))?o:null==(o=g.find.attr(t,e))?void 0:o)},attrHooks:{type:{set:function(t,e){if(!l.radioValue&&"radio"===e&&y(t,"input")){var n=t.value;return t.setAttribute("type",e),n&&(t.value=n),e}}}},removeAttr:function(t,e){var n,o=0,p=e&&e.match(Y);if(p&&1===t.nodeType)for(;n=p[o++];)t.removeAttribute(n)}}),We={set:function(t,e,n){return!1===e?g.removeAttr(t,n):t.setAttribute(n,n),n}},g.each(g.expr.match.bool.source.match(/\w+/g),(function(t,e){var n=ve[e]||g.find.attr;ve[e]=function(t,e,o){var p,M,b=e.toLowerCase();return o||(M=ve[b],ve[b]=p,p=null!=n(t,e,o)?b:null,ve[b]=M),p}}));var Re=/^(?:input|select|textarea|button)$/i,me=/^(?:a|area)$/i;function ge(t){return(t.match(Y)||[]).join(" ")}function Le(t){return t.getAttribute&&t.getAttribute("class")||""}function ye(t){return Array.isArray(t)?t:"string"==typeof t&&t.match(Y)||[]}g.fn.extend({prop:function(t,e){return tt(this,g.prop,t,e,arguments.length>1)},removeProp:function(t){return this.each((function(){delete this[g.propFix[t]||t]}))}}),g.extend({prop:function(t,e,n){var o,p,M=t.nodeType;if(3!==M&&8!==M&&2!==M)return 1===M&&g.isXMLDoc(t)||(e=g.propFix[e]||e,p=g.propHooks[e]),void 0!==n?p&&"set"in p&&void 0!==(o=p.set(t,n,e))?o:t[e]=n:p&&"get"in p&&null!==(o=p.get(t,e))?o:t[e]},propHooks:{tabIndex:{get:function(t){var e=g.find.attr(t,"tabindex");return e?parseInt(e,10):Re.test(t.nodeName)||me.test(t.nodeName)&&t.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),l.optSelected||(g.propHooks.selected={get:function(t){var e=t.parentNode;return e&&e.parentNode&&e.parentNode.selectedIndex,null},set:function(t){var e=t.parentNode;e&&(e.selectedIndex,e.parentNode&&e.parentNode.selectedIndex)}}),g.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],(function(){g.propFix[this.toLowerCase()]=this})),g.fn.extend({addClass:function(t){var e,n,o,p,M,b;return d(t)?this.each((function(e){g(this).addClass(t.call(this,e,Le(this)))})):(e=ye(t)).length?this.each((function(){if(o=Le(this),n=1===this.nodeType&&" "+ge(o)+" "){for(M=0;M-1;)n=n.replace(" "+p+" "," ");b=ge(n),o!==b&&this.setAttribute("class",b)}})):this:this.attr("class","")},toggleClass:function(t,e){var n,o,p,M,b=typeof t,c="string"===b||Array.isArray(t);return d(t)?this.each((function(n){g(this).toggleClass(t.call(this,n,Le(this),e),e)})):"boolean"==typeof e&&c?e?this.addClass(t):this.removeClass(t):(n=ye(t),this.each((function(){if(c)for(M=g(this),p=0;p-1)return!0;return!1}});var _e=/\r/g;g.fn.extend({val:function(t){var e,n,o,p=this[0];return arguments.length?(o=d(t),this.each((function(n){var p;1===this.nodeType&&(null==(p=o?t.call(this,n,g(this).val()):t)?p="":"number"==typeof p?p+="":Array.isArray(p)&&(p=g.map(p,(function(t){return null==t?"":t+""}))),(e=g.valHooks[this.type]||g.valHooks[this.nodeName.toLowerCase()])&&"set"in e&&void 0!==e.set(this,p,"value")||(this.value=p))}))):p?(e=g.valHooks[p.type]||g.valHooks[p.nodeName.toLowerCase()])&&"get"in e&&void 0!==(n=e.get(p,"value"))?n:"string"==typeof(n=p.value)?n.replace(_e,""):null==n?"":n:void 0}}),g.extend({valHooks:{option:{get:function(t){var e=g.find.attr(t,"value");return null!=e?e:ge(g.text(t))}},select:{get:function(t){var e,n,o,p=t.options,M=t.selectedIndex,b="select-one"===t.type,c=b?null:[],r=b?M+1:p.length;for(o=M<0?r:b?M:0;o-1)&&(n=!0);return n||(t.selectedIndex=-1),M}}}}),g.each(["radio","checkbox"],(function(){g.valHooks[this]={set:function(t,e){if(Array.isArray(e))return t.checked=g.inArray(g(t).val(),e)>-1}},l.checkOn||(g.valHooks[this].get=function(t){return null===t.getAttribute("value")?"on":t.value})}));var Ne=o.location,Ee={guid:Date.now()},Te=/\?/;g.parseXML=function(t){var e,n;if(!t||"string"!=typeof t)return null;try{e=(new o.DOMParser).parseFromString(t,"text/xml")}catch(t){}return n=e&&e.getElementsByTagName("parsererror")[0],e&&!n||g.error("Invalid XML: "+(n?g.map(n.childNodes,(function(t){return t.textContent})).join("\n"):t)),e};var Be=/^(?:focusinfocus|focusoutblur)$/,Ce=function(t){t.stopPropagation()};g.extend(g.event,{trigger:function(t,e,n,p){var M,b,c,r,z,a,i,O,A=[n||q],u=s.call(t,"type")?t.type:t,l=s.call(t,"namespace")?t.namespace.split("."):[];if(b=O=c=n=n||q,3!==n.nodeType&&8!==n.nodeType&&!Be.test(u+g.event.triggered)&&(u.indexOf(".")>-1&&(l=u.split("."),u=l.shift(),l.sort()),z=u.indexOf(":")<0&&"on"+u,(t=t[g.expando]?t:new g.Event(u,"object"==typeof t&&t)).isTrigger=p?2:3,t.namespace=l.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+l.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=n),e=null==e?[t]:g.makeArray(e,[t]),i=g.event.special[u]||{},p||!i.trigger||!1!==i.trigger.apply(n,e))){if(!p&&!i.noBubble&&!f(n)){for(r=i.delegateType||u,Be.test(r+u)||(b=b.parentNode);b;b=b.parentNode)A.push(b),c=b;c===(n.ownerDocument||q)&&A.push(c.defaultView||c.parentWindow||o)}for(M=0;(b=A[M++])&&!t.isPropagationStopped();)O=b,t.type=M>1?r:i.bindType||u,(a=(ct.get(b,"events")||Object.create(null))[t.type]&&ct.get(b,"handle"))&&a.apply(b,e),(a=z&&b[z])&&a.apply&&Mt(b)&&(t.result=a.apply(b,e),!1===t.result&&t.preventDefault());return t.type=u,p||t.isDefaultPrevented()||i._default&&!1!==i._default.apply(A.pop(),e)||!Mt(n)||z&&d(n[u])&&!f(n)&&((c=n[z])&&(n[z]=null),g.event.triggered=u,t.isPropagationStopped()&&O.addEventListener(u,Ce),n[u](),t.isPropagationStopped()&&O.removeEventListener(u,Ce),g.event.triggered=void 0,c&&(n[z]=c)),t.result}},simulate:function(t,e,n){var o=g.extend(new g.Event,n,{type:t,isSimulated:!0});g.event.trigger(o,null,e)}}),g.fn.extend({trigger:function(t,e){return this.each((function(){g.event.trigger(t,e,this)}))},triggerHandler:function(t,e){var n=this[0];if(n)return g.event.trigger(t,e,n,!0)}});var we=/\[\]$/,Se=/\r?\n/g,Xe=/^(?:submit|button|image|reset|file)$/i,xe=/^(?:input|select|textarea|keygen)/i;function ke(t,e,n,o){var p;if(Array.isArray(e))g.each(e,(function(e,p){n||we.test(t)?o(t,p):ke(t+"["+("object"==typeof p&&null!=p?e:"")+"]",p,n,o)}));else if(n||"object"!==v(e))o(t,e);else for(p in e)ke(t+"["+p+"]",e[p],n,o)}g.param=function(t,e){var n,o=[],p=function(t,e){var n=d(e)?e():e;o[o.length]=encodeURIComponent(t)+"="+encodeURIComponent(null==n?"":n)};if(null==t)return"";if(Array.isArray(t)||t.jquery&&!g.isPlainObject(t))g.each(t,(function(){p(this.name,this.value)}));else for(n in t)ke(n,t[n],e,p);return o.join("&")},g.fn.extend({serialize:function(){return g.param(this.serializeArray())},serializeArray:function(){return this.map((function(){var t=g.prop(this,"elements");return t?g.makeArray(t):this})).filter((function(){var t=this.type;return this.name&&!g(this).is(":disabled")&&xe.test(this.nodeName)&&!Xe.test(t)&&(this.checked||!gt.test(t))})).map((function(t,e){var n=g(this).val();return null==n?null:Array.isArray(n)?g.map(n,(function(t){return{name:e.name,value:t.replace(Se,"\r\n")}})):{name:e.name,value:n.replace(Se,"\r\n")}})).get()}});var Ie=/%20/g,De=/#.*$/,Pe=/([?&])_=[^&]*/,Ue=/^(.*?):[ \t]*([^\r\n]*)$/gm,je=/^(?:GET|HEAD)$/,He=/^\/\//,Fe={},Ge={},Ye="*/".concat("*"),$e=q.createElement("a");function Ve(t){return function(e,n){"string"!=typeof e&&(n=e,e="*");var o,p=0,M=e.toLowerCase().match(Y)||[];if(d(n))for(;o=M[p++];)"+"===o[0]?(o=o.slice(1)||"*",(t[o]=t[o]||[]).unshift(n)):(t[o]=t[o]||[]).push(n)}}function Ke(t,e,n,o){var p={},M=t===Ge;function b(c){var r;return p[c]=!0,g.each(t[c]||[],(function(t,c){var z=c(e,n,o);return"string"!=typeof z||M||p[z]?M?!(r=z):void 0:(e.dataTypes.unshift(z),b(z),!1)})),r}return b(e.dataTypes[0])||!p["*"]&&b("*")}function Qe(t,e){var n,o,p=g.ajaxSettings.flatOptions||{};for(n in e)void 0!==e[n]&&((p[n]?t:o||(o={}))[n]=e[n]);return o&&g.extend(!0,t,o),t}$e.href=Ne.href,g.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ne.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Ne.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Ye,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":g.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(t,e){return e?Qe(Qe(t,g.ajaxSettings),e):Qe(g.ajaxSettings,t)},ajaxPrefilter:Ve(Fe),ajaxTransport:Ve(Ge),ajax:function(t,e){"object"==typeof t&&(e=t,t=void 0),e=e||{};var n,p,M,b,c,r,z,a,i,O,s=g.ajaxSetup({},e),A=s.context||s,u=s.context&&(A.nodeType||A.jquery)?g(A):g.event,l=g.Deferred(),d=g.Callbacks("once memory"),f=s.statusCode||{},h={},W={},v="canceled",R={readyState:0,getResponseHeader:function(t){var e;if(z){if(!b)for(b={};e=Ue.exec(M);)b[e[1].toLowerCase()+" "]=(b[e[1].toLowerCase()+" "]||[]).concat(e[2]);e=b[t.toLowerCase()+" "]}return null==e?null:e.join(", ")},getAllResponseHeaders:function(){return z?M:null},setRequestHeader:function(t,e){return null==z&&(t=W[t.toLowerCase()]=W[t.toLowerCase()]||t,h[t]=e),this},overrideMimeType:function(t){return null==z&&(s.mimeType=t),this},statusCode:function(t){var e;if(t)if(z)R.always(t[R.status]);else for(e in t)f[e]=[f[e],t[e]];return this},abort:function(t){var e=t||v;return n&&n.abort(e),m(0,e),this}};if(l.promise(R),s.url=((t||s.url||Ne.href)+"").replace(He,Ne.protocol+"//"),s.type=e.method||e.type||s.method||s.type,s.dataTypes=(s.dataType||"*").toLowerCase().match(Y)||[""],null==s.crossDomain){r=q.createElement("a");try{r.href=s.url,r.href=r.href,s.crossDomain=$e.protocol+"//"+$e.host!=r.protocol+"//"+r.host}catch(t){s.crossDomain=!0}}if(s.data&&s.processData&&"string"!=typeof s.data&&(s.data=g.param(s.data,s.traditional)),Ke(Fe,s,e,R),z)return R;for(i in(a=g.event&&s.global)&&0==g.active++&&g.event.trigger("ajaxStart"),s.type=s.type.toUpperCase(),s.hasContent=!je.test(s.type),p=s.url.replace(De,""),s.hasContent?s.data&&s.processData&&0===(s.contentType||"").indexOf("application/x-www-form-urlencoded")&&(s.data=s.data.replace(Ie,"+")):(O=s.url.slice(p.length),s.data&&(s.processData||"string"==typeof s.data)&&(p+=(Te.test(p)?"&":"?")+s.data,delete s.data),!1===s.cache&&(p=p.replace(Pe,"$1"),O=(Te.test(p)?"&":"?")+"_="+Ee.guid+++O),s.url=p+O),s.ifModified&&(g.lastModified[p]&&R.setRequestHeader("If-Modified-Since",g.lastModified[p]),g.etag[p]&&R.setRequestHeader("If-None-Match",g.etag[p])),(s.data&&s.hasContent&&!1!==s.contentType||e.contentType)&&R.setRequestHeader("Content-Type",s.contentType),R.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+("*"!==s.dataTypes[0]?", "+Ye+"; q=0.01":""):s.accepts["*"]),s.headers)R.setRequestHeader(i,s.headers[i]);if(s.beforeSend&&(!1===s.beforeSend.call(A,R,s)||z))return R.abort();if(v="abort",d.add(s.complete),R.done(s.success),R.fail(s.error),n=Ke(Ge,s,e,R)){if(R.readyState=1,a&&u.trigger("ajaxSend",[R,s]),z)return R;s.async&&s.timeout>0&&(c=o.setTimeout((function(){R.abort("timeout")}),s.timeout));try{z=!1,n.send(h,m)}catch(t){if(z)throw t;m(-1,t)}}else m(-1,"No Transport");function m(t,e,b,r){var i,O,q,h,W,v=e;z||(z=!0,c&&o.clearTimeout(c),n=void 0,M=r||"",R.readyState=t>0?4:0,i=t>=200&&t<300||304===t,b&&(h=function(t,e,n){for(var o,p,M,b,c=t.contents,r=t.dataTypes;"*"===r[0];)r.shift(),void 0===o&&(o=t.mimeType||e.getResponseHeader("Content-Type"));if(o)for(p in c)if(c[p]&&c[p].test(o)){r.unshift(p);break}if(r[0]in n)M=r[0];else{for(p in n){if(!r[0]||t.converters[p+" "+r[0]]){M=p;break}b||(b=p)}M=M||b}if(M)return M!==r[0]&&r.unshift(M),n[M]}(s,R,b)),!i&&g.inArray("script",s.dataTypes)>-1&&g.inArray("json",s.dataTypes)<0&&(s.converters["text script"]=function(){}),h=function(t,e,n,o){var p,M,b,c,r,z={},a=t.dataTypes.slice();if(a[1])for(b in t.converters)z[b.toLowerCase()]=t.converters[b];for(M=a.shift();M;)if(t.responseFields[M]&&(n[t.responseFields[M]]=e),!r&&o&&t.dataFilter&&(e=t.dataFilter(e,t.dataType)),r=M,M=a.shift())if("*"===M)M=r;else if("*"!==r&&r!==M){if(!(b=z[r+" "+M]||z["* "+M]))for(p in z)if((c=p.split(" "))[1]===M&&(b=z[r+" "+c[0]]||z["* "+c[0]])){!0===b?b=z[p]:!0!==z[p]&&(M=c[0],a.unshift(c[1]));break}if(!0!==b)if(b&&t.throws)e=b(e);else try{e=b(e)}catch(t){return{state:"parsererror",error:b?t:"No conversion from "+r+" to "+M}}}return{state:"success",data:e}}(s,h,R,i),i?(s.ifModified&&((W=R.getResponseHeader("Last-Modified"))&&(g.lastModified[p]=W),(W=R.getResponseHeader("etag"))&&(g.etag[p]=W)),204===t||"HEAD"===s.type?v="nocontent":304===t?v="notmodified":(v=h.state,O=h.data,i=!(q=h.error))):(q=v,!t&&v||(v="error",t<0&&(t=0))),R.status=t,R.statusText=(e||v)+"",i?l.resolveWith(A,[O,v,R]):l.rejectWith(A,[R,v,q]),R.statusCode(f),f=void 0,a&&u.trigger(i?"ajaxSuccess":"ajaxError",[R,s,i?O:q]),d.fireWith(A,[R,v]),a&&(u.trigger("ajaxComplete",[R,s]),--g.active||g.event.trigger("ajaxStop")))}return R},getJSON:function(t,e,n){return g.get(t,e,n,"json")},getScript:function(t,e){return g.get(t,void 0,e,"script")}}),g.each(["get","post"],(function(t,e){g[e]=function(t,n,o,p){return d(n)&&(p=p||o,o=n,n=void 0),g.ajax(g.extend({url:t,type:e,dataType:p,data:n,success:o},g.isPlainObject(t)&&t))}})),g.ajaxPrefilter((function(t){var e;for(e in t.headers)"content-type"===e.toLowerCase()&&(t.contentType=t.headers[e]||"")})),g._evalUrl=function(t,e,n){return g.ajax({url:t,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(t){g.globalEval(t,e,n)}})},g.fn.extend({wrapAll:function(t){var e;return this[0]&&(d(t)&&(t=t.call(this[0])),e=g(t,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&e.insertBefore(this[0]),e.map((function(){for(var t=this;t.firstElementChild;)t=t.firstElementChild;return t})).append(this)),this},wrapInner:function(t){return d(t)?this.each((function(e){g(this).wrapInner(t.call(this,e))})):this.each((function(){var e=g(this),n=e.contents();n.length?n.wrapAll(t):e.append(t)}))},wrap:function(t){var e=d(t);return this.each((function(n){g(this).wrapAll(e?t.call(this,n):t)}))},unwrap:function(t){return this.parent(t).not("body").each((function(){g(this).replaceWith(this.childNodes)})),this}}),g.expr.pseudos.hidden=function(t){return!g.expr.pseudos.visible(t)},g.expr.pseudos.visible=function(t){return!!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)},g.ajaxSettings.xhr=function(){try{return new o.XMLHttpRequest}catch(t){}};var Je={0:200,1223:204},Ze=g.ajaxSettings.xhr();l.cors=!!Ze&&"withCredentials"in Ze,l.ajax=Ze=!!Ze,g.ajaxTransport((function(t){var e,n;if(l.cors||Ze&&!t.crossDomain)return{send:function(p,M){var b,c=t.xhr();if(c.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(b in t.xhrFields)c[b]=t.xhrFields[b];for(b in t.mimeType&&c.overrideMimeType&&c.overrideMimeType(t.mimeType),t.crossDomain||p["X-Requested-With"]||(p["X-Requested-With"]="XMLHttpRequest"),p)c.setRequestHeader(b,p[b]);e=function(t){return function(){e&&(e=n=c.onload=c.onerror=c.onabort=c.ontimeout=c.onreadystatechange=null,"abort"===t?c.abort():"error"===t?"number"!=typeof c.status?M(0,"error"):M(c.status,c.statusText):M(Je[c.status]||c.status,c.statusText,"text"!==(c.responseType||"text")||"string"!=typeof c.responseText?{binary:c.response}:{text:c.responseText},c.getAllResponseHeaders()))}},c.onload=e(),n=c.onerror=c.ontimeout=e("error"),void 0!==c.onabort?c.onabort=n:c.onreadystatechange=function(){4===c.readyState&&o.setTimeout((function(){e&&n()}))},e=e("abort");try{c.send(t.hasContent&&t.data||null)}catch(t){if(e)throw t}},abort:function(){e&&e()}}})),g.ajaxPrefilter((function(t){t.crossDomain&&(t.contents.script=!1)})),g.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(t){return g.globalEval(t),t}}}),g.ajaxPrefilter("script",(function(t){void 0===t.cache&&(t.cache=!1),t.crossDomain&&(t.type="GET")})),g.ajaxTransport("script",(function(t){var e,n;if(t.crossDomain||t.scriptAttrs)return{send:function(o,p){e=g(" - @endscript diff --git a/resources/views/livewire/project/application/preview/form.blade.php b/resources/views/livewire/project/application/preview/form.blade.php index fda54e31f..a273de810 100644 --- a/resources/views/livewire/project/application/preview/form.blade.php +++ b/resources/views/livewire/project/application/preview/form.blade.php @@ -7,7 +7,7 @@
Preview Deployments based on pull requests are here.
+ helper="Templates:
@@{{ random }} to generate random sub-domain each time a PR is deployed
@@{{ pr_id }} to use pull request ID as sub-domain or @@{{ domain }} to replace the domain name with the application's domain name." /> @if ($previewUrlTemplate)
Domain Preview: {{ $previewUrlTemplate }}
@endif diff --git a/resources/views/livewire/project/application/previews.blade.php b/resources/views/livewire/project/application/previews.blade.php index 876aba17a..37f7e35b5 100644 --- a/resources/views/livewire/project/application/previews.blade.php +++ b/resources/views/livewire/project/application/previews.blade.php @@ -130,6 +130,22 @@ @endif
+ + + + + + + + + Force deploy (without + cache) + @if (data_get($preview, 'status') === 'exited') @if (data_get($preview, 'status') !== 'exited') - + @endif - +
@endforeach diff --git a/resources/views/livewire/project/database/backup/index.blade.php b/resources/views/livewire/project/database/backup/index.blade.php index e9ba05431..91f0676aa 100644 --- a/resources/views/livewire/project/database/backup/index.blade.php +++ b/resources/views/livewire/project/database/backup/index.blade.php @@ -5,7 +5,7 @@

Backups

-
+

Scheduled Backups

diff --git a/resources/views/livewire/project/database/configuration.blade.php b/resources/views/livewire/project/database/configuration.blade.php index f968acacd..5e1600461 100644 --- a/resources/views/livewire/project/database/configuration.blade.php +++ b/resources/views/livewire/project/database/configuration.blade.php @@ -5,7 +5,7 @@

Configuration

-
+
General diff --git a/resources/views/livewire/project/database/heading.blade.php b/resources/views/livewire/project/database/heading.blade.php index 03f09591c..43fa44eca 100644 --- a/resources/views/livewire/project/database/heading.blade.php +++ b/resources/views/livewire/project/database/heading.blade.php @@ -1,15 +1,15 @@ -