From 72ddfc6bf3ac04b05704af1cb63dc9a87bb45056 Mon Sep 17 00:00:00 2001 From: Felipe Almeman Date: Tue, 24 Feb 2026 21:35:48 -0300 Subject: [PATCH] feat(api): add new endpoints for server message retrieval and management - Implemented GET /api/server/{token}/messages for retrieving messages with pagination and filtering options. - Added POST /server/{token}/disable to stop a WhatsApp server instance. - Added POST /server/{token}/enable to start a WhatsApp server instance. - Introduced POST /server/{token}/messages/{messageid}/history/download for downloading media from history-sync events. - Updated command execution endpoint to accept a request body with action and token. - Enhanced pending messages retrieval with additional filtering options. - Added new properties for environment settings including branding and login customization options. fix(webserver): improve SPA serving logic - Added ServeSPA function to handle serving the frontend application in both development and production modes. - Implemented reverse proxy for development mode to route requests to the Vite dev server. - Enhanced static file serving and fallback to index.html for SPA routes. refactor(whatsapp): extend WhatsappBoolean functionality - Added ToWhatsappBoolean method to convert WhatsappBooleanExtended to WhatsappBoolean. --- .gitignore | 2 + AGENTS.md | 27 + src/.env.example | 45 +- src/api/api.go | 12 +- .../api_handlers+HistoryDownloadController.go | 208 ++ src/api/api_handlers+LoginController.go | 47 + src/api/api_handlers+SPAController.go | 2259 +++++++++++++++++ ..._handlers+ServerEnableDisableController.go | 91 + src/api/api_handlers.go | 81 +- src/api/api_spa_routes.go | 105 + src/api/api_spa_utils.go | 25 + src/api/api_websocket_client.go | 180 ++ src/api/api_websocket_hub.go | 49 + src/assets/frontend/assets/groupdetail.css | 1 + src/assets/frontend/assets/groupdetail.js | 1 + src/assets/frontend/assets/groups.css | 1 + src/assets/frontend/assets/groups.js | 1 + src/assets/frontend/assets/index.css | 5 + src/assets/frontend/assets/index.js | 35 + src/assets/frontend/index.html | 15 + src/environment/api_settings.go | 49 +- src/environment/branding_settings.go | 55 + src/environment/environment_settings.go | 23 + src/environment/form_settings.go | 15 +- src/environment/general_settings.go | 29 + src/form/form.go | 6 +- src/form/form_handlers.go | 20 +- src/form/form_json_handlers.go | 28 + src/frontend/.gitignore | 36 + src/frontend/README.md | 32 + src/frontend/index.html | 14 + src/frontend/package-lock.json | 1854 ++++++++++++++ src/frontend/package.json | 25 + src/frontend/src/App.bak | 80 + src/frontend/src/App.vue | 353 +++ src/frontend/src/components/ConfirmModal.vue | 37 + src/frontend/src/components/Toaster.vue | 44 + .../src/components/TriStateToggle.vue | 133 + src/frontend/src/main.ts | 8 + src/frontend/src/pages/Account.vue | 465 ++++ src/frontend/src/pages/Connect.vue | 338 +++ src/frontend/src/pages/Environment.vue | 185 ++ src/frontend/src/pages/GroupDetail.vue | 1054 ++++++++ src/frontend/src/pages/Groups.vue | 971 +++++++ src/frontend/src/pages/Home.vue | 1802 +++++++++++++ src/frontend/src/pages/Login.vue | 561 ++++ src/frontend/src/pages/Messages.vue | 1593 ++++++++++++ src/frontend/src/pages/PairCode.vue | 680 +++++ src/frontend/src/pages/QRCode.vue | 381 +++ src/frontend/src/pages/RabbitMQ.vue | 740 ++++++ src/frontend/src/pages/SendMessage.vue | 1355 ++++++++++ src/frontend/src/pages/Server.vue | 1240 +++++++++ src/frontend/src/pages/Setup.vue | 472 ++++ src/frontend/src/pages/UserCreate.vue | 398 +++ src/frontend/src/pages/Users.vue | 495 ++++ src/frontend/src/pages/Webhooks.vue | 1184 +++++++++ src/frontend/src/router.ts | 60 + src/frontend/src/services/api.ts | 9 + src/frontend/src/services/signalr.ts | 169 ++ src/frontend/src/services/toast.ts | 25 + src/frontend/src/services/ws.ts | 45 + src/frontend/src/stores/session.ts | 32 + src/frontend/src/stores/toast.ts | 38 + src/frontend/src/styles.css | 15 + src/frontend/tsconfig.json | 17 + src/frontend/vite.config.ts | 70 + src/models/qp_receive_response.go | 3 + src/models/qp_whatsapp_extensions.go | 16 + src/models/sqlite_migration.go | 32 + src/swagger/docs.go | 436 +++- src/swagger/swagger.json | 436 +++- src/swagger/swagger.yaml | 296 ++- src/webserver/webserver.go | 152 +- src/whatsapp/whatsapp_boolean_extended.go | 12 + 74 files changed, 21690 insertions(+), 118 deletions(-) create mode 100644 AGENTS.md create mode 100644 src/api/api_handlers+HistoryDownloadController.go create mode 100644 src/api/api_handlers+LoginController.go create mode 100644 src/api/api_handlers+SPAController.go create mode 100644 src/api/api_handlers+ServerEnableDisableController.go create mode 100644 src/api/api_spa_routes.go create mode 100644 src/api/api_spa_utils.go create mode 100644 src/api/api_websocket_client.go create mode 100644 src/api/api_websocket_hub.go create mode 100644 src/assets/frontend/assets/groupdetail.css create mode 100644 src/assets/frontend/assets/groupdetail.js create mode 100644 src/assets/frontend/assets/groups.css create mode 100644 src/assets/frontend/assets/groups.js create mode 100644 src/assets/frontend/assets/index.css create mode 100644 src/assets/frontend/assets/index.js create mode 100644 src/assets/frontend/index.html create mode 100644 src/environment/branding_settings.go create mode 100644 src/form/form_json_handlers.go create mode 100644 src/frontend/.gitignore create mode 100644 src/frontend/README.md create mode 100644 src/frontend/index.html create mode 100644 src/frontend/package-lock.json create mode 100644 src/frontend/package.json create mode 100644 src/frontend/src/App.bak create mode 100644 src/frontend/src/App.vue create mode 100644 src/frontend/src/components/ConfirmModal.vue create mode 100644 src/frontend/src/components/Toaster.vue create mode 100644 src/frontend/src/components/TriStateToggle.vue create mode 100644 src/frontend/src/main.ts create mode 100644 src/frontend/src/pages/Account.vue create mode 100644 src/frontend/src/pages/Connect.vue create mode 100644 src/frontend/src/pages/Environment.vue create mode 100644 src/frontend/src/pages/GroupDetail.vue create mode 100644 src/frontend/src/pages/Groups.vue create mode 100644 src/frontend/src/pages/Home.vue create mode 100644 src/frontend/src/pages/Login.vue create mode 100644 src/frontend/src/pages/Messages.vue create mode 100644 src/frontend/src/pages/PairCode.vue create mode 100644 src/frontend/src/pages/QRCode.vue create mode 100644 src/frontend/src/pages/RabbitMQ.vue create mode 100644 src/frontend/src/pages/SendMessage.vue create mode 100644 src/frontend/src/pages/Server.vue create mode 100644 src/frontend/src/pages/Setup.vue create mode 100644 src/frontend/src/pages/UserCreate.vue create mode 100644 src/frontend/src/pages/Users.vue create mode 100644 src/frontend/src/pages/Webhooks.vue create mode 100644 src/frontend/src/router.ts create mode 100644 src/frontend/src/services/api.ts create mode 100644 src/frontend/src/services/signalr.ts create mode 100644 src/frontend/src/services/toast.ts create mode 100644 src/frontend/src/services/ws.ts create mode 100644 src/frontend/src/stores/session.ts create mode 100644 src/frontend/src/stores/toast.ts create mode 100644 src/frontend/src/styles.css create mode 100644 src/frontend/tsconfig.json create mode 100644 src/frontend/vite.config.ts create mode 100644 src/models/sqlite_migration.go diff --git a/.gitignore b/.gitignore index 3be34acb..0074dc71 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,5 @@ main.exe .telegram.token apoint-voip-server.json src/.env.apoint-voip +bin +pkg \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..f9778fba --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,27 @@ +# SPA Sync From chat.aireset.com.br + +## task objective +Sync SPA updates from `chat.aireset.com.br/src` into `quepasa/src` with full scope (backend SPA + frontend + webserver fallback), versioning frontend assets. + +## mandatory checklist +- [x] Create dedicated feature branch +- [x] Sync SPA backend API routes/controllers/login +- [x] Sync form handlers for SPA-first flow +- [x] Sync webserver SPA fallback behavior +- [x] Sync environment SPA-related settings +- [x] Sync frontend source (`src/frontend`) +- [x] Sync built assets (`src/assets/frontend`) +- [x] Regenerate Swagger docs +- [x] Validate build + +## current status +Branch `feature/spa-sync-from-chat-20260224` with SPA sync completed. Backend build, frontend build, and Swagger generation executed successfully. Local runtime smoke tests executed with app running on port `31000`. + +## next steps +Await user validation/QA in runtime and follow-up adjustments if necessary. Keep temporary runtime env override notes for local startup (`USER`/`PASSWORD`) until seed config is aligned. + +## immutable constraints discovered during execution +- Do not commit or push without explicit user request. +- Keep API prefix aligned for SPA usage (`/api`). +- Preserve SPA auth flow consistency (login/session/cookie JWT). +- Keep swagger in sync after API route/controller changes. diff --git a/src/.env.example b/src/.env.example index a55136ae..c60de8ba 100644 --- a/src/.env.example +++ b/src/.env.example @@ -9,7 +9,7 @@ # WEBAPIHOST - Web server bind address # Options: IP address, hostname, or empty for all interfaces # Examples: localhost, 127.0.0.1, 0.0.0.0, your-domain.com -WEBAPIHOST= +WEBAPIHOST=127.0.0.1 # WEBAPIPORT - Web server listening port # Options: Any valid port number (1-65535) @@ -25,31 +25,31 @@ WEBSOCKETSSL=false # SIGNING_SECRET - Secret key for signing JWT tokens and cookies # Options: Any strong random string (recommended: 32+ characters) # Example: your-super-secret-signing-key-here -SIGNING_SECRET= +SIGNING_SECRET=dev-signing-secret-1234567890-abc # MASTERKEY - Master key for super admin API methods # Options: Any string (acts as super admin password) # Example: your-master-admin-key -MASTERKEY= +MASTERKEY=dev-master-key # USER - Default user for initial database seeding # Options: Any valid email address or username # Default: Uses "default@quepasa.io" if not set # Note: Only used during first startup when no users exist # IMPORTANT: ALWAYS CHANGE THIS IN PRODUCTION! -USER=admin@yourdomain.com +USER="contato@localhost.com.br" # PASSWORD - Password for default user # Options: Any strong password (recommended: 12+ characters with mixed case, numbers, symbols) # Default: Creates user with EMPTY password if not set (INSECURE!) # Note: Only used during first startup when no users exist # IMPORTANT: ALWAYS SET THIS IN PRODUCTION! -PASSWORD=YourSecurePassword123!@# +PASSWORD="YourSecurePassword123!@#" # HTTPLOGS - Enable HTTP request logging # Options: true, false # Default: false -HTTPLOGS=false +HTTPLOGS=HTTPLOGS=true # ============================================================================= # MODEL CONTEXT PROTOCOL (MCP) SERVER @@ -59,7 +59,7 @@ HTTPLOGS=false # Options: true, false # Default: false # Note: Allows AI assistants to interact with QuePasa API via MCP protocol -MCP_ENABLED=false +MCP_ENABLED=true # MCP_PATH - MCP server endpoint path # Options: Any valid URL path @@ -75,7 +75,10 @@ MCP_PATH=/mcp # Options: Any positive integer # Default: 10 # Examples: 5, 10, 15, 30 -#WEBHOOK_TIMEOUT=10 +WEBHOOK_TIMEOUT=30 + +# Examples: 1, 2, 4, 8 +WEBHOOK_WORKERS=8 # ============================================================================= # SWAGGER DOCUMENTATION @@ -107,35 +110,35 @@ DBDRIVER=sqlite3 # Options: localhost, IP address, hostname # Examples: localhost, 127.0.0.1, db.example.com # Note: Not needed for sqlite3 -DBHOST= +#DBHOST= # DBDATABASE - Database name # Options: Any valid database name # Examples: quepasa, quepasa_production # Note: For sqlite3, this is the file path -DBDATABASE= +#DBDATABASE= # DBPORT - Database server port # Options: Any valid port number # Examples: 5432 (PostgreSQL), 3306 (MySQL) # Note: Not needed for sqlite3 -DBPORT= +#DBPORT= # DBUSER - Database username # Options: Any valid database username # Note: Not needed for sqlite3 -DBUSER= +#DBUSER= # DBPASSWORD - Database password # Options: Any string # Note: Not needed for sqlite3 -DBPASSWORD= +#DBPASSWORD= # DBSSLMODE - Database SSL connection mode # Options: disable, require, verify-ca, verify-full # Default: disable # Note: PostgreSQL specific -DBSSLMODE= +#DBSSLMODE= # ============================================================================= # WHATSAPP CONFIGURATION @@ -172,7 +175,7 @@ BROADCASTS=false # Options: Any positive integer, or empty for default # Examples: 1, 7, 30 # Note: Higher values may slow initial sync -HISTORYSYNCDAYS= +HISTORYSYNCDAYS=1 # PRESENCE - WhatsApp presence status # Options: available, unavailable, composing, recording, paused @@ -264,19 +267,19 @@ SIPPROXY_RETRIES=3 # Options: DEBUG, INFO, WARN, ERROR, FATAL # Default: INFO # Examples: DEBUG (verbose), INFO (normal), WARN (minimal) -LOGLEVEL= +LOGLEVEL=DEBUG # WHATSMEOW_LOGLEVEL - Whatsmeow library log level # Options: DEBUG, INFO, WARN, ERROR # Default: WARN # Note: Controls WhatsApp protocol library logging -WHATSMEOW_LOGLEVEL= +WHATSMEOW_LOGLEVEL=DEBUG # WHATSMEOW_DBLOGLEVEL - Whatsmeow database operations log level # Options: DEBUG, INFO, WARN, ERROR # Default: WARN # Note: Controls database query logging from Whatsmeow -WHATSMEOW_DBLOGLEVEL= +WHATSMEOW_DBLOGLEVEL=DEBUG # WHATSMEOW_USE_RETRY_MESSAGE_STORE - Persist outgoing messages for retry receipts after restart # Options: true, false @@ -292,13 +295,15 @@ WHATSMEOW_USE_RETRY_MESSAGE_STORE=false # Options: true, false # Default: true # Note: Automatically updates database schema -MIGRATIONS=true +# MIGRATIONS=true +# MIGRATIONS=/opt/quepasa/migrations +MIGRATIONS=./migrations # APP_TITLE - Application title displayed in WhatsApp device list # Options: Any string # Default: QuePasa # Examples: "My WhatsApp Bot", "Company Bot" -APP_TITLE= +APP_TITLE="Hermes" # REMOVEDIGIT9 - Remove digit 9 from Brazilian phone numbers # Options: true, false diff --git a/src/api/api.go b/src/api/api.go index 5e69dbb4..b35e51ff 100644 --- a/src/api/api.go +++ b/src/api/api.go @@ -49,10 +49,20 @@ func Configure(r chi.Router) { })) */ - // Mount API routes under the configured prefix + // Mount API routes under the configured prefix (e.g., /api) r.Route("/"+apiPrefix, func(r chi.Router) { r.Group(RegisterAPIControllers) r.Group(RegisterAPIV3Controllers) + r.Group(RegisterSPAControllers) }) + + // For backward compatibility, also register routes at root level + // when API_PREFIX is not empty. This allows legacy clients using + // /info, /v3/bot/..., /health to continue working. + if apiPrefix != "" { + log.Info("Registering legacy API routes at root level for backward compatibility") + r.Group(RegisterAPIControllers) + r.Group(RegisterAPIV3Controllers) + } }) } diff --git a/src/api/api_handlers+HistoryDownloadController.go b/src/api/api_handlers+HistoryDownloadController.go new file mode 100644 index 00000000..d6504086 --- /dev/null +++ b/src/api/api_handlers+HistoryDownloadController.go @@ -0,0 +1,208 @@ +package api + +import ( + "encoding/json" + "fmt" + "mime" + "net/http" + "path" + "strings" + "time" + + "github.com/go-chi/chi/v5" + models "github.com/nocodeleaks/quepasa/models" + whatsapp "github.com/nocodeleaks/quepasa/whatsapp" + waE2E "go.mau.fi/whatsmeow/proto/waE2E" + "google.golang.org/protobuf/proto" +) + +// SPAServerHistoryDownloadController downloads media referenced by a history-sync ProtocolMessage +// +// @Summary Download history-sync media +// @Description Given a ProtocolMessage history-sync event message id, attempts to download and decrypt the referenced media using the active Whatsmeow connection, attaches it to the message and triggers an update so the UI and dispatchers are notified. +// @Tags SPA +// @Accept json +// @Produce json +// @Param token path string true "Server token" +// @Param messageid path string true "Message id (protocol message)" +// @Success 200 {object} models.QpResponse +// @Failure 400 {object} models.QpResponse +// @Failure 401 {object} models.QpResponse +// @Failure 403 {object} models.QpResponse +// @Failure 503 {object} models.QpResponse +// @Security Bearer +// @Router /server/{token}/messages/{messageid}/history/download [post] +func SPAServerHistoryDownloadController(w http.ResponseWriter, r *http.Request) { + response := &models.QpResponse{} + + // get server + server, err := GetServer(r) + if err != nil { + response.ParseError(err) + RespondInterface(w, response) + return + } + + // check readiness + if server.GetStatus() != whatsapp.Ready { + err := &ApiServerNotReadyException{Wid: server.GetWId(), Status: server.GetStatus()} + response.ParseError(err) + RespondInterfaceCode(w, response, http.StatusServiceUnavailable) + return + } + + messageId := chi.URLParam(r, "messageid") + if messageId == "" { + response.ParseError(fmt.Errorf("missing messageid")) + RespondInterfaceCode(w, response, http.StatusBadRequest) + return + } + + msg, gerr := server.Handler.GetById(messageId) + if gerr != nil { + response.ParseError(gerr) + RespondInterfaceCode(w, response, http.StatusNotFound) + return + } + + if msg.Debug == nil || msg.Debug.Event != "ProtocolMessage" { + response.ParseError(fmt.Errorf("message is not a protocol/history sync event")) + RespondInterfaceCode(w, response, http.StatusBadRequest) + return + } + + // try type assertion + switch debug := msg.Debug.Info.(type) { + case *waE2E.ProtocolMessage: + notif := debug.GetHistorySyncNotification() + if notif == nil { + response.ParseError(fmt.Errorf("no history sync notification inside protocol message")) + RespondInterfaceCode(w, response, http.StatusBadRequest) + return + } + + // Build a temporary waE2E.Message to allow download via existing connection.Download + // We will pick document/image based on filename ext + directPath := notif.GetDirectPath() + var waMsg *waE2E.Message + + // naive extension check + if strings.Contains(strings.ToLower(directPath), ".jpg") || strings.Contains(strings.ToLower(directPath), ".jpeg") || strings.Contains(strings.ToLower(directPath), ".png") || strings.Contains(strings.ToLower(directPath), ".webp") { + internal := &waE2E.ImageMessage{ + DirectPath: proto.String(directPath), + MediaKey: notif.MediaKey, + FileEncSHA256: notif.GetFileEncSHA256(), + FileSHA256: notif.GetFileSHA256(), + FileLength: proto.Uint64(notif.GetFileLength()), + } + waMsg = &waE2E.Message{ImageMessage: internal} + } else { + internal := &waE2E.DocumentMessage{ + DirectPath: proto.String(directPath), + MediaKey: notif.MediaKey, + FileEncSHA256: notif.GetFileEncSHA256(), + FileSHA256: notif.GetFileSHA256(), + FileLength: proto.Uint64(notif.GetFileLength()), + } + waMsg = &waE2E.Message{DocumentMessage: internal} + } + + // create temp wrapper whatsapp message + tmp := &whatsapp.WhatsappMessage{ + Id: msg.Id + "-history-download", + Timestamp: time.Now().UTC(), + Type: whatsapp.UnhandledMessageType, + Chat: msg.Chat, + FromHistory: true, + Content: waMsg, + } + + // attempt download using active connection + conn, cerr := server.GetValidConnection() + if cerr != nil { + response.ParseError(fmt.Errorf("server connection unavailable: %v", cerr)) + RespondInterfaceCode(w, response, http.StatusServiceUnavailable) + return + } + + logentry := server.GetLogger().WithField("messageid", msg.Id) + logentry.Infof("initiating history download for directPath=%s", directPath) + + downloaded, derr := conn.DownloadData(tmp) + if derr != nil { + logentry.Errorf("failed to download history media: %v", derr) + response.ParseError(fmt.Errorf("failed to download history media: %v", derr)) + RespondInterfaceCode(w, response, http.StatusInternalServerError) + return + } + logentry.Infof("downloaded %d bytes for message %s", len(downloaded), msg.Id) + + // attach to existing message + attachment := &whatsapp.WhatsappAttachment{} + // validate content + if len(downloaded) == 0 { + response.ParseError(fmt.Errorf("download returned empty content")) + RespondInterfaceCode(w, response, http.StatusInternalServerError) + return + } + attachment.SetContent(&downloaded) + attachment.FileLength = uint64(len(downloaded)) + + // derive filename and mimetype + attachment.FileName = path.Base(directPath) + if ext := path.Ext(attachment.FileName); len(ext) > 0 { + attachment.Mimetype = mime.TypeByExtension(ext) + } + // sniff content-type as fallback + if attachment.Mimetype == "" { + attachment.Mimetype = http.DetectContentType(downloaded) + } + if attachment.Mimetype == "" { + attachment.Mimetype = "application/octet-stream" + } + + // set a public download url pointing to the standard /download endpoint + if prefix, err := models.GetDownloadPrefixFromToken(server.Token); err == nil { + attachment.Url = prefix + "/" + msg.Id + } + + msg.Attachment = attachment + + // set checksum from notification sha256 when available + if notif.GetFileSHA256() != nil { + attachment.Checksum = fmt.Sprintf("%x", notif.GetFileSHA256()) + } + + // set message type based on extension (image vs generic document) + if strings.Contains(strings.ToLower(directPath), ".jpg") || strings.Contains(strings.ToLower(directPath), ".jpeg") || strings.Contains(strings.ToLower(directPath), ".png") || strings.Contains(strings.ToLower(directPath), ".webp") { + msg.Type = whatsapp.ImageMessageType + } else { + msg.Type = whatsapp.DocumentMessageType // generic + } + + // Trigger update so UI and external dispatchers are notified + if server.Handler != nil { + server.Handler.Trigger(msg) + } + + RespondSuccess(w, map[string]interface{}{"result": "success", "id": msg.Id}) + return + + default: + // unknown debug content + // try to unmarshal if it's a json map + var m map[string]interface{} + b, _ := json.Marshal(msg.Debug.Info) + json.Unmarshal(b, &m) + if _, ok := m["historySyncNotification"]; ok { + // can't download without a connection -> return informative error + response.ParseError(fmt.Errorf("protocol message present but cannot be processed on server side")) + RespondInterfaceCode(w, response, http.StatusBadRequest) + return + } + + response.ParseError(fmt.Errorf("unsupported debug.info type for history download")) + RespondInterfaceCode(w, response, http.StatusBadRequest) + return + } +} diff --git a/src/api/api_handlers+LoginController.go b/src/api/api_handlers+LoginController.go new file mode 100644 index 00000000..1888b69f --- /dev/null +++ b/src/api/api_handlers+LoginController.go @@ -0,0 +1,47 @@ +package api + +import ( + "net/http" + + environment "github.com/nocodeleaks/quepasa/environment" + models "github.com/nocodeleaks/quepasa/models" + log "github.com/sirupsen/logrus" +) + +// LoginConfigController returns login page customizations from environment +func LoginConfigController(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + log.Infof("LoginConfigController called from %s", r.RemoteAddr) + response := map[string]interface{}{ + "appTitle": environment.Settings.General.AppTitle, + "loginLogo": environment.Settings.General.LoginLogo, + "loginSubtitle": environment.Settings.General.LoginSubtitle, + "loginWarning": environment.Settings.General.LoginWarning, + "loginFooter": environment.Settings.General.LoginFooter, + "loginLayout": environment.Settings.General.LoginLayout, + "customCss": environment.Settings.General.LoginCustomCSS, + "fontAwesome": environment.Settings.General.LoginFontAwesome, + "googleFonts": environment.Settings.General.LoginGoogleFonts, + "accountSetup": environment.Settings.General.AccountSetup, + "version": models.QpVersion, + "sqliteMigrationAvailable": func() bool { + params := environment.Settings.Database.GetDBParameters() + if params.Driver == "sqlite3" { + return false + } + _, ok := models.CheckLocalSqliteExists() + return ok + }(), + "branding": map[string]interface{}{ + "title": environment.Settings.Branding.Title, + "logo": environment.Settings.Branding.Logo, + "favicon": environment.Settings.Branding.Favicon, + "primaryColor": environment.Settings.Branding.PrimaryColor, + "secondaryColor": environment.Settings.Branding.SecondaryColor, + "accentColor": environment.Settings.Branding.AccentColor, + "companyName": environment.Settings.Branding.CompanyName, + "companyUrl": environment.Settings.Branding.CompanyUrl, + }, + } + RespondSuccess(w, response) +} diff --git a/src/api/api_handlers+SPAController.go b/src/api/api_handlers+SPAController.go new file mode 100644 index 00000000..07b73df9 --- /dev/null +++ b/src/api/api_handlers+SPAController.go @@ -0,0 +1,2259 @@ +package api + +import ( + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "net/http" + "os" + "strconv" + "strings" + "time" + + "github.com/go-chi/chi/v5" + "github.com/google/uuid" + websocket "github.com/gorilla/websocket" + log "github.com/sirupsen/logrus" + qrcode "github.com/skip2/go-qrcode" + + environment "github.com/nocodeleaks/quepasa/environment" + models "github.com/nocodeleaks/quepasa/models" + whatsapp "github.com/nocodeleaks/quepasa/whatsapp" + whatsmeow "github.com/nocodeleaks/quepasa/whatsmeow" +) + +// parseWhatsappBoolean converts JSON value to WhatsappBoolean +// Accepts: -1, 0, 1 (numbers) or "true", "false", null +func parseWhatsappBoolean(v interface{}) (whatsapp.WhatsappBoolean, error) { + switch val := v.(type) { + case float64: + return whatsapp.WhatsappBoolean(int(val)), nil + case int: + return whatsapp.WhatsappBoolean(val), nil + case bool: + if val { + return whatsapp.TrueBooleanType, nil + } + return whatsapp.FalseBooleanType, nil + case nil: + return whatsapp.UnSetBooleanType, nil + case string: + switch strings.ToLower(strings.TrimSpace(val)) { + case "1", "true", "yes": + return whatsapp.TrueBooleanType, nil + case "-1", "false", "no": + return whatsapp.FalseBooleanType, nil + case "0", "": + return whatsapp.UnSetBooleanType, nil + } + } + return whatsapp.UnSetBooleanType, fmt.Errorf("invalid WhatsappBoolean value: %v", v) +} + +// SPASessionController returns basic session info for SPA +// GET /api/session +func SPASessionController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + if err == models.ErrFormUnauthenticated { + RespondUnauthorized(w, err) + return + } + RespondInterface(w, err) + return + } + + resp := map[string]interface{}{ + "user": map[string]interface{}{ + "username": user.Username, + "email": user.Username, + "level": "", + }, + "version": models.QpVersion, + "serversViewMode": environment.Settings.Form.ServersViewMode, + "branding": environment.Settings.Branding, + } + + RespondInterface(w, resp) +} + +// SPAServersController returns the list of servers for the authenticated user +// GET /api/servers +func SPAServersController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + if err == models.ErrFormUnauthenticated { + RespondUnauthorized(w, err) + return + } + RespondInterface(w, err) + return + } + + // Fetch servers from database (includes disconnected ones) + isAdmin := false + allServers := models.WhatsappService.DB.Servers.FindAll() + dbServers := make([]*models.QpServer, 0) + for _, server := range allServers { + if server != nil && server.User == user.Username { + dbServers = append(dbServers, server) + } + } + + var dbErr error + if dbErr != nil { + log.Errorf("Error fetching servers from database: %v", dbErr) + RespondServerError(nil, w, dbErr) + return + } + + items := make([]map[string]interface{}, 0, len(dbServers)) + + // Helper function to convert whatsapp.WhatsappBoolean to bool + toBool := func(wb whatsapp.WhatsappBoolean) bool { + return wb == whatsapp.TrueBooleanType + } + + for _, dbServer := range dbServers { + // Try to get live server from memory for real-time state + liveServer, _ := models.WhatsappService.FindByToken(dbServer.Token) + + var state whatsapp.WhatsappConnectionState + var timestamps models.QpTimestamps + var dispatchCount, webhookCount, rabbitmqCount int + + if liveServer != nil { + // Server is in memory - use live data + state = liveServer.GetState() + timestamps = liveServer.Timestamps + + dispatchings := liveServer.GetDispatchingByFilter("") + dispatchCount = len(dispatchings) + + webhooks := liveServer.GetWebhooks() + webhookCount = len(webhooks) + + rabbitConfigs := liveServer.GetRabbitMQConfigsByQueue("") + rabbitmqCount = len(rabbitConfigs) + } else { + // Server is not in memory - use database data with offline state + state = whatsapp.Disconnected + } + + uptimeSeconds := int64(0) + if !timestamps.Start.IsZero() { + uptimeSeconds = int64(time.Since(timestamps.Start).Seconds()) + } + + // Get connection status string + connectionStatus := "Unverified" + if state == whatsapp.Ready { + connectionStatus = "Ready" + } else if state == whatsapp.Connecting || state == whatsapp.Starting { + connectionStatus = "Connecting" + } else if state == whatsapp.Disconnected { + connectionStatus = "Disconnected" + } else if state == whatsapp.UnVerified { + connectionStatus = "Unverified" + } + + // Include owner info for admin users + serverItem := map[string]interface{}{ + "token": dbServer.Token, + "wid": dbServer.Wid, + "state": state.String(), + "state_code": state.EnumIndex(), + "reconnect": false, // Not available from DB + "start_time": timestamps.Start, + "last_update": timestamps.Update, + "uptime_seconds": uptimeSeconds, + "verified": dbServer.Verified, + "devel": dbServer.Devel, + "has_webhooks": webhookCount > 0, + "has_websockets": false, + "webhook_count": webhookCount, + "rabbitmq_count": rabbitmqCount, + "dispatch_count": dispatchCount, + "has_dispatching": dispatchCount > 0, + "connection": connectionStatus, + "groups": toBool(dbServer.Groups), + "broadcasts": toBool(dbServer.Broadcasts), + "read_receipts": toBool(dbServer.ReadReceipts), + "calls": toBool(dbServer.Calls), + } + + // Add owner info for admin users viewing other users' servers + if isAdmin && dbServer.User != user.Username { + serverItem["owner"] = dbServer.User + } + + items = append(items, serverItem) + } + + resp := map[string]interface{}{ + "result": "success", + "version": models.QpVersion, + "servers": items, + "serversViewMode": environment.Settings.Form.ServersViewMode, + "isAdmin": isAdmin, + } + + RespondInterface(w, resp) +} + +// SPAServersSearchController searches servers for the authenticated user +// POST /api/servers/search +func SPAServersSearchController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + if err == models.ErrFormUnauthenticated { + RespondUnauthorized(w, err) + return + } + RespondInterface(w, err) + return + } + + // Parse request body + var req struct { + Query string `json:"query"` + Token string `json:"token"` + Phone string `json:"phone"` + State string `json:"state"` + Page int `json:"page"` + Limit int `json:"limit"` + } + if r.Body != nil { + if err := json.NewDecoder(r.Body).Decode(&req); err != nil && err.Error() != "EOF" { + RespondErrorCode(w, err, http.StatusBadRequest) + return + } + } + + if req.Page <= 0 { + req.Page = 1 + } + if req.Limit <= 0 || req.Limit > 100 { + req.Limit = 25 + } + + servers := models.GetServersForUser(user) + items := make([]map[string]interface{}, 0, len(servers)) + + // Simple filter function + q := strings.TrimSpace(strings.ToLower(req.Query)) + for _, server := range servers { + // Ownership guard (already by GetServersForUser) + // Build searchable fields + token := strings.ToLower(server.Token) + wid := strings.ToLower(server.Wid) + state := strings.ToLower(server.GetState().String()) + + // Match logic + match := true + if len(req.Token) > 0 { + // exact match by token + match = match && strings.EqualFold(server.Token, req.Token) + } + if len(req.Phone) > 0 { + phone := strings.ToLower(req.Phone) + match = match && strings.Contains(wid, phone) + } + if len(req.State) > 0 { + match = match && strings.Contains(state, strings.ToLower(req.State)) + } + if len(q) > 0 { + if !(strings.Contains(token, q) || strings.Contains(wid, q) || strings.Contains(state, q)) { + match = false + } + } + + if !match { + continue + } + + stateVal := server.GetState() + timestamps := server.Timestamps + uptimeSeconds := int64(0) + if !timestamps.Start.IsZero() { + uptimeSeconds = int64(time.Since(timestamps.Start).Seconds()) + } + + dispatchings := server.GetDispatchingByFilter("") + dispatchCount := len(dispatchings) + webhooks := server.GetWebhooks() + rabbitConfigs := server.GetRabbitMQConfigsByQueue("") + rabbitmqCount := len(rabbitConfigs) + + connectionStatus := "Unverified" + if stateVal == whatsapp.Ready { + connectionStatus = "Ready" + } else if stateVal == whatsapp.Connecting || stateVal == whatsapp.Starting { + connectionStatus = "Connecting" + } else if stateVal == whatsapp.Disconnected { + connectionStatus = "Disconnected" + } else if stateVal == whatsapp.UnVerified { + connectionStatus = "Unverified" + } + + items = append(items, map[string]interface{}{ + "token": server.Token, + "wid": server.Wid, + "state": stateVal.String(), + "uptime_seconds": uptimeSeconds, + "verified": server.Verified, + "devel": server.Devel, + "webhook_count": len(webhooks), + "rabbitmq_count": rabbitmqCount, + "dispatch_count": dispatchCount, + "has_dispatching": dispatchCount > 0, + "connection": connectionStatus, + }) + } + + // Pagination + total := len(items) + start := (req.Page - 1) * req.Limit + end := start + req.Limit + if start < 0 { + start = 0 + } + if start > total { + start = total + } + if end > total { + end = total + } + paged := items[start:end] + + resp := map[string]interface{}{ + "result": "success", + "total": total, + "page": req.Page, + "limit": req.Limit, + "servers": paged, + } + + RespondInterface(w, resp) +} + +// SPAAccountController returns account info for SPA +// GET /api/account +func SPAAccountController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + if err == models.ErrFormUnauthenticated { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + RespondInterface(w, err) + return + } + + data := map[string]interface{}{ + "user": user, + "servers": models.GetServersForUser(user), + "version": models.QpVersion, + "hasMasterKey": len(environment.Settings.API.MasterKey) > 0, + } + + RespondSuccess(w, data) +} + +// SPAMasterKeyController returns the master key for authenticated users +// GET /api/account/masterkey +func SPAMasterKeyController(w http.ResponseWriter, r *http.Request) { + _, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + master := environment.Settings.API.MasterKey + if len(master) == 0 { + RespondErrorCode(w, errors.New("master key not configured"), http.StatusNotFound) + return + } + + RespondSuccess(w, map[string]interface{}{"masterKey": master}) +} + +// SPAWebHooksController returns webhooks for a server +// GET /api/webhooks?token=TOKEN +func SPAWebHooksController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := r.URL.Query().Get("token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + response := map[string]interface{}{ + "server": server, + "webhooks": server.GetWebhooks(), + } + RespondSuccess(w, response) +} + +// SPAWebHooksCreateController creates a webhook +// POST /api/webhooks +func SPAWebHooksCreateController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + var webhook struct { + Token string `json:"token"` + Url string `json:"url"` + TrackId string `json:"trackId"` + ForwardInternal bool `json:"forwardInternal"` + Broadcasts bool `json:"broadcasts"` + Groups bool `json:"groups"` + ReadReceipts bool `json:"readReceipts"` + Calls bool `json:"calls"` + Extra interface{} `json:"extra"` + } + if err := json.NewDecoder(r.Body).Decode(&webhook); err != nil { + RespondErrorCode(w, err, http.StatusBadRequest) + return + } + + token := webhook.Token + if token == "" { + token = r.URL.Query().Get("token") + } + if token == "" { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + boolToWB := func(v bool) whatsapp.WhatsappBoolean { + if v { + return whatsapp.TrueBooleanType + } + return whatsapp.FalseBooleanType + } + + d := &models.QpDispatching{ + ConnectionString: webhook.Url, + Type: models.DispatchingTypeWebhook, + ForwardInternal: webhook.ForwardInternal, + TrackId: webhook.TrackId, + Extra: webhook.Extra, + } + d.WhatsappOptions = whatsapp.WhatsappOptions{ + ReadReceipts: boolToWB(webhook.ReadReceipts), + Groups: boolToWB(webhook.Groups), + Broadcasts: boolToWB(webhook.Broadcasts), + Calls: boolToWB(webhook.Calls), + } + affected, derr := server.DispatchingAddOrUpdate(d) + if derr != nil { + RespondInterface(w, derr) + return + } + + RespondSuccess(w, map[string]interface{}{"affected": affected}) +} + +// SPAWebHooksDeleteController deletes a webhook +// DELETE /api/webhooks +func SPAWebHooksDeleteController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := r.URL.Query().Get("token") + if token == "" { + token = r.FormValue("token") + } + if token == "" { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + url := r.FormValue("url") + if url == "" { + var body struct{ Url string `json:"url"` } + _ = json.NewDecoder(r.Body).Decode(&body) + url = body.Url + } + if url == "" { + RespondErrorCode(w, errors.New("missing url parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + affected, derr := server.DispatchingRemove(url) + if derr != nil { + RespondInterface(w, derr) + return + } + + RespondSuccess(w, map[string]interface{}{"affected": affected}) +} + +// SPAWebHooksUpdateController updates webhook fields (url, context, trackid, extra, options) +// PUT /api/webhooks +func SPAWebHooksUpdateController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + var webhook struct { + Token string `json:"token"` + OriginalUrl string `json:"originalUrl"` // URL original para identificar o webhook + Url string `json:"url"` // Nova URL (pode ser igual à original) + TrackId *string `json:"trackId"` // Ponteiro para permitir null/undefined + ForwardInternal *bool `json:"forwardInternal"` // Ponteiro para permitir null/undefined + Broadcasts *int `json:"broadcasts"` // -1, 0, 1 + Groups *int `json:"groups"` // -1, 0, 1 + ReadReceipts *int `json:"readReceipts"` // -1, 0, 1 + Calls *int `json:"calls"` // -1, 0, 1 + Extra interface{} `json:"extra"` + } + if err := json.NewDecoder(r.Body).Decode(&webhook); err != nil { + RespondErrorCode(w, err, http.StatusBadRequest) + return + } + + token := webhook.Token + if token == "" { + token = r.URL.Query().Get("token") + } + if token == "" { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + if webhook.OriginalUrl == "" { + RespondErrorCode(w, errors.New("missing originalUrl parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Se a URL mudou, precisamos remover a antiga e criar uma nova + if webhook.Url != "" && webhook.Url != webhook.OriginalUrl { + // Remove a antiga + _, derr := server.DispatchingRemove(webhook.OriginalUrl) + if derr != nil { + RespondInterface(w, derr) + return + } + } + + // Prepara o dispatching atualizado + newUrl := webhook.Url + if newUrl == "" { + newUrl = webhook.OriginalUrl + } + + d := &models.QpDispatching{ + ConnectionString: newUrl, + Type: models.DispatchingTypeWebhook, + Extra: webhook.Extra, + } + + // Set optional fields + if webhook.TrackId != nil { + d.TrackId = *webhook.TrackId + } + if webhook.ForwardInternal != nil { + d.ForwardInternal = *webhook.ForwardInternal + } + + // Handle tri-state boolean options + if webhook.Broadcasts != nil { + d.Broadcasts = whatsapp.WhatsappBoolean(*webhook.Broadcasts) + } + if webhook.Groups != nil { + d.Groups = whatsapp.WhatsappBoolean(*webhook.Groups) + } + if webhook.ReadReceipts != nil { + d.ReadReceipts = whatsapp.WhatsappBoolean(*webhook.ReadReceipts) + } + if webhook.Calls != nil { + d.Calls = whatsapp.WhatsappBoolean(*webhook.Calls) + } + + affected, derr := server.DispatchingAddOrUpdate(d) + if derr != nil { + RespondInterface(w, derr) + return + } + + RespondSuccess(w, map[string]interface{}{"affected": affected}) +} + +// SPARabbitMQController returns RabbitMQ configs for a server +// GET /api/rabbitmq?token=TOKEN +func SPARabbitMQController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := r.URL.Query().Get("token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + response := map[string]interface{}{ + "server": server, + "rabbitmq": server.GetRabbitMQConfigsByQueue(""), + } + RespondSuccess(w, response) +} + +// SPARabbitMQCreateController creates a RabbitMQ config +// POST /api/rabbitmq +func SPARabbitMQCreateController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + var cfg struct { + Token string `json:"token"` + ConnectionString string `json:"connectionString"` + TrackId string `json:"trackId"` + ReadReceipts bool `json:"readReceipts"` + Groups bool `json:"groups"` + Broadcasts bool `json:"broadcasts"` + Extra interface{} `json:"extra"` + } + if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil { + RespondErrorCode(w, err, http.StatusBadRequest) + return + } + + token := cfg.Token + if token == "" { + token = r.URL.Query().Get("token") + } + if token == "" { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + boolToWB := func(v bool) whatsapp.WhatsappBoolean { + if v { + return whatsapp.TrueBooleanType + } + return whatsapp.FalseBooleanType + } + + d := &models.QpDispatching{ + ConnectionString: cfg.ConnectionString, + Type: models.DispatchingTypeRabbitMQ, + TrackId: cfg.TrackId, + Extra: cfg.Extra, + } + d.WhatsappOptions = whatsapp.WhatsappOptions{ + ReadReceipts: boolToWB(cfg.ReadReceipts), + Groups: boolToWB(cfg.Groups), + Broadcasts: boolToWB(cfg.Broadcasts), + } + affected, derr := server.DispatchingAddOrUpdate(d) + if derr != nil { + RespondInterface(w, derr) + return + } + + RespondSuccess(w, map[string]interface{}{"affected": affected}) +} + +// SPARabbitMQDeleteController deletes a RabbitMQ config +// DELETE /api/rabbitmq +func SPARabbitMQDeleteController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := r.URL.Query().Get("token") + if token == "" { + token = r.FormValue("token") + } + if token == "" { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + cs := r.FormValue("connectionString") + if cs == "" { + var body struct{ ConnectionString string `json:"connectionString"` } + _ = json.NewDecoder(r.Body).Decode(&body) + cs = body.ConnectionString + } + if cs == "" { + RespondErrorCode(w, errors.New("missing connectionString parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + affected, derr := server.DispatchingRemove(cs) + if derr != nil { + RespondInterface(w, derr) + return + } + + RespondSuccess(w, map[string]interface{}{"affected": affected}) +} + +// SPAServerInfoController returns server info +// GET /api/server/{token}/info +func SPAServerInfoController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondInterface(w, gerr) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Get current state + state := server.GetState() + + RespondSuccess(w, map[string]interface{}{ + "server": server, + "state": state.String(), + "stateCode": state.EnumIndex(), + "connected": state == whatsapp.Ready, + "wid": server.Wid, + }) +} + +// SPAServerQRCodeController returns QR code for server connection +// GET /api/server/{token}/qrcode +func SPAServerQRCodeController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondInterface(w, gerr) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Check if already connected + if server.GetStatus() == whatsapp.Ready { + RespondSuccess(w, map[string]interface{}{ + "result": "connected", + "connected": true, + "wid": server.Wid, + }) + return + } + + // Get pairing info + pairing := &models.QpWhatsappPairing{ + Username: user.Username, + Token: token, + } + + // Apply history sync from environment default when available + if d := models.ENV.HistorySync(); d != nil { + pairing.HistorySyncDays = *d + } + + con, cerr := pairing.GetConnection() + if cerr != nil { + RespondInterface(w, cerr) + return + } + + // Get QR code string + qrCodeStr := con.GetWhatsAppQRCode() + if qrCodeStr == "" { + RespondErrorCode(w, errors.New("empty QR code - server may already be connected"), http.StatusBadRequest) + return + } + + // Generate QR code image using skip2/go-qrcode + png, qerr := qrcode.Encode(qrCodeStr, qrcode.Medium, 256) + if qerr != nil { + RespondInterface(w, qerr) + return + } + + // Return as base64 image + RespondSuccess(w, map[string]interface{}{ + "result": "success", + "qrcode": "data:image/png;base64," + base64.StdEncoding.EncodeToString(png), + "rawcode": qrCodeStr, + }) +} + +// SPAServerPairCodeController returns pair code for server connection +// GET /api/server/{token}/paircode +func SPAServerPairCodeController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondInterface(w, gerr) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Check if already connected + if server.GetStatus() == whatsapp.Ready { + RespondSuccess(w, map[string]interface{}{ + "result": "connected", + "connected": true, + "wid": server.Wid, + }) + return + } + + // Get phone from query + phone := r.URL.Query().Get("phone") + if phone == "" { + RespondErrorCode(w, errors.New("missing phone parameter"), http.StatusBadRequest) + return + } + + // Get pairing info + pairing := &models.QpWhatsappPairing{ + Username: user.Username, + Token: token, + } + + // Apply history sync from environment default when available + if d := models.ENV.HistorySync(); d != nil { + pairing.HistorySyncDays = *d + } + + con, cerr := pairing.GetConnection() + if cerr != nil { + RespondInterface(w, cerr) + return + } + + // Get pair code using PairPhone method + pairCode, pcerr := con.PairPhone(phone) + if pcerr != nil { + if strings.Contains(pcerr.Error(), "missing ") { + // Return a friendly error to SPA with suggestion to retry + RespondErrorCode(w, fmt.Errorf("pairing failed due to incomplete notification from WhatsApp: %s", pcerr.Error()), http.StatusServiceUnavailable) + return + } + RespondInterface(w, pcerr) + return + } + + // Format pair code as XX-XX-XX-XX for readability + formattedCode := formatPairCode(pairCode) + + RespondSuccess(w, map[string]interface{}{ + "result": "success", + "paircode": pairCode, + "formatted": formattedCode, + }) +} + +// formatPairCode formats pair code as XX-XX-XX-XX +func formatPairCode(code string) string { + if len(code) != 8 { + return code + } + return code[0:2] + "-" + code[2:4] + "-" + code[4:6] + "-" + code[6:8] +} + +// SPAServerCreateController creates a new server +// POST /api/server/create +func SPAServerCreateController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + // Generate new token + token := uuid.New().String() + + // Create server info with default options from environment + info := &models.QpServer{ + Token: token, + User: user.Username, + } + + // Apply default WhatsApp options from environment + // Convert WhatsappBooleanExtended to WhatsappBoolean for storage + info.Groups = models.ENV.Groups().ToWhatsappBoolean() + info.Broadcasts = models.ENV.Broadcasts().ToWhatsappBoolean() + info.ReadReceipts = models.ENV.ReadReceipts().ToWhatsappBoolean() + info.Calls = models.ENV.Calls().ToWhatsappBoolean() + // ReadUpdate returns bool, convert to WhatsappBoolean + if models.ENV.ReadUpdate() { + info.ReadUpdate = whatsapp.TrueBooleanType + } else { + info.ReadUpdate = whatsapp.FalseBooleanType + } + + // Append new server + server, cerr := models.WhatsappService.AppendNewServer(info) + if cerr != nil { + RespondInterface(w, cerr) + return + } + + // Persist server to database so it survives restarts + if saveErr := server.Save("server created via SPA"); saveErr != nil { + // Remove from in-memory cache if save fails + delete(models.WhatsappService.Servers, server.Token) + RespondInterface(w, saveErr) + return + } + + RespondSuccess(w, map[string]interface{}{ + "server": server, + "token": server.Token, + }) +} + +// SPAServerDeleteController deletes a server +// POST /api/delete +func SPAServerDeleteController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + // Get token from body or form + r.ParseForm() + token := r.Form.Get("token") + if token == "" { + var body struct{ Token string `json:"token"` } + _ = json.NewDecoder(r.Body).Decode(&body) + token = body.Token + } + if token == "" { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Delete the server + derr := models.WhatsappService.Delete(server, "server deleted via SPA") + if derr != nil { + RespondInterface(w, derr) + return + } + + RespondSuccess(w, map[string]interface{}{"result": "success"}) +} + +// SPAServerDebugController toggles debug mode for a server +// POST /api/debug +func SPAServerDebugController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + // Get token from body or form + r.ParseForm() + token := r.Form.Get("token") + if token == "" { + var body struct{ Token string `json:"token"` } + _ = json.NewDecoder(r.Body).Decode(&body) + token = body.Token + } + if token == "" { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Toggle debug mode + _, terr := server.ToggleDevel() + if terr != nil { + RespondInterface(w, terr) + return + } + + RespondSuccess(w, map[string]interface{}{"devel": server.Devel}) +} + +// SPAServerUpdateController updates server options (history sync etc) +// POST /api/server/{token}/update +func SPAServerUpdateController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondInterface(w, gerr) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Parse body (accept form or JSON) + r.ParseForm() + var jb map[string]interface{} + _ = json.NewDecoder(r.Body).Decode(&jb) + + updated := false + + // Handle WhatsApp options (groups, broadcasts, readreceipts, calls, readupdate) + // Values: -1 = false, 0 = unset, 1 = true + whatsappOptions := server.GetOptions() + + if v, ok := jb["groups"]; ok { + if val, err := parseWhatsappBoolean(v); err == nil { + whatsappOptions.Groups = val + updated = true + } + } + if v, ok := jb["broadcasts"]; ok { + if val, err := parseWhatsappBoolean(v); err == nil { + whatsappOptions.Broadcasts = val + updated = true + } + } + if v, ok := jb["readreceipts"]; ok { + if val, err := parseWhatsappBoolean(v); err == nil { + whatsappOptions.ReadReceipts = val + updated = true + } + } + if v, ok := jb["calls"]; ok { + if val, err := parseWhatsappBoolean(v); err == nil { + whatsappOptions.Calls = val + updated = true + } + } + if v, ok := jb["readupdate"]; ok { + if val, err := parseWhatsappBoolean(v); err == nil { + whatsappOptions.ReadUpdate = val + updated = true + } + } + + if !updated { + RespondSuccess(w, map[string]interface{}{"server": server, "message": "no changes"}) + return + } + + errSave := server.Save("update server options") + if errSave != nil { + RespondInterface(w, errSave) + return + } + + RespondSuccess(w, map[string]interface{}{"server": server}) +} + +// SPAToggleController handles toggle operations for server/webhook/rabbitmq +// POST /api/toggle +func SPAToggleController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + // Read body once and reuse + var jb map[string]interface{} + _ = json.NewDecoder(r.Body).Decode(&jb) + + // Get token + token := r.URL.Query().Get("token") + if token == "" { + r.ParseForm() + token = r.Form.Get("token") + } + if token == "" { + if v, ok := jb["token"].(string); ok { + token = v + } + } + if token == "" { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Get key + key := r.URL.Query().Get("key") + if key == "" { + r.ParseForm() + key = r.Form.Get("key") + } + if key == "" { + if v, ok := jb["key"].(string); ok { + key = v + } + } + if key == "" { + RespondErrorCode(w, errors.New("missing key parameter"), http.StatusBadRequest) + return + } + + var err2 error + // If user tries to toggle server-level features via SPA toggle, instruct them to use /command endpoint instead + if strings.HasPrefix(key, "server-") { + // mapping to command actions + mapping := map[string]string{ + "server-groups": "groups", + "server-broadcasts": "broadcasts", + "server-readreceipts": "readreceipts", + "server-calls": "calls", + "server-readupdate": "readupdate", + } + if action, ok := mapping[key]; ok { + resp := &models.QpResponse{} + resp.ParseError(fmt.Errorf("use /command with action='%s' instead of /toggle key '%s'", action, key)) + RespondInterfaceCode(w, resp, http.StatusBadRequest) + return + } + } + if strings.HasPrefix(key, "server") { + // Server-level toggles are deprecated via SPA toggle endpoint. Use /api/command with action=start|stop or other actions. + RespondErrorCode(w, fmt.Errorf("server-level toggles are removed from /api/toggle; use /api/command with action=start|stop|restart|groups|..."), http.StatusBadRequest) + return + } else if strings.HasPrefix(key, "webhook") { + url := r.URL.Query().Get("url") + if url == "" { + r.ParseForm() + url = r.Form.Get("url") + } + if url == "" { + if v, ok := jb["url"].(string); ok { + url = v + } + } + if url == "" { + RespondErrorCode(w, errors.New("missing url parameter"), http.StatusBadRequest) + return + } + dispatching := server.GetDispatching(url) + var webhook *models.QpWhatsappServerDispatching = nil + if dispatching != nil && dispatching.IsWebhook() { + webhook = models.NewQpWhatsappServerDispatchingFromDispatching(dispatching, server) + } + if webhook == nil { + RespondErrorCode(w, errors.New("webhook not found for url: "+url), http.StatusNotFound) + return + } + switch key { + case "webhook-forwardinternal": + _, err2 = webhook.ToggleForwardInternal() + case "webhook-broadcasts": + err2 = models.ToggleBroadcasts(webhook) + case "webhook-groups": + err2 = models.ToggleGroups(webhook) + case "webhook-readreceipts": + err2 = models.ToggleReadReceipts(webhook) + case "webhook-calls": + err2 = models.ToggleCalls(webhook) + default: + err2 = errors.New("invalid webhook key: " + key) + } + } else if strings.HasPrefix(key, "rabbitmq") { + cs := r.URL.Query().Get("connectionString") + if cs == "" { + r.ParseForm() + cs = r.Form.Get("connectionString") + } + if cs == "" { + if v, ok := jb["connectionString"].(string); ok { + cs = v + } + if cs == "" { + if v2, ok2 := jb["connection_string"].(string); ok2 { + cs = v2 + } + } + } + if cs == "" { + RespondErrorCode(w, errors.New("missing connectionString parameter"), http.StatusBadRequest) + return + } + dispatching := server.GetDispatching(cs) + var rabbitmq *models.QpWhatsappServerDispatching = nil + if dispatching != nil && dispatching.IsRabbitMQ() { + rabbitmq = models.NewQpWhatsappServerDispatchingFromDispatching(dispatching, server) + } + if rabbitmq == nil { + RespondErrorCode(w, errors.New("rabbitmq configuration not found for connection: "+cs), http.StatusNotFound) + return + } + switch key { + case "rabbitmq-forwardinternal": + _, err2 = rabbitmq.ToggleForwardInternal() + case "rabbitmq-broadcasts": + err2 = models.ToggleBroadcasts(rabbitmq) + case "rabbitmq-groups": + err2 = models.ToggleGroups(rabbitmq) + case "rabbitmq-readreceipts": + err2 = models.ToggleReadReceipts(rabbitmq) + case "rabbitmq-calls": + err2 = models.ToggleCalls(rabbitmq) + default: + err2 = errors.New("invalid rabbitmq key: " + key) + } + } else { + err2 = errors.New("invalid key or prefix: " + key) + } + + if err2 != nil { + RespondErrorCode(w, err2, http.StatusInternalServerError) + return + } + + RespondSuccess(w, map[string]interface{}{"result": "success"}) +} + +// SPAUserController creates a new user +// POST /api/user +func SPAUserController(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + email := r.Form.Get("email") + password := r.Form.Get("password") + if email == "" || password == "" { + var j struct { + Email string `json:"email"` + Password string `json:"password"` + } + if err := json.NewDecoder(r.Body).Decode(&j); err == nil { + email = j.Email + password = j.Password + } + } + + if email == "" || password == "" { + RespondErrorCode(w, errors.New("email and password required"), http.StatusBadRequest) + return + } + + exists, err := models.WhatsappService.DB.Users.Exists(email) + if err != nil { + RespondInterface(w, err) + return + } + + if exists { + RespondErrorCode(w, errors.New("user already exists"), http.StatusConflict) + return + } + + _, cerr := models.WhatsappService.DB.Users.Create(email, password) + if cerr != nil { + RespondInterface(w, cerr) + return + } + + RespondSuccess(w, map[string]interface{}{"result": "success"}) +} + +// SPAServerSendController sends a message +// POST /api/server/{token}/send +func SPAServerSendController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondErrorCode(w, gerr, http.StatusNotFound) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + type payload struct { + Recipient string `json:"recipient"` + Message string `json:"message"` + Id string `json:"id,omitempty"` + } + + var p payload + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + RespondErrorCode(w, err, http.StatusBadRequest) + return + } + + if p.Recipient == "" || p.Message == "" { + RespondErrorCode(w, errors.New("recipient and message are required"), http.StatusBadRequest) + return + } + + msg, merr := models.ToWhatsappMessage(p.Recipient, p.Message, nil) + if merr != nil { + RespondServerError(server, w, merr) + return + } + + msg.Id = p.Id + _, sendErr := server.SendMessage(msg) + if sendErr != nil { + RespondServerError(server, w, sendErr) + return + } + + RespondSuccess(w, map[string]interface{}{"result": "success", "id": msg.GetId()}) +} + +// SPAVerifyWebSocketController handles websocket connections for QR code verification +// GET /api/verify/ws +func SPAVerifyWebSocketController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + if err == models.ErrFormUnauthenticated { + RespondUnauthorized(w, err) + return + } + RespondInterface(w, err) + return + } + + var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + } + + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Errorf("(websocket): service error: %s", err.Error()) + return + } + + HSDString := r.URL.Query().Get("historysyncdays") + historysyncdays, _ := strconv.ParseUint(HSDString, 10, 32) + + pairing := &models.QpWhatsappPairing{ + Username: user.Username, + HistorySyncDays: uint32(historysyncdays), + } + + WebSocketStart(*pairing, conn) +} + +// SPAUsersListController returns all users created by the current user +// GET /api/users +func SPAUsersListController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + // Build response without exposing password hashes + type userResponse struct { + Username string `json:"username"` + CreatedBy string `json:"created_by,omitempty"` + Timestamp string `json:"timestamp,omitempty"` + IsSelf bool `json:"is_self,omitempty"` + } + + response := []userResponse{{ + Username: user.Username, + CreatedBy: "", + Timestamp: user.Timestamp.Format("2006-01-02T15:04:05Z07:00"), + IsSelf: true, + }} + + RespondSuccess(w, map[string]interface{}{"users": response}) +} + +// SPAUserDeleteController deletes a user +// DELETE /api/user +func SPAUserDeleteController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + type request struct { + Username string `json:"username"` + } + + var req request + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + RespondErrorCode(w, err, http.StatusBadRequest) + return + } + + if req.Username == "" { + RespondErrorCode(w, errors.New("username is required"), http.StatusBadRequest) + return + } + + // Prevent deleting self + if req.Username == user.Username { + RespondErrorCode(w, errors.New("cannot delete yourself"), http.StatusBadRequest) + return + } + + RespondErrorCode(w, errors.New("user deletion is not supported in this build"), http.StatusNotImplemented) +} + +// SPAEnvironmentController returns all environment variables grouped by category +// GET /api/environment +func SPAEnvironmentController(w http.ResponseWriter, r *http.Request) { + type envVar struct { + Name string `json:"name"` + Value string `json:"value"` + Description string `json:"description"` + } + + type category struct { + Name string `json:"name"` + Variables []envVar `json:"variables"` + } + + categories := []category{ + { + Name: "Database", + Variables: []envVar{ + {Name: "DBDRIVER", Value: getEnvMasked("DBDRIVER", false), Description: "Database driver (sqlite3, mysql, postgres)"}, + {Name: "DBHOST", Value: getEnvMasked("DBHOST", false), Description: "Database host"}, + {Name: "DBDATABASE", Value: getEnvMasked("DBDATABASE", false), Description: "Database name"}, + {Name: "DBPORT", Value: getEnvMasked("DBPORT", false), Description: "Database port"}, + {Name: "DBUSER", Value: getEnvMasked("DBUSER", false), Description: "Database user"}, + {Name: "DBPASSWORD", Value: getEnvMasked("DBPASSWORD", true), Description: "Database password"}, + {Name: "DBSSLMODE", Value: getEnvMasked("DBSSLMODE", false), Description: "Database SSL mode"}, + }, + }, + { + Name: "API", + Variables: []envVar{ + {Name: "MASTERKEY", Value: getEnvMasked("MASTERKEY", true), Description: "Master key for API authentication"}, + {Name: "API_PREFIX", Value: getEnvMasked("API_PREFIX", false), Description: "API routes prefix (default: api)"}, + {Name: "API_TIMEOUT", Value: getEnvMasked("API_TIMEOUT", false), Description: "API request timeout in milliseconds"}, + {Name: "SIGNING_SECRET", Value: getEnvMasked("SIGNING_SECRET", true), Description: "Token for hash signing cookies"}, + {Name: "WEBSOCKETSSL", Value: getEnvMasked("WEBSOCKETSSL", false), Description: "Use SSL for websocket QR code"}, + {Name: "WEBHOOK_TIMEOUT", Value: getEnvMasked("WEBHOOK_TIMEOUT", false), Description: "Webhook timeout in milliseconds"}, + }, + }, + { + Name: "WebServer", + Variables: []envVar{ + {Name: "WEBSERVER_HOST", Value: getEnvMasked("WEBSERVER_HOST", false), Description: "HTTP host address"}, + {Name: "WEBSERVER_PORT", Value: getEnvMasked("WEBSERVER_PORT", false), Description: "HTTP port"}, + {Name: "WEBSERVER_LOGS", Value: getEnvMasked("WEBSERVER_LOGS", false), Description: "Enable HTTP request logging"}, + {Name: "WEBAPIHOST", Value: getEnvMasked("WEBAPIHOST", false), Description: "HTTP host (legacy fallback)"}, + {Name: "WEBAPIPORT", Value: getEnvMasked("WEBAPIPORT", false), Description: "HTTP port (legacy fallback)"}, + }, + }, + { + Name: "Form", + Variables: []envVar{ + {Name: "FORM", Value: getEnvMasked("FORM", false), Description: "Enable/disable form interface"}, + {Name: "FORM_PREFIX", Value: getEnvMasked("FORM_PREFIX", false), Description: "Form endpoint path prefix (default: form)"}, + {Name: "SERVERS_VIEW_MODE", Value: getEnvMasked("SERVERS_VIEW_MODE", false), Description: "Servers view mode: card or table"}, + }, + }, + { + Name: "Swagger", + Variables: []envVar{ + {Name: "SWAGGER", Value: getEnvMasked("SWAGGER", false), Description: "Swagger documentation enabled"}, + {Name: "SWAGGER_PREFIX", Value: getEnvMasked("SWAGGER_PREFIX", false), Description: "Swagger path prefix (default: swagger)"}, + }, + }, + { + Name: "Metrics", + Variables: []envVar{ + {Name: "METRICS", Value: getEnvMasked("METRICS", false), Description: "Prometheus metrics enabled"}, + {Name: "METRICS_PREFIX", Value: getEnvMasked("METRICS_PREFIX", false), Description: "Metrics endpoint path prefix"}, + {Name: "METRICS_DASHBOARD", Value: getEnvMasked("METRICS_DASHBOARD", false), Description: "Dashboard endpoint enabled"}, + {Name: "METRICS_DASHBOARD_PREFIX", Value: getEnvMasked("METRICS_DASHBOARD_PREFIX", false), Description: "Dashboard endpoint path prefix"}, + }, + }, + { + Name: "WhatsApp", + Variables: []envVar{ + {Name: "READUPDATE", Value: getEnvMasked("READUPDATE", false), Description: "Mark chat read when sending message"}, + {Name: "READRECEIPTS", Value: getEnvMasked("READRECEIPTS", false), Description: "Dispatch read receipts events"}, + {Name: "CALLS", Value: getEnvMasked("CALLS", false), Description: "Accept/handle calls"}, + {Name: "GROUPS", Value: getEnvMasked("GROUPS", false), Description: "Handle group messages"}, + {Name: "BROADCASTS", Value: getEnvMasked("BROADCASTS", false), Description: "Handle broadcast messages"}, + {Name: "HISTORYSYNCDAYS", Value: getEnvMasked("HISTORYSYNCDAYS", false), Description: "History sync days"}, + {Name: "PRESENCE", Value: getEnvMasked("PRESENCE", false), Description: "Presence status"}, + {Name: "WAKEUP_HOUR", Value: getEnvMasked("WAKEUP_HOUR", false), Description: "Scheduled hour(s) to activate presence"}, + {Name: "WAKEUP_DURATION", Value: getEnvMasked("WAKEUP_DURATION", false), Description: "Duration in seconds for wake up"}, + }, + }, + { + Name: "Whatsmeow", + Variables: []envVar{ + {Name: "WHATSMEOW_LOGLEVEL", Value: getEnvMasked("WHATSMEOW_LOGLEVEL", false), Description: "Whatsmeow log level"}, + {Name: "WHATSMEOW_DBLOGLEVEL", Value: getEnvMasked("WHATSMEOW_DBLOGLEVEL", false), Description: "Whatsmeow DB log level"}, + {Name: "DISPATCHUNHANDLED", Value: getEnvMasked("DISPATCHUNHANDLED", false), Description: "Dispatch unhandled messages"}, + }, + }, + { + Name: "General", + Variables: []envVar{ + {Name: "MIGRATIONS", Value: getEnvMasked("MIGRATIONS", false), Description: "Enable database migrations (true/false/path)"}, + {Name: "APP_TITLE", Value: getEnvMasked("APP_TITLE", false), Description: "Application title for WhatsApp ID"}, + {Name: "REMOVEDIGIT9", Value: getEnvMasked("REMOVEDIGIT9", false), Description: "Remove 9th digit from Brazilian numbers"}, + {Name: "SYNOPSISLENGTH", Value: getEnvMasked("SYNOPSISLENGTH", false), Description: "Synopsis length for messages"}, + {Name: "CACHELENGTH", Value: getEnvMasked("CACHELENGTH", false), Description: "Cache max items"}, + {Name: "CACHEDAYS", Value: getEnvMasked("CACHEDAYS", false), Description: "Cache max days"}, + {Name: "CONVERT_WAVE_TO_OGG", Value: getEnvMasked("CONVERT_WAVE_TO_OGG", false), Description: "Convert wave to OGG"}, + {Name: "COMPATIBLE_MIME_AS_AUDIO", Value: getEnvMasked("COMPATIBLE_MIME_AS_AUDIO", false), Description: "Treat compatible MIME as audio"}, + {Name: "ACCOUNTSETUP", Value: getEnvMasked("ACCOUNTSETUP", false), Description: "Enable account creation"}, + {Name: "LOGLEVEL", Value: getEnvMasked("LOGLEVEL", false), Description: "General log level"}, + }, + }, + { + Name: "Login Customization", + Variables: []envVar{ + {Name: "LOGIN_LOGO", Value: getEnvMasked("LOGIN_LOGO", false), Description: "URL for login page logo"}, + {Name: "LOGIN_SUBTITLE", Value: getEnvMasked("LOGIN_SUBTITLE", false), Description: "Subtitle under logo"}, + {Name: "LOGIN_WARNING", Value: getEnvMasked("LOGIN_WARNING", false), Description: "Prominent warning text"}, + {Name: "LOGIN_FOOTER", Value: getEnvMasked("LOGIN_FOOTER", false), Description: "Footer text"}, + {Name: "LOGIN_LAYOUT", Value: getEnvMasked("LOGIN_LAYOUT", false), Description: "Layout type: center|split|simple"}, + {Name: "LOGIN_CUSTOM_CSS", Value: getEnvMasked("LOGIN_CUSTOM_CSS", false), Description: "URL to custom CSS"}, + }, + }, + { + Name: "Branding", + Variables: []envVar{ + {Name: "BRANDING_TITLE", Value: getEnvMasked("BRANDING_TITLE", false), Description: "Application title"}, + {Name: "BRANDING_LOGO", Value: getEnvMasked("BRANDING_LOGO", false), Description: "Logo URL"}, + {Name: "BRANDING_FAVICON", Value: getEnvMasked("BRANDING_FAVICON", false), Description: "Favicon URL"}, + {Name: "BRANDING_PRIMARY_COLOR", Value: getEnvMasked("BRANDING_PRIMARY_COLOR", false), Description: "Primary color"}, + {Name: "BRANDING_SECONDARY_COLOR", Value: getEnvMasked("BRANDING_SECONDARY_COLOR", false), Description: "Secondary color"}, + {Name: "BRANDING_ACCENT_COLOR", Value: getEnvMasked("BRANDING_ACCENT_COLOR", false), Description: "Accent color"}, + {Name: "BRANDING_COMPANY_NAME", Value: getEnvMasked("BRANDING_COMPANY_NAME", false), Description: "Company name for footer"}, + {Name: "BRANDING_COMPANY_URL", Value: getEnvMasked("BRANDING_COMPANY_URL", false), Description: "Company URL for footer"}, + }, + }, + { + Name: "MCP", + Variables: []envVar{ + {Name: "MCP_ENABLED", Value: getEnvMasked("MCP_ENABLED", false), Description: "MCP server enabled"}, + {Name: "MCP_PATH", Value: getEnvMasked("MCP_PATH", false), Description: "MCP endpoint path"}, + }, + }, + { + Name: "RabbitMQ", + Variables: []envVar{ + {Name: "RABBITMQ_QUEUE", Value: getEnvMasked("RABBITMQ_QUEUE", false), Description: "RabbitMQ queue name"}, + {Name: "RABBITMQ_CONNECTIONSTRING", Value: getEnvMasked("RABBITMQ_CONNECTIONSTRING", true), Description: "RabbitMQ connection string"}, + {Name: "RABBITMQ_CACHELENGTH", Value: getEnvMasked("RABBITMQ_CACHELENGTH", false), Description: "RabbitMQ cache length"}, + }, + }, + { + Name: "SIP Proxy", + Variables: []envVar{ + {Name: "SIPPROXY_HOST", Value: getEnvMasked("SIPPROXY_HOST", false), Description: "SIP server host (required for activation)"}, + {Name: "SIPPROXY_PORT", Value: getEnvMasked("SIPPROXY_PORT", false), Description: "SIP server port"}, + {Name: "SIPPROXY_PROTOCOL", Value: getEnvMasked("SIPPROXY_PROTOCOL", false), Description: "SIP server protocol"}, + {Name: "SIPPROXY_LOCALPORT", Value: getEnvMasked("SIPPROXY_LOCALPORT", false), Description: "Local SIP port"}, + {Name: "SIPPROXY_PUBLICIP", Value: getEnvMasked("SIPPROXY_PUBLICIP", false), Description: "Public IP for SIP"}, + {Name: "SIPPROXY_STUNSERVER", Value: getEnvMasked("SIPPROXY_STUNSERVER", false), Description: "STUN server for NAT discovery"}, + {Name: "SIPPROXY_MEDIAPORTS", Value: getEnvMasked("SIPPROXY_MEDIAPORTS", false), Description: "RTP media port range"}, + {Name: "SIPPROXY_CODECS", Value: getEnvMasked("SIPPROXY_CODECS", false), Description: "Supported audio codecs"}, + {Name: "SIPPROXY_LOGLEVEL", Value: getEnvMasked("SIPPROXY_LOGLEVEL", false), Description: "SIP proxy log level"}, + }, + }, + } + + RespondSuccess(w, map[string]interface{}{"categories": categories}) +} + +// getEnvMasked returns the environment variable value, masking sensitive data +func getEnvMasked(name string, sensitive bool) string { + value := os.Getenv(name) + if sensitive && value != "" { + return "********" + } + return value +} + +// SPAServerMessagesController returns messages for a server (SPA endpoint) +// +// @Summary Get server messages (SPA) +// @Description Retrieves messages from WhatsApp server with pagination, timestamp and exceptions filtering (authenticated SPA endpoint) +// @Tags SPA +// @Accept json +// @Produce json +// @Param token path string true "Server token" +// @Param timestamp query string false "Timestamp filter for messages (Unix timestamp)" +// @Param exceptions query string false "Filter by exceptions: 'true' for messages with errors, 'false' for messages without errors, omit for all" +// @Param page query int false "Page number (default: 1)" +// @Param limit query int false "Messages per page (default: 50, max: 500)" +// @Success 200 {object} models.QpReceiveResponse +// @Failure 400 {object} models.QpResponse +// @Failure 401 {object} models.QpResponse +// @Failure 403 {object} models.QpResponse +// @Failure 503 {object} models.QpResponse +// @Security Bearer +// @Router /api/server/{token}/messages [get] +func SPAServerMessagesController(w http.ResponseWriter, r *http.Request) { + response := &models.QpReceiveResponse{} + + // Authenticate user via JWT + user, err := GetFormUserFromRequest(r) + if err != nil { + log.Debugf("SPA messages: authentication failed - %v", err) + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + // Get server token from URL path + token := chi.URLParam(r, "token") + if len(token) == 0 { + log.Warnf("SPA messages: missing token parameter") + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + // Find server by token + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + log.Warnf("SPA messages: server not found for token %s", token) + RespondInterface(w, gerr) + return + } + + // Verify ownership + if server.User != user.Username { + log.Warnf("SPA messages: user %s attempted to access server owned by %s", user.Username, server.User) + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Get current status + status := server.GetStatus() + log.Debugf("SPA messages: server %s status=%s, user=%s", token, status.String(), user.Username) + + // Check if server is ready + if status != whatsapp.Ready { + err = fmt.Errorf("server (%s) not ready yet ! current status: %s", server.Wid, status.String()) + log.Infof("SPA messages: server not ready - %s", err.Error()) + response.ParseError(err) + RespondInterfaceCode(w, response, http.StatusServiceUnavailable) + return + } + + // Verify handler is attached + if server.Handler == nil { + err = fmt.Errorf("handlers not attached") + log.Errorf("SPA messages: server %s has no handler attached", token) + response.ParseError(err) + RespondInterface(w, response) + return + } + + // Get pagination parameters + queryValues := r.URL.Query() + page := 1 + limit := 50 // Default: 50 messages per page + + if pageStr := queryValues.Get("page"); pageStr != "" { + if parsedPage, err := strconv.Atoi(pageStr); err == nil && parsedPage > 0 { + page = parsedPage + } + } + + if limitStr := queryValues.Get("limit"); limitStr != "" { + if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 { + limit = parsedLimit + // Max limit: 500 messages per page + if limit > 500 { + limit = 500 + } + } + } + + // Get timestamp filter + timestamp, err := GetTimestamp(r) + if err != nil { + log.Warnf("SPA messages: invalid timestamp parameter - %v", err) + response.ParseError(err) + RespondInterface(w, response) + return + } + + // Get exceptions filter parameter + exceptionsFilter := queryValues.Get("exceptions") + + // Retrieve and filter messages + allMessages := GetOrderedMessagesWithExceptionsFilter(server, timestamp, exceptionsFilter) + totalMessages := len(allMessages) + + // Calculate pagination + totalPages := (totalMessages + limit - 1) / limit // Ceiling division + if page > totalPages && totalPages > 0 { + page = totalPages + } + + // Calculate start and end indices for current page + startIdx := (page - 1) * limit + endIdx := startIdx + limit + if endIdx > totalMessages { + endIdx = totalMessages + } + + // Get messages for current page + var pagedMessages []whatsapp.WhatsappMessage + if startIdx < totalMessages { + pagedMessages = allMessages[startIdx:endIdx] + } else { + pagedMessages = []whatsapp.WhatsappMessage{} + } + + response.Server = server.QpServer + response.Messages = pagedMessages + response.Total = uint64(totalMessages) + response.Page = page + response.Limit = limit + response.TotalPages = totalPages + + // Build success message with filter information + var msg string + if timestamp > 0 { + searchTime := time.Unix(timestamp, 0) + msg = fmt.Sprintf("getting with timestamp: %v => %s", timestamp, searchTime) + } else { + msg = "getting without timestamp filter" + } + + if exceptionsFilter != "" { + msg += fmt.Sprintf(", exceptions filter: %s", exceptionsFilter) + } + + msg += fmt.Sprintf(", page %d/%d (%d messages)", page, totalPages, len(pagedMessages)) + + log.Debugf("SPA messages: returning %d messages (page %d/%d) for server %s (total: %d)", + len(pagedMessages), page, totalPages, token, totalMessages) + + response.ParseSuccess(msg) + RespondSuccess(w, response) +} + +// SPAServerEditMessageController edits a message +// PUT /api/server/{token}/message/{messageid}/edit +func SPAServerEditMessageController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + messageId := chi.URLParam(r, "messageid") + if len(messageId) == 0 { + RespondErrorCode(w, errors.New("missing messageid parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondInterface(w, gerr) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + type payload struct { + Content string `json:"content"` + } + + var p payload + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + RespondErrorCode(w, err, http.StatusBadRequest) + return + } + + if p.Content == "" { + RespondErrorCode(w, errors.New("content is required"), http.StatusBadRequest) + return + } + + if err := server.Edit(messageId, p.Content); err != nil { + RespondServerError(server, w, err) + return + } + + RespondSuccess(w, map[string]interface{}{"result": "success"}) +} + +// SPAServerRevokeMessageController revokes/deletes a message +// DELETE /api/server/{token}/message/{messageid} +func SPAServerRevokeMessageController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + messageId := chi.URLParam(r, "messageid") + if len(messageId) == 0 { + RespondErrorCode(w, errors.New("missing messageid parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondInterface(w, gerr) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + if err := server.Revoke(messageId); err != nil { + RespondServerError(server, w, err) + return + } + + RespondSuccess(w, map[string]interface{}{"result": "success"}) +} + +// SPAServerArchiveChatController archives a chat +// POST /api/server/{token}/chat/archive +func SPAServerArchiveChatController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondInterface(w, gerr) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + type payload struct { + ChatId string `json:"chatid"` + Archive bool `json:"archive"` + } + + var p payload + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + RespondErrorCode(w, err, http.StatusBadRequest) + return + } + + if p.ChatId == "" { + RespondErrorCode(w, errors.New("chatid is required"), http.StatusBadRequest) + return + } + + // Format and validate the chat ID + formattedChatId, fmtErr := whatsapp.FormatEndpoint(p.ChatId) + if fmtErr != nil { + RespondErrorCode(w, fmtErr, http.StatusBadRequest) + return + } + + // Get WhatsmeowConnection + conn := server.GetConnection().(*whatsmeow.WhatsmeowConnection) + + // Archive or unarchive chat + if err := whatsmeow.ArchiveChat(conn, formattedChatId, p.Archive); err != nil { + RespondServerError(server, w, err) + return + } + + RespondSuccess(w, map[string]interface{}{"result": "success"}) +} + +// SPAServerPresenceController sends presence to a chat +// POST /api/server/{token}/chat/presence +func SPAServerPresenceController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondInterface(w, gerr) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + type payload struct { + ChatId string `json:"chatid"` + Type string `json:"type"` + Duration int `json:"duration"` + } + + var p payload + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + RespondErrorCode(w, err, http.StatusBadRequest) + return + } + + if p.ChatId == "" { + RespondErrorCode(w, errors.New("chatid is required"), http.StatusBadRequest) + return + } + + if p.Type == "" { + p.Type = "composing" + } + + // Parse presence type string to enum + var presenceType whatsapp.WhatsappChatPresenceType + presenceType.Parse(p.Type) + + if err := server.SendChatPresence(p.ChatId, presenceType); err != nil { + RespondServerError(server, w, err) + return + } + + RespondSuccess(w, map[string]interface{}{"result": "success"}) +} + +// SPAServerContactsController returns all contacts for a server +// GET /api/server/{token}/contacts +func SPAServerContactsController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if token == "" { + RespondBadRequest(w, fmt.Errorf("missing token parameter")) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondNotFound(w, fmt.Errorf("server token not found")) + return + } + + // Check ownership + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Get contacts + contacts, err := server.GetContacts() + if err != nil { + RespondServerError(server, w, err) + return + } + + response := &models.QpContactsResponse{} + response.Total = len(contacts) + response.Contacts = contacts + RespondSuccess(w, response) +} + +// SPAServerGroupsController returns all groups for a server +// GET /api/server/{token}/groups +func SPAServerGroupsController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if token == "" { + RespondBadRequest(w, fmt.Errorf("missing token parameter")) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondNotFound(w, fmt.Errorf("server token not found")) + return + } + + // Check ownership + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Get all joined groups + groups, err := server.GetGroupManager().GetJoinedGroups() + if err != nil { + RespondServerError(server, w, err) + return + } + + response := &models.QpGroupsResponse{} + response.Total = len(groups) + response.Groups = groups + RespondSuccess(w, response) +} + +// SPAServerDownloadMediaController downloads media for a message +// GET /api/server/{token}/download/{messageid} +func SPAServerDownloadMediaController(w http.ResponseWriter, r *http.Request) { + user, err := GetFormUserFromRequest(r) + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + token := chi.URLParam(r, "token") + if len(token) == 0 { + RespondErrorCode(w, errors.New("missing token parameter"), http.StatusBadRequest) + return + } + + messageId := chi.URLParam(r, "messageid") + if len(messageId) == 0 { + RespondErrorCode(w, errors.New("missing messageid parameter"), http.StatusBadRequest) + return + } + + server, gerr := models.GetServerFromToken(token) + if gerr != nil { + RespondInterface(w, gerr) + return + } + + if server.User != user.Username { + RespondErrorCode(w, errors.New("server token not owned by user"), http.StatusForbidden) + return + } + + // Use existing download logic from server - Download returns attachment with metadata + att, err := server.Download(messageId, false) + if err != nil { + RespondServerError(server, w, err) + return + } + + // Set appropriate content type and disposition + w.Header().Set("Content-Type", att.Mimetype) + if att.FileName != "" { + w.Header().Set("Content-Disposition", fmt.Sprintf("inline; filename=\"%s\"", att.FileName)) + } + content := att.GetContent() + if content != nil { + w.Write(*content) + } +} diff --git a/src/api/api_handlers+ServerEnableDisableController.go b/src/api/api_handlers+ServerEnableDisableController.go new file mode 100644 index 00000000..6757598c --- /dev/null +++ b/src/api/api_handlers+ServerEnableDisableController.go @@ -0,0 +1,91 @@ +package api + +import ( + "net/http" + "time" + + models "github.com/nocodeleaks/quepasa/models" + whatsapp "github.com/nocodeleaks/quepasa/whatsapp" +) + +// SPAServerEnableController enables (starts) a server +// +// @Summary Enable a server (SPA) +// @Description Starts the WhatsApp server instance identified by {token}. Sends a system message to notify connected listeners. +// @Tags SPA +// @Accept json +// @Produce json +// @Param token path string true "Server token" +// @Success 200 {object} models.QpResponse +// @Failure 400 {object} models.QpResponse +// @Failure 401 {object} models.QpResponse +// @Failure 500 {object} models.QpResponse +// @Security Bearer +// @Router /server/{token}/enable [post] +func SPAServerEnableController(w http.ResponseWriter, r *http.Request) { + response := &models.QpResponse{} + + server, err := GetServer(r) + if err != nil { + response.ParseError(err) + RespondInterface(w, response) + return + } + + err = server.Start() + if err != nil { + response.ParseError(err) + RespondInterfaceCode(w, response, http.StatusInternalServerError) + return + } + + // notify + if server.Handler != nil { + sysMsg := &whatsapp.WhatsappMessage{ + Id: "server-enable-" + server.Token, + Timestamp: time.Now().UTC(), + Type: whatsapp.SystemMessageType, + FromMe: false, + Chat: whatsapp.WASYSTEMCHAT, + Text: "Server enabled", + Info: map[string]interface{}{"event": "server_enabled"}, + } + go server.Handler.Message(sysMsg, "server-enable-notify") + } + + RespondSuccess(w, map[string]interface{}{"result": "started"}) +} + +// SPAServerDisableController disables (stops) a server +// +// @Summary Disable a server (SPA) +// @Description Stops the WhatsApp server instance identified by {token}. Sends feedback to the caller on success. +// @Tags SPA +// @Accept json +// @Produce json +// @Param token path string true "Server token" +// @Success 200 {object} models.QpResponse +// @Failure 400 {object} models.QpResponse +// @Failure 401 {object} models.QpResponse +// @Failure 500 {object} models.QpResponse +// @Security Bearer +// @Router /server/{token}/disable [post] +func SPAServerDisableController(w http.ResponseWriter, r *http.Request) { + response := &models.QpResponse{} + + server, err := GetServer(r) + if err != nil { + response.ParseError(err) + RespondInterface(w, response) + return + } + + err = server.Stop("disabled via api") + if err != nil { + response.ParseError(err) + RespondInterfaceCode(w, response, http.StatusInternalServerError) + return + } + + RespondSuccess(w, map[string]interface{}{"result": "stopped"}) +} diff --git a/src/api/api_handlers.go b/src/api/api_handlers.go index 4124277f..42a7e5b3 100644 --- a/src/api/api_handlers.go +++ b/src/api/api_handlers.go @@ -1,6 +1,7 @@ package api import ( + "encoding/json" "fmt" "net/http" @@ -26,6 +27,9 @@ func RegisterAPIControllers(r chi.Router) { // Environment settings (master key only) r.Get(endpoint+"/environment", EnvironmentController) + // Login config (public) + r.Get(endpoint+"/login/config", LoginConfigController) + r.Post(endpoint+"/account", AccountController) // CONTROL METHODS ************************ @@ -38,7 +42,7 @@ func RegisterAPIControllers(r chi.Router) { r.Get(endpoint+"/scan", ScannerController) r.Get(endpoint+"/paircode", PairCodeController) - r.Get(endpoint+"/command", CommandController) + r.Post(endpoint+"/command", CommandController) // ---------------------------------------- // CONTROL METHODS ************************ @@ -55,6 +59,9 @@ func RegisterAPIControllers(r chi.Router) { // Mark message as read r.Post(endpoint+"/read", MarkReadController) + // Edit message + r.Put(endpoint+"/edit", EditMessageController) + // used to send alert msgs via url, triggers on monitor systems like zabbix r.Get(endpoint+"/send", SendAny) @@ -224,29 +231,55 @@ func RegisterAPIControllers(r chi.Router) { // CommandController manages bot server commands // // @Summary Execute bot commands -// @Description Execute control commands for the bot server (start, stop, restart) +// @Description Execute control commands for the bot server (start, stop, restart) or toggle settings (groups, broadcasts, readreceipts, readupdate, calls, debug) // @Tags Bot // @Accept json // @Produce json -// @Param action query string true "Command action" Enums(start, stop, restart) -// @Success 200 {object} models.QpResponse -// @Failure 400 {object} models.QpResponse -// @Security ApiKeyAuth -// @Router /command [get] +// @Param request body object{token=string,action=string} true "Command request" +// @Success 200 {object} models.QpResponse +// @Failure 400 {object} models.QpResponse +// @Failure 500 {object} models.QpResponse +// @Security ApiKeyAuth +// @Router /command [post] func CommandController(w http.ResponseWriter, r *http.Request) { // setting default response type as json w.Header().Set("Content-Type", "application/json") response := &models.QpResponse{} - server, err := GetServer(r) - if err != nil { - response.ParseError(err) - RespondInterface(w, response) - return + // parse optional JSON body { token, action } + var body struct { + Token string `json:"token"` + Action string `json:"action"` + } + if r.ContentLength > 0 { + _ = json.NewDecoder(r.Body).Decode(&body) + } + + // Determine action (body over query) + action := body.Action + if action == "" { + action = library.GetRequestParameter(r, "action") } - action := library.GetRequestParameter(r, "action") + // Resolve server: prefer explicit token from body, else from request + var server *models.QpWhatsappServer + var err error + if body.Token != "" { + server, err = models.GetServerFromToken(body.Token) + if err != nil { + response.ParseError(err) + RespondInterface(w, response) + return + } + } else { + server, err = GetServer(r) + if err != nil { + response.ParseError(err) + RespondInterface(w, response) + return + } + } switch action { case "start": err = server.Start() @@ -264,39 +297,47 @@ func CommandController(w http.ResponseWriter, r *http.Request) { response.ParseSuccess("restarted") } case "status": - err = fmt.Errorf("status command has been removed, please use /health endpoint instead") + // status action is deprecated; provide a helpful success message pointing to /health + response.ParseSuccess("'status' is deprecated; use /health endpoint instead") + err = nil case "groups": - err := models.ToggleGroups(server) + err = models.ToggleGroups(server) if err == nil { message := "groups toggled: " + server.Groups.String() response.ParseSuccess(message) } case "broadcasts": - err := models.ToggleBroadcasts(server) + err = models.ToggleBroadcasts(server) if err == nil { message := "broadcasts toggled: " + server.Broadcasts.String() response.ParseSuccess(message) } case "readreceipts": - err := models.ToggleReadReceipts(server) + err = models.ToggleReadReceipts(server) if err == nil { message := "readreceipts toggled: " + server.ReadReceipts.String() response.ParseSuccess(message) } case "calls": - err := models.ToggleCalls(server) + err = models.ToggleCalls(server) if err == nil { message := "calls toggled: " + server.Calls.String() response.ParseSuccess(message) } + case "readupdate": + err = models.ToggleReadUpdate(server) + if err == nil { + message := "readupdate toggled: " + server.ReadUpdate.String() + response.ParseSuccess(message) + } case "debug": - _, err := server.ToggleDevel() + _, err = server.ToggleDevel() if err == nil { message := "debug toggled: " + fmt.Sprintf("%t", server.Devel) response.ParseSuccess(message) } default: - err = fmt.Errorf("invalid action: {%s}, try {start,stop,restart,groups,broadcasts,readreceipts,calls,debug}", action) + err = fmt.Errorf("invalid action: {%s}, try {start,stop,restart,groups,broadcasts,readreceipts,readupdate,calls,debug}", action) } if err != nil { diff --git a/src/api/api_spa_routes.go b/src/api/api_spa_routes.go new file mode 100644 index 00000000..7539b2d1 --- /dev/null +++ b/src/api/api_spa_routes.go @@ -0,0 +1,105 @@ +package api + +import ( + "net/http" + "os" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/jwtauth" + models "github.com/nocodeleaks/quepasa/models" +) + +// Token of authentication / encryption for SPA routes +var spaTokenAuth = jwtauth.New("HS256", []byte(os.Getenv(models.ENV_SIGNING_SECRET)), nil) + +// GetSPATokenAuth returns the JWT authentication token for SPA routes +func GetSPATokenAuth() *jwtauth.JWTAuth { + return spaTokenAuth +} + +// SPAAuthenticatorHandler is the JWT authentication middleware for SPA routes +func SPAAuthenticatorHandler(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token, _, err := jwtauth.FromContext(r.Context()) + + if err != nil { + RespondErrorCode(w, err, http.StatusUnauthorized) + return + } + + if token == nil || !token.Valid { + RespondErrorCode(w, models.ErrFormUnauthenticated, http.StatusUnauthorized) + return + } + + next.ServeHTTP(w, r) + }) +} + +// RegisterSPAControllers registers SPA-related controllers under /api prefix +// These are authenticated routes for the Vue SPA frontend +func RegisterSPAControllers(r chi.Router) { + tokenAuth := GetSPATokenAuth() + r.Use(jwtauth.Verifier(tokenAuth)) + r.Use(SPAAuthenticatorHandler) + + // Session and servers + r.Get("/session", SPASessionController) + r.Get("/servers", SPAServersController) + // Server-side search for SPA + r.Post("/servers/search", SPAServersSearchController) + + // Account + r.Get("/account", SPAAccountController) + r.Get("/account/masterkey", SPAMasterKeyController) + + // Server management + r.Post("/server/create", SPAServerCreateController) + r.Post("/server/{token}/update", SPAServerUpdateController) + r.Get("/server/{token}/info", SPAServerInfoController) + r.Get("/server/{token}/qrcode", SPAServerQRCodeController) + r.Get("/server/{token}/paircode", SPAServerPairCodeController) + r.Post("/server/{token}/send", SPAServerSendController) + r.Get("/server/{token}/messages", SPAServerMessagesController) + r.Post("/server/{token}/messages/{messageid}/history/download", SPAServerHistoryDownloadController) + r.Post("/server/{token}/enable", SPAServerEnableController) + r.Post("/server/{token}/disable", SPAServerDisableController) + r.Post("/delete", SPAServerDeleteController) + r.Post("/debug", SPAServerDebugController) + r.Post("/toggle", SPAToggleController) + + // Message operations + r.Put("/server/{token}/message/{messageid}/edit", SPAServerEditMessageController) + r.Delete("/server/{token}/message/{messageid}", SPAServerRevokeMessageController) + r.Get("/server/{token}/download/{messageid}", SPAServerDownloadMediaController) + + // Chat operations + r.Post("/server/{token}/chat/archive", SPAServerArchiveChatController) + r.Post("/server/{token}/chat/presence", SPAServerPresenceController) + + // Contacts and Groups + r.Get("/server/{token}/contacts", SPAServerContactsController) + r.Get("/server/{token}/groups", SPAServerGroupsController) + + // User management + r.Get("/users", SPAUsersListController) + r.Post("/user", SPAUserController) + r.Delete("/user", SPAUserDeleteController) + + // Webhooks + r.Get("/webhooks", SPAWebHooksController) + r.Post("/webhooks", SPAWebHooksCreateController) + r.Put("/webhooks", SPAWebHooksUpdateController) + r.Delete("/webhooks", SPAWebHooksDeleteController) + + // RabbitMQ + r.Get("/rabbitmq", SPARabbitMQController) + r.Post("/rabbitmq", SPARabbitMQCreateController) + r.Delete("/rabbitmq", SPARabbitMQDeleteController) + + // Environment + r.Get("/environment", SPAEnvironmentController) + + // WebSocket for QR code verification + r.HandleFunc("/verify/ws", SPAVerifyWebSocketController) +} diff --git a/src/api/api_spa_utils.go b/src/api/api_spa_utils.go new file mode 100644 index 00000000..392769bf --- /dev/null +++ b/src/api/api_spa_utils.go @@ -0,0 +1,25 @@ +package api + +import ( + "net/http" + + "github.com/go-chi/jwtauth" + models "github.com/nocodeleaks/quepasa/models" +) + +// GetFormUserFromRequest gets the user_id from the JWT and finds the +// corresponding user in the database. This is used by SPA controllers +// that require JWT authentication. +func GetFormUserFromRequest(r *http.Request) (*models.QpUser, error) { + _, claims, err := jwtauth.FromContext(r.Context()) + if err != nil { + return nil, err + } + + user, ok := claims["user_id"].(string) + if !ok { + return nil, models.ErrFormUnauthenticated + } + + return models.WhatsappService.DB.Users.Find(user) +} diff --git a/src/api/api_websocket_client.go b/src/api/api_websocket_client.go new file mode 100644 index 00000000..f8a6b0b8 --- /dev/null +++ b/src/api/api_websocket_client.go @@ -0,0 +1,180 @@ +package api + +import ( + "bytes" + "context" + "strings" + "time" + + websocket "github.com/gorilla/websocket" + models "github.com/nocodeleaks/quepasa/models" + log "github.com/sirupsen/logrus" +) + +const ( + // Time allowed to write a message to the peer. + writeWait = 10 * time.Second + + // Time allowed to read the next pong message from the peer. + pongWait = 60 * time.Second + + // Send pings to peer with this period. Must be less than pongWait. + pingPeriod = (pongWait * 9) / 10 + + // Maximum message size allowed from peer. + maxMessageSize = 512 +) + +var ( + newline = []byte{'\n'} + space = []byte{' '} +) + +// WebSocketClient is a middleman between the websocket connection and the hub. +type WebSocketClient struct { + hub *Hub + + // The websocket connection. + conn *websocket.Conn + + // Buffered channel of outbound messages. + send chan []byte + + OnClose func(int, string) error + + Cancel func() + + ctx context.Context +} + +// readPump pumps messages from the websocket connection to the hub. +// +// The application runs readPump in a per-connection goroutine. The application +// ensures that there is at most one reader on a connection by executing all +// reads from this goroutine. +func (c *WebSocketClient) readPump(pairing models.QpWhatsappPairing) { + defer func() { + c.hub.unregister <- c + }() + + c.conn.SetReadLimit(maxMessageSize) + c.conn.SetReadDeadline(time.Now().Add(pongWait)) + c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil }) + + for { + _, message, err := c.conn.ReadMessage() + if err != nil { + if websocket.IsUnexpectedCloseError(err, + websocket.CloseNoStatusReceived, + websocket.CloseGoingAway, + websocket.CloseAbnormalClosure) { + log.Errorf("(websocket): unexpected, %s", err.Error()) + } + return + } + message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1)) + normalized := string(message) + normalized = strings.ToLower(normalized) + normalized = strings.TrimSpace(normalized) + log.Infof("(websocket): message received: %s", normalized) + + if normalized == "start" { + go c.QrCodeScanner(pairing) + } else { + log.Warnf("(websocket): received unknown msg: %s", normalized) + } + } +} + +func (c *WebSocketClient) QrCodeScanner(pairing models.QpWhatsappPairing) { + out := make(chan []byte) + defer close(out) + go func() { + for qrcode := range out { + c.hub.broadcast <- qrcode + } + }() + + // show qrcode + err := models.SignInWithQRCode(c.ctx, pairing, out) + if err != nil { + if strings.Contains(err.Error(), "time") { + c.hub.broadcast <- []byte("timeout") + } else { + log.Errorf("unknown error on sign in with qrcode: %s", err.Error()) + } + } else { + log.Info("complete to read qr code on websocket") + c.hub.broadcast <- []byte("complete") + } +} + +// writePump pumps messages from the hub to the websocket connection. +// +// A goroutine running writePump is started for each connection. The +// application ensures that there is at most one writer to a connection by +// executing all writes from this goroutine. +func (c *WebSocketClient) writePump() { + ticker := time.NewTicker(pingPeriod) + defer func() { + ticker.Stop() + c.conn.Close() + }() + for { + select { + case message, ok := <-c.send: + c.conn.SetWriteDeadline(time.Now().Add(writeWait)) + if !ok { + // The hub closed the channel. + c.conn.WriteMessage(websocket.CloseMessage, []byte{}) + return + } + + w, err := c.conn.NextWriter(websocket.TextMessage) + if err != nil { + return + } + w.Write(message) + + // Add queued chat messages to the current websocket message. + n := len(c.send) + for i := 0; i < n; i++ { + w.Write(newline) + w.Write(<-c.send) + } + + if err := w.Close(); err != nil { + return + } + case <-ticker.C: + c.conn.SetWriteDeadline(time.Now().Add(writeWait)) + if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil { + return + } + } + } +} + +// WebSocketStart handles websocket requests from the peer. +func WebSocketStart(pairing models.QpWhatsappPairing, conn *websocket.Conn) { + execContext, cancel := context.WithCancel(context.Background()) + + hub := newHub() + go hub.run() + + client := &WebSocketClient{hub: hub, conn: conn, send: make(chan []byte, 256), ctx: execContext} + client.hub.register <- client + client.OnClose = client.conn.CloseHandler() + client.conn.SetCloseHandler(client.OnWebSocketClosed) + client.Cancel = cancel + + // Allow collection of memory referenced by the caller by doing all work in + // new goroutines. + go client.writePump() + go client.readPump(pairing) +} + +func (c *WebSocketClient) OnWebSocketClosed(code int, text string) error { + c.Cancel() + return c.OnClose(code, text) +} diff --git a/src/api/api_websocket_hub.go b/src/api/api_websocket_hub.go new file mode 100644 index 00000000..8cbfb123 --- /dev/null +++ b/src/api/api_websocket_hub.go @@ -0,0 +1,49 @@ +package api + +// Hub maintains the set of active clients and broadcasts messages to the +// clients. +type Hub struct { + // Registered clients. + clients map[*WebSocketClient]bool + + // Inbound messages from the clients. + broadcast chan []byte + + // Register requests from the clients. + register chan *WebSocketClient + + // Unregister requests from clients. + unregister chan *WebSocketClient +} + +func newHub() *Hub { + return &Hub{ + broadcast: make(chan []byte), + register: make(chan *WebSocketClient), + unregister: make(chan *WebSocketClient), + clients: make(map[*WebSocketClient]bool), + } +} + +func (h *Hub) run() { + for { + select { + case client := <-h.register: + h.clients[client] = true + case client := <-h.unregister: + if _, ok := h.clients[client]; ok { + delete(h.clients, client) + close(client.send) + } + case message := <-h.broadcast: + for client := range h.clients { + select { + case client.send <- message: + default: + close(client.send) + delete(h.clients, client) + } + } + } + } +} diff --git a/src/assets/frontend/assets/groupdetail.css b/src/assets/frontend/assets/groupdetail.css new file mode 100644 index 00000000..31d9d768 --- /dev/null +++ b/src/assets/frontend/assets/groupdetail.css @@ -0,0 +1 @@ +.group-detail-page[data-v-1c61b59e]{max-width:1200px;width:100%;margin:0 auto;padding:24px}.group-layout[data-v-1c61b59e]{display:grid;grid-template-columns:1.35fr 1fr;gap:20px;align-items:start}.messages-column[data-v-1c61b59e]{background:#0f172a;color:#e5e7eb;border-radius:16px;padding:16px;box-shadow:0 10px 30px #00000026;min-height:520px}.messages-header[data-v-1c61b59e]{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:12px}.messages-header h2[data-v-1c61b59e]{margin:0;font-size:1.4rem;letter-spacing:.01em}.messages-header small[data-v-1c61b59e]{color:#cbd5e1}.eyebrow[data-v-1c61b59e]{margin:0;text-transform:uppercase;letter-spacing:.12em;font-size:.7rem;color:#94a3b8}.messages-list[data-v-1c61b59e]{display:flex;flex-direction:column;gap:12px;max-height:calc(100vh - 220px);overflow-y:auto;padding-right:6px}.message-item[data-v-1c61b59e]{display:grid;grid-template-columns:auto 1fr;gap:10px;padding:12px;border-radius:12px;background:linear-gradient(135deg,#ffffff0f,#ffffff05);border:1px solid rgba(255,255,255,.06)}.message-avatar img[data-v-1c61b59e],.avatar-placeholder-small[data-v-1c61b59e]{width:38px;height:38px;border-radius:10px;object-fit:cover;background:#1f2937;display:flex;align-items:center;justify-content:center;color:#94a3b8}.message-content[data-v-1c61b59e]{display:flex;flex-direction:column;gap:6px;overflow:hidden}.message-meta[data-v-1c61b59e]{display:flex;justify-content:space-between;align-items:center;font-size:.85rem;color:#cbd5e1}.message-sender[data-v-1c61b59e]{font-weight:600;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.message-time[data-v-1c61b59e]{font-size:.78rem;color:#94a3b8}.message-text[data-v-1c61b59e]{color:#e2e8f0;line-height:1.5;word-break:break-word}.load-more-state[data-v-1c61b59e]{text-align:center;padding:8px;color:#cbd5e1}.load-more-state.muted[data-v-1c61b59e]{color:#94a3b8}.load-more-btn[data-v-1c61b59e]{background:#e5e7eb;color:#0f172a;border:none;padding:8px 14px;border-radius:10px;cursor:pointer;font-weight:600}.load-more-btn[data-v-1c61b59e]:hover{background:#cbd5e1}.empty-messages[data-v-1c61b59e]{color:#94a3b8;text-align:center;padding:20px 0}@media (max-width: 1024px){.group-layout[data-v-1c61b59e]{grid-template-columns:1fr}.messages-column[data-v-1c61b59e]{order:2}.details-column[data-v-1c61b59e]{order:1}}.loading-container[data-v-1c61b59e]{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:100px 20px;color:#6b7280}.loading-spinner[data-v-1c61b59e]{width:40px;height:40px;border:3px solid #e5e7eb;border-top-color:#00034b;border-radius:50%;animation:spin-1c61b59e 1s linear infinite;margin-bottom:15px}@keyframes spin-1c61b59e{to{transform:rotate(360deg)}}.error-container[data-v-1c61b59e]{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:100px 20px;color:#dc3545;text-align:center}.error-container i[data-v-1c61b59e]{font-size:3rem;margin-bottom:15px}.btn-back[data-v-1c61b59e]{margin-top:20px;padding:10px 20px;background:#00034b;color:#fff;border-radius:8px;text-decoration:none}.group-header[data-v-1c61b59e]{text-align:center;padding:20px 0 30px;position:relative}.back-btn[data-v-1c61b59e]{position:absolute;left:0;top:20px;display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;background:#e5e7eb;color:#00034b;text-decoration:none;transition:all .2s}.back-btn[data-v-1c61b59e]:hover{background:#00034b;color:#fff}.group-photo-container[data-v-1c61b59e]{position:relative;display:inline-block;margin-bottom:15px}.group-photo[data-v-1c61b59e]{width:120px;height:120px;border-radius:50%;object-fit:cover;border:3px solid #e5e7eb}.group-photo-placeholder[data-v-1c61b59e]{width:120px;height:120px;border-radius:50%;background:linear-gradient(135deg,#00034b,#000266);display:flex;align-items:center;justify-content:center;color:#fff;font-size:3rem}.edit-photo-btn[data-v-1c61b59e]{position:absolute;bottom:0;right:0;width:36px;height:36px;border-radius:50%;background:#00034b;color:#fff;border:3px solid white;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s}.edit-photo-btn[data-v-1c61b59e]:hover{background:#000266}.group-name[data-v-1c61b59e]{margin:0 0 5px;font-size:1.5rem;color:#111827;display:flex;align-items:center;justify-content:center;gap:10px}.edit-btn[data-v-1c61b59e]{padding:5px 8px;background:transparent;border:none;color:#6b7280;cursor:pointer;border-radius:4px;transition:all .2s}.edit-btn[data-v-1c61b59e]:hover{background:#e5e7eb;color:#00034b}.group-meta[data-v-1c61b59e]{margin:0;color:#6b7280;font-size:.9rem}.section[data-v-1c61b59e]{background:#fff;border:1px solid #e5e7eb;border-radius:12px;padding:16px;margin-bottom:16px}.section-header[data-v-1c61b59e]{display:flex;align-items:center;gap:10px;font-weight:600;color:#111827;margin-bottom:12px}.section-header i[data-v-1c61b59e]{color:#00034b}.description-text[data-v-1c61b59e]{margin:0;color:#374151;white-space:pre-wrap;line-height:1.5}.description-empty[data-v-1c61b59e]{margin:0;color:#9ca3af;font-style:italic}.description-meta[data-v-1c61b59e]{margin:10px 0 0;font-size:.75rem;color:#9ca3af}.actions-section[data-v-1c61b59e]{display:flex;justify-content:space-around;padding:12px}.action-btn[data-v-1c61b59e]{display:flex;flex-direction:column;align-items:center;gap:6px;padding:12px 20px;background:transparent;border:none;color:#00034b;cursor:pointer;border-radius:8px;transition:all .2s}.action-btn[data-v-1c61b59e]:hover{background:#e5e7eb}.action-btn i[data-v-1c61b59e]{font-size:1.2rem}.action-btn span[data-v-1c61b59e]{font-size:.8rem}.search-box[data-v-1c61b59e]{margin-bottom:12px}.search-input[data-v-1c61b59e]{width:100%;padding:10px 14px;border:1px solid #e5e7eb;border-radius:8px;font-size:.9rem;outline:none;transition:border-color .2s}.search-input[data-v-1c61b59e]:focus{border-color:#00034b}.participants-list[data-v-1c61b59e]{max-height:400px;overflow-y:auto}.participant-item[data-v-1c61b59e]{display:flex;align-items:center;gap:12px;padding:10px 0;border-bottom:1px solid #f3f4f6}.participant-item[data-v-1c61b59e]:last-child{border-bottom:none}.participant-avatar img[data-v-1c61b59e]{width:45px;height:45px;border-radius:50%;object-fit:cover}.participant-avatar .avatar-placeholder[data-v-1c61b59e]{width:45px;height:45px;border-radius:50%;background:#e5e7eb;display:flex;align-items:center;justify-content:center;color:#6b7280}.participant-info[data-v-1c61b59e]{flex:1;min-width:0}.participant-name[data-v-1c61b59e]{font-weight:500;color:#111827;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.participant-phone[data-v-1c61b59e]{font-size:.8rem;color:#6b7280}.participant-badges[data-v-1c61b59e]{display:flex;gap:5px}.badge[data-v-1c61b59e]{padding:4px 8px;border-radius:4px;font-size:.7rem;font-weight:500}.badge-owner[data-v-1c61b59e]{background:#00034b1a;color:#00034b}.badge-admin[data-v-1c61b59e]{background:#10b9811a;color:#059669}.danger-section[data-v-1c61b59e]{background:#fef2f2;border-color:#fecaca}.danger-btn[data-v-1c61b59e]{width:100%;display:flex;align-items:center;justify-content:center;gap:10px;padding:12px;background:transparent;border:none;color:#dc2626;font-weight:500;cursor:pointer;border-radius:8px;transition:all .2s}.danger-btn[data-v-1c61b59e]:hover{background:#fee2e2}@media (max-width: 640px){.group-detail-page[data-v-1c61b59e]{padding:15px}.group-photo[data-v-1c61b59e],.group-photo-placeholder[data-v-1c61b59e]{width:100px;height:100px}.group-photo-placeholder[data-v-1c61b59e]{font-size:2.5rem}.action-btn[data-v-1c61b59e]{padding:10px 15px}} diff --git a/src/assets/frontend/assets/groupdetail.js b/src/assets/frontend/assets/groupdetail.js new file mode 100644 index 00000000..19a1af67 --- /dev/null +++ b/src/assets/frontend/assets/groupdetail.js @@ -0,0 +1 @@ +import{d as le,u as ue,r as v,c as L,o as ce,a as y,p as f,b as de,_ as pe,e as u,f as a,h as j,t as m,i as F,j as ge,g as P,F as J,q,k as z,l as me,v as fe,s as c}from"./index.js";const ve=le({setup(){const e=ue(),s=de(),g=e.params.token,k=e.params.id,w=v({}),B=v(""),T=v({}),D=v([]),h=v([]),n=v(!1),$=v(""),C=v(!1),M=v(""),I=v(""),A=v(null),N=v(!1),S=50,H=L(()=>D.value.length),U=L(()=>h.value.length{if(!w.value.Participants||!I.value)return!1;const t=w.value.Participants.find(o=>{var r,i;return((r=o.PhoneNumber)==null?void 0:r.includes(I.value))||((i=o.JID)==null?void 0:i.includes(I.value))});return(t==null?void 0:t.IsAdmin)||(t==null?void 0:t.IsSuperAdmin)||!1}),_=L(()=>{const t=w.value.Participants||[];if(!M.value)return t;const o=M.value.toLowerCase();return t.filter(r=>{var i,l,b;return((i=r.DisplayName)==null?void 0:i.toLowerCase().includes(o))||((l=r.PhoneNumber)==null?void 0:l.includes(o))||((b=r.JID)==null?void 0:b.includes(o))})});async function R(){var t,o,r,i;n.value=!0,$.value="",D.value=[],h.value=[];try{const l=await y.get(`/api/groups/get?token=${encodeURIComponent(g)}&groupid=${encodeURIComponent(k)}`);w.value=((t=l.data)==null?void 0:t.groupinfo)||{},O();const p=((o=(await y.get(`/api/server/${g}/info`)).data)==null?void 0:o.wid)||"";I.value=p.replace("@s.whatsapp.net","").replace("@lid",""),await Z(),await Y()}catch(l){$.value=((i=(r=l==null?void 0:l.response)==null?void 0:r.data)==null?void 0:i.result)||(l==null?void 0:l.message)||"Erro ao carregar grupo"}finally{n.value=!1}}async function O(){var t;try{const o=await y.get(`/api/picinfo/${encodeURIComponent(k)}?token=${encodeURIComponent(g)}`);(t=o.data)!=null&&t.url&&(B.value=o.data.url)}catch{}}async function Z(){var o;const t=(w.value.Participants||[]).slice(0,10);for(const r of t){const i=r.PhoneNumber||r.JID;if(i)try{const l=await y.get(`/api/picinfo/${encodeURIComponent(i)}?token=${encodeURIComponent(g)}`);(o=l.data)!=null&&o.url&&(T.value[i]=l.data.url)}catch{}}}function K(t){if(!t)return"";let o=t.replace("@s.whatsapp.net","").replace("@lid","");if(o.length>=12){const r=o.slice(0,2),i=o.slice(2,4),l=o.slice(4,9),b=o.slice(9);return`+${r} ${i} ${l}-${b}`}return o}function Q(t){return t?new Date(t).toLocaleDateString("pt-BR",{day:"2-digit",month:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit"}):""}function X(t){if(!t)return"";const o=new Date(t),r=new Date,i=r.getTime()-o.getTime(),l=24*60*60*1e3;return inew Date(E.timestamp).getTime()-new Date(p.timestamp).getTime()),D.value=b,h.value=b.slice(0,S)}catch{}}function V(){if(!U.value||N.value)return;N.value=!0;const t=D.value.slice(h.value.length,h.value.length+S);h.value=h.value.concat(t),requestAnimationFrame(()=>{N.value=!1})}function x(){const t=A.value;if(!t||N.value||!U.value)return;t.scrollHeight-(t.scrollTop+t.clientHeight)<160&&V()}function ee(t,o=120){const r=t.text||"";return r.length<=o?r:r.substring(0,o)+"..."}function se(){C.value=!C.value,C.value||(M.value="")}async function te(){var t,o;if(confirm("Deseja realmente sair do grupo?"))try{await y.post("/api/groups/leave",{token:g,group_jid:k}),f("Saída do grupo solicitada","success"),s.push(`/server/${g}/groups`)}catch(r){f(((o=(t=r==null?void 0:r.response)==null?void 0:t.data)==null?void 0:o.result)||(r==null?void 0:r.message)||"Erro ao sair do grupo","error")}}async function ae(){var o,r;const t=prompt("Novo nome do grupo (<=25 caracteres):",w.value.Name||"");if(t)try{await y.put("/api/groups/name",{token:g,group_jid:k,name:t}),f("Nome do grupo atualizado","success"),await R()}catch(i){f(((r=(o=i==null?void 0:i.response)==null?void 0:o.data)==null?void 0:r.result)||(i==null?void 0:i.message)||"Erro ao atualizar nome","error")}}async function oe(){var o,r;const t=prompt("Nova descrição do grupo:",w.value.Topic||"");if(t!=null)try{await y.put("/api/groups/description",{token:g,group_jid:k,topic:t}),f("Descrição atualizada","success"),await R()}catch(i){f(((r=(o=i==null?void 0:i.response)==null?void 0:o.data)==null?void 0:r.result)||(i==null?void 0:i.message)||"Erro ao atualizar descrição","error")}}async function ie(){var r,i;const t=prompt("Telefone(s) para adicionar (separados por vírgula):");if(!t)return;const o=t.split(",").map(l=>l.trim()).filter(Boolean);try{await y.put("/api/groups/participants",{token:g,group_jid:k,participants:o}),f("Participantes adicionados","success"),await R()}catch(l){f(((i=(r=l==null?void 0:l.response)==null?void 0:r.data)==null?void 0:i.result)||(l==null?void 0:l.message)||"Erro ao adicionar participante","error")}}async function ne(){var o,r;const t=prompt("URL da imagem do grupo (ou vazio para cancelar):");if(t)try{await y.put("/api/groups/photo",{token:g,group_jid:k,image_url:t}),f("Foto do grupo atualizada","success"),await R()}catch(i){f(((r=(o=i==null?void 0:i.response)==null?void 0:o.data)==null?void 0:r.result)||(i==null?void 0:i.message)||"Erro ao alterar foto","error")}}async function re(){var t,o,r;try{const l=(t=(await y.get(`/api/invite?chatid=${encodeURIComponent(k)}&token=${encodeURIComponent(g)}`)).data)==null?void 0:t.url;l?(await navigator.clipboard.writeText(l),f("Link copiado para a área de transferência!","success")):f("Nenhum link de convite disponível","error")}catch(i){f(((r=(o=i==null?void 0:i.response)==null?void 0:o.data)==null?void 0:r.result)||(i==null?void 0:i.message)||"Erro ao obter link","error")}}return ce(()=>{R()}),{token:g,group:w,groupPicture:B,participantPictures:T,messages:D,visibleMessages:h,loading:n,error:$,isAdmin:W,showSearch:C,participantSearch:M,totalMessages:H,hasMoreMessages:U,isLoadingMore:N,messagesListRef:A,filteredParticipants:_,formatPhone:K,formatDate:Q,formatTime:X,messagePreview:ee,loadMoreMessages:V,onMessagesScroll:x,searchParticipants:se,leaveGroup:te,setGroupName:ae,setGroupTopic:oe,setGroupPhoto:ne,addParticipant:ie,getInvite:re}}}),he={class:"group-detail-page"},ye={key:0,class:"loading-container"},ke={key:1,class:"error-container"},be={key:2,class:"group-layout"},Pe={class:"messages-column"},we={class:"messages-header"},De={key:0},Ne={class:"message-avatar"},Ce=["src"],Me={key:1,class:"avatar-placeholder-small"},Ie={class:"message-content"},$e={class:"message-meta"},Te={class:"message-sender"},Ae={class:"message-time"},Se={class:"message-text"},Re={key:0,class:"load-more-state"},Ee={key:1,class:"load-more-state"},Ge={key:2,class:"load-more-state muted"},Le={key:1,class:"empty-messages"},Be={class:"details-column"},Ue={class:"group-header"},Ve={class:"group-photo-container"},je=["src","alt"],Fe={key:1,class:"group-photo-placeholder"},Je={class:"group-name"},qe={class:"group-meta"},ze={key:0,class:"section"},He={class:"section-header"},We={key:0,class:"description-text"},_e={key:1,class:"description-empty"},Oe={key:2,class:"description-meta"},Ze={class:"section actions-section"},Ke={class:"section"},Qe={class:"section-header"},Xe={key:0,class:"search-box"},Ye={class:"participants-list"},xe={class:"participant-avatar"},es=["src","alt"],ss={key:1,class:"avatar-placeholder"},ts={class:"participant-info"},as={class:"participant-name"},os={key:0},is={key:1},ns={key:0,class:"participant-phone"},rs={class:"participant-badges"},ls={key:0,class:"badge badge-owner"},us={key:1,class:"badge badge-admin"},cs={class:"section danger-section"};function ds(e,s,g,k,w,B){var D,h;const T=ge("router-link");return c(),u("div",he,[e.loading?(c(),u("div",ye,[...s[10]||(s[10]=[a("div",{class:"loading-spinner"},null,-1),a("p",null,"Carregando grupo...",-1)])])):e.error?(c(),u("div",ke,[s[12]||(s[12]=a("i",{class:"fa fa-exclamation-triangle"},null,-1)),a("p",null,m(e.error),1),j(T,{to:`/server/${e.token}/groups`,class:"btn-back"},{default:F(()=>[...s[11]||(s[11]=[z("Voltar aos grupos",-1)])]),_:1},8,["to"])])):(c(),u("div",be,[a("div",Pe,[a("div",we,[s[13]||(s[13]=a("div",null,[a("p",{class:"eyebrow"},"Histórico recente"),a("h2",null,"Mensagens")],-1)),e.totalMessages?(c(),u("small",De,m(e.visibleMessages.length)+" de "+m(e.totalMessages)+" mensagens",1)):P("",!0)]),e.visibleMessages.length?(c(),u("div",{key:0,class:"messages-list",ref:"messagesListRef",onScrollPassive:s[1]||(s[1]=(...n)=>e.onMessagesScroll&&e.onMessagesScroll(...n))},[(c(!0),u(J,null,q(e.visibleMessages,n=>{var $,C,M,I,A,N,S;return c(),u("div",{key:n.id,class:"message-item"},[a("div",Ne,[e.participantPictures[(($=n.participant)==null?void 0:$.phone)||((C=n.participant)==null?void 0:C.id)]?(c(),u("img",{key:0,src:e.participantPictures[((M=n.participant)==null?void 0:M.phone)||((I=n.participant)==null?void 0:I.id)]},null,8,Ce)):(c(),u("div",Me,[...s[14]||(s[14]=[a("i",{class:"fa fa-user"},null,-1)])]))]),a("div",Ie,[a("div",$e,[a("span",Te,m(((A=n.participant)==null?void 0:A.title)||e.formatPhone(((N=n.participant)==null?void 0:N.phone)||((S=n.participant)==null?void 0:S.id))),1),a("span",Ae,m(e.formatTime(n.timestamp)),1)]),a("div",Se,m(e.messagePreview(n)),1)])])}),128)),e.isLoadingMore?(c(),u("div",Re,"Carregando mais mensagens...")):e.hasMoreMessages?(c(),u("div",Ee,[a("button",{class:"load-more-btn",type:"button",onClick:s[0]||(s[0]=(...n)=>e.loadMoreMessages&&e.loadMoreMessages(...n))},"Carregar mais 50")])):(c(),u("div",Ge," Você chegou ao início do histórico "))],544)):(c(),u("div",Le,"Nenhuma mensagem recente"))]),a("div",Be,[a("div",Ue,[j(T,{to:`/server/${e.token}/groups`,class:"back-btn"},{default:F(()=>[...s[15]||(s[15]=[a("i",{class:"fa fa-arrow-left"},null,-1)])]),_:1},8,["to"]),a("div",Ve,[e.groupPicture?(c(),u("img",{key:0,src:e.groupPicture,alt:e.group.Name,class:"group-photo"},null,8,je)):(c(),u("div",Fe,[...s[16]||(s[16]=[a("i",{class:"fa fa-users"},null,-1)])])),e.isAdmin?(c(),u("button",{key:2,onClick:s[2]||(s[2]=(...n)=>e.setGroupPhoto&&e.setGroupPhoto(...n)),class:"edit-photo-btn",title:"Alterar foto"},[...s[17]||(s[17]=[a("i",{class:"fa fa-camera"},null,-1)])])):P("",!0)]),a("h1",Je,[z(m(e.group.Name||"Grupo sem nome")+" ",1),e.isAdmin?(c(),u("button",{key:0,onClick:s[3]||(s[3]=(...n)=>e.setGroupName&&e.setGroupName(...n)),class:"edit-btn",title:"Alterar nome"},[...s[18]||(s[18]=[a("i",{class:"fa fa-pencil"},null,-1)])])):P("",!0)]),a("p",qe," Grupo · "+m(((D=e.group.Participants)==null?void 0:D.length)||0)+" membros ",1)]),e.group.Topic||e.isAdmin?(c(),u("div",ze,[a("div",He,[s[20]||(s[20]=a("i",{class:"fa fa-info-circle"},null,-1)),s[21]||(s[21]=a("span",null,"Descrição",-1)),e.isAdmin?(c(),u("button",{key:0,onClick:s[4]||(s[4]=(...n)=>e.setGroupTopic&&e.setGroupTopic(...n)),class:"edit-btn",title:"Alterar descrição"},[...s[19]||(s[19]=[a("i",{class:"fa fa-pencil"},null,-1)])])):P("",!0)]),e.group.Topic?(c(),u("p",We,m(e.group.Topic),1)):(c(),u("p",_e,"Nenhuma descrição definida")),e.group.TopicSetAt?(c(),u("p",Oe," Criada em "+m(e.formatDate(e.group.TopicSetAt)),1)):P("",!0)])):P("",!0),a("div",Ze,[a("button",{class:"action-btn",onClick:s[5]||(s[5]=(...n)=>e.getInvite&&e.getInvite(...n))},[...s[22]||(s[22]=[a("i",{class:"fa fa-link"},null,-1),a("span",null,"Link de convite",-1)])]),e.isAdmin?(c(),u("button",{key:0,class:"action-btn",onClick:s[6]||(s[6]=(...n)=>e.addParticipant&&e.addParticipant(...n))},[...s[23]||(s[23]=[a("i",{class:"fa fa-user-plus"},null,-1),a("span",null,"Adicionar",-1)])])):P("",!0),a("button",{class:"action-btn",onClick:s[7]||(s[7]=(...n)=>e.searchParticipants&&e.searchParticipants(...n))},[...s[24]||(s[24]=[a("i",{class:"fa fa-search"},null,-1),a("span",null,"Pesquisar",-1)])])]),a("div",Ke,[a("div",Qe,[s[25]||(s[25]=a("i",{class:"fa fa-users"},null,-1)),a("span",null,m(((h=e.group.Participants)==null?void 0:h.length)||0)+" membros",1)]),e.showSearch?(c(),u("div",Xe,[me(a("input",{"onUpdate:modelValue":s[8]||(s[8]=n=>e.participantSearch=n),type:"text",placeholder:"Pesquisar membros...",class:"search-input"},null,512),[[fe,e.participantSearch]])])):P("",!0),a("div",Ye,[(c(!0),u(J,null,q(e.filteredParticipants,n=>(c(),u("div",{key:n.JID,class:"participant-item"},[a("div",xe,[e.participantPictures[n.PhoneNumber||n.JID]?(c(),u("img",{key:0,src:e.participantPictures[n.PhoneNumber||n.JID],alt:n.DisplayName},null,8,es)):(c(),u("div",ss,[...s[26]||(s[26]=[a("i",{class:"fa fa-user"},null,-1)])]))]),a("div",ts,[a("div",as,[n.DisplayName?(c(),u("span",os,"~ "+m(n.DisplayName),1)):(c(),u("span",is,m(e.formatPhone(n.PhoneNumber||n.JID)),1))]),n.DisplayName&&n.PhoneNumber?(c(),u("div",ns,m(e.formatPhone(n.PhoneNumber)),1)):P("",!0)]),a("div",rs,[n.IsSuperAdmin?(c(),u("span",ls,"Criador")):n.IsAdmin?(c(),u("span",us,"Admin")):P("",!0)])]))),128))])]),a("div",cs,[a("button",{class:"danger-btn",onClick:s[9]||(s[9]=(...n)=>e.leaveGroup&&e.leaveGroup(...n))},[...s[27]||(s[27]=[a("i",{class:"fa fa-sign-out"},null,-1),a("span",null,"Sair do grupo",-1)])])])])]))])}const gs=pe(ve,[["render",ds],["__scopeId","data-v-1c61b59e"]]);export{gs as default}; diff --git a/src/assets/frontend/assets/groups.css b/src/assets/frontend/assets/groups.css new file mode 100644 index 00000000..fc71a950 --- /dev/null +++ b/src/assets/frontend/assets/groups.css @@ -0,0 +1 @@ +.groups-page[data-v-6c4bb8c9]{padding:20px;max-width:1400px;margin:0 auto}.page-header[data-v-6c4bb8c9]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;flex-wrap:wrap;gap:15px}.header-left[data-v-6c4bb8c9]{display:flex;align-items:center;gap:15px}.back-btn[data-v-6c4bb8c9]{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;background:#e5e7eb;color:#00034b;text-decoration:none;transition:all .2s}.back-btn[data-v-6c4bb8c9]:hover{background:#00034b;color:#fff}.page-header h1[data-v-6c4bb8c9]{margin:0;font-size:1.8rem;color:#111827}.group-count[data-v-6c4bb8c9]{color:#6b7280;font-size:1rem}.header-actions[data-v-6c4bb8c9]{display:flex;align-items:center;gap:10px}.view-toggle[data-v-6c4bb8c9]{display:flex;background:#e5e7eb;border-radius:8px;overflow:hidden}.toggle-btn[data-v-6c4bb8c9]{padding:8px 12px;border:none;background:transparent;color:#6b7280;cursor:pointer;transition:all .2s}.toggle-btn.active[data-v-6c4bb8c9]{background:#00034b;color:#fff}.toggle-btn[data-v-6c4bb8c9]:hover:not(.active){color:#111827}.btn-icon[data-v-6c4bb8c9]{width:40px;height:40px;border-radius:50%;border:none;background:#e5e7eb;color:#00034b;cursor:pointer;transition:all .2s}.btn-icon[data-v-6c4bb8c9]:hover{background:#00034b;color:#fff}.btn-primary[data-v-6c4bb8c9]{padding:10px 20px;border:none;border-radius:8px;background:#00034b;color:#fff;font-weight:500;cursor:pointer;transition:all .2s}.btn-primary[data-v-6c4bb8c9]:hover{background:#000266;transform:translateY(-1px)}.search-bar[data-v-6c4bb8c9]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#e5e7eb;border-radius:12px;margin-bottom:20px}.search-bar i[data-v-6c4bb8c9]{color:#6b7280}.search-input[data-v-6c4bb8c9]{flex:1;border:none;background:transparent;color:#111827;font-size:1rem;outline:none}.search-input[data-v-6c4bb8c9]::placeholder{color:#6b7280}.clear-search[data-v-6c4bb8c9]{padding:4px 8px;border:none;background:transparent;color:#6b7280;cursor:pointer}.clear-search[data-v-6c4bb8c9]:hover{color:#111827}.pagination-controls[data-v-6c4bb8c9]{display:flex;align-items:center;gap:8px;padding:10px 12px;background:#f8fafc;border:1px solid #e5e7eb;border-radius:10px;margin-bottom:16px}.btn-page[data-v-6c4bb8c9]{width:34px;height:34px;border-radius:8px;border:1px solid #e5e7eb;background:#fff;color:#00034b;cursor:pointer;transition:all .2s}.btn-page[data-v-6c4bb8c9]:disabled{opacity:.5;cursor:not-allowed}.btn-page[data-v-6c4bb8c9]:hover:not(:disabled){background:#00034b;color:#fff}.page-info[data-v-6c4bb8c9]{font-size:.9rem;color:#6b7280;margin:0 4px}.page-size-select[data-v-6c4bb8c9]{margin-left:auto;border:1px solid #e5e7eb;border-radius:8px;padding:6px 10px;background:#fff;color:#111827}.loading-container[data-v-6c4bb8c9]{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;color:#6b7280}.loading-spinner[data-v-6c4bb8c9]{width:40px;height:40px;border:3px solid #e5e7eb;border-top-color:#00034b;border-radius:50%;animation:spin-6c4bb8c9 1s linear infinite;margin-bottom:15px}@keyframes spin-6c4bb8c9{to{transform:rotate(360deg)}}.error-box[data-v-6c4bb8c9]{display:flex;align-items:center;gap:10px;padding:15px 20px;background:#dc35451a;border:1px solid rgba(220,53,69,.3);border-radius:12px;color:#dc3545}.empty-state[data-v-6c4bb8c9]{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;color:#6b7280}.empty-state i[data-v-6c4bb8c9]{font-size:4rem;margin-bottom:15px;opacity:.5}.groups-grid[data-v-6c4bb8c9]{display:grid;grid-template-columns:repeat(auto-fill,minmax(350px,1fr));gap:16px}.group-card[data-v-6c4bb8c9]{display:flex;gap:15px;padding:16px;background:#fff;border-radius:12px;cursor:pointer;transition:all .2s;border:1px solid #e5e7eb;box-shadow:0 1px 3px #0000001a}.group-card[data-v-6c4bb8c9]:hover{border-color:#00034b;transform:translateY(-2px);box-shadow:0 4px 12px #00034b26}.card-avatar[data-v-6c4bb8c9],.item-avatar[data-v-6c4bb8c9]{flex-shrink:0}.card-avatar img[data-v-6c4bb8c9],.item-avatar img[data-v-6c4bb8c9]{width:60px;height:60px;border-radius:50%;object-fit:cover}.avatar-placeholder[data-v-6c4bb8c9]{width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,#00034b,#000266);display:flex;align-items:center;justify-content:center;color:#fff;font-size:1.5rem}.card-content[data-v-6c4bb8c9],.item-content[data-v-6c4bb8c9]{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}.card-header[data-v-6c4bb8c9],.item-header[data-v-6c4bb8c9]{display:flex;justify-content:space-between;align-items:flex-start;gap:10px}.group-name[data-v-6c4bb8c9]{margin:0;font-size:1rem;font-weight:600;color:#111827;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.message-time[data-v-6c4bb8c9]{font-size:.75rem;color:#00034b;white-space:nowrap}.last-message[data-v-6c4bb8c9]{margin:0;font-size:.875rem;color:#6b7280;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.last-message.empty[data-v-6c4bb8c9]{font-style:italic;opacity:.7}.sender-name[data-v-6c4bb8c9]{color:#00034b;font-weight:500}.card-footer[data-v-6c4bb8c9]{display:flex;align-items:center;gap:10px;margin-top:auto}.participants-count[data-v-6c4bb8c9]{font-size:.75rem;color:#6b7280}.participants-info[data-v-6c4bb8c9]{font-size:.875rem;color:#6b7280}.badge[data-v-6c4bb8c9]{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;font-size:.7rem}.badge-announce[data-v-6c4bb8c9]{background:#ffc10733;color:#d97706}.badge-community[data-v-6c4bb8c9]{background:#00034b1a;color:#00034b}.groups-list[data-v-6c4bb8c9]{display:flex;flex-direction:column;gap:0;background:#fff;border-radius:12px;overflow:hidden;border:1px solid #e5e7eb}.group-item[data-v-6c4bb8c9]{display:flex;align-items:center;gap:15px;padding:12px 16px;background:#fff;cursor:pointer;transition:all .2s;border-bottom:1px solid #e5e7eb}.group-item[data-v-6c4bb8c9]:last-child{border-bottom:none}.group-item[data-v-6c4bb8c9]:hover{background:#f3f4f6}.item-avatar img[data-v-6c4bb8c9]{width:50px;height:50px}.item-avatar .avatar-placeholder[data-v-6c4bb8c9]{width:50px;height:50px;font-size:1.2rem}.item-badges[data-v-6c4bb8c9]{display:flex;gap:5px}@media (max-width: 768px){.groups-page[data-v-6c4bb8c9]{padding:15px}.page-header[data-v-6c4bb8c9]{flex-direction:column;align-items:flex-start}.header-actions[data-v-6c4bb8c9]{width:100%;justify-content:space-between}.groups-grid[data-v-6c4bb8c9]{grid-template-columns:1fr}.btn-primary span[data-v-6c4bb8c9]{display:none}} diff --git a/src/assets/frontend/assets/groups.js b/src/assets/frontend/assets/groups.js new file mode 100644 index 00000000..441d77f8 --- /dev/null +++ b/src/assets/frontend/assets/groups.js @@ -0,0 +1 @@ +import{d as ee,u as se,r as P,c as z,w as V,o as ae,a as J,b as te,p as A,_ as oe,e as n,f as a,g as b,h as ne,i as ie,j as le,t as d,n as B,k as M,l as L,v as re,m as Q,F as U,q as W,s as i}from"./index.js";const ue=ee({setup(){const s=se(),e=te(),h=s.params.token,y=P([]),T=P({}),N=P(!1),E=P(""),t=P(""),C=P("card"),p=P(1),$=P(24),G=z(()=>{if(!t.value)return y.value;const o=t.value.toLowerCase();return y.value.filter(r=>{var g;return((g=r.Name)==null?void 0:g.toLowerCase().includes(o))||r.JID.toLowerCase().includes(o)})}),w=z(()=>Math.ceil(G.value.length/$.value)||1),q=z(()=>{const o=(p.value-1)*$.value,r=o+$.value;return G.value.slice(o,r)});async function S(){var o,r,g;N.value=!0,E.value="";try{const m=((o=(await J.get(`/api/groups/getall?token=${encodeURIComponent(h)}`)).data)==null?void 0:o.groups)||[];m.sort((v,R)=>{const D=v.Name||"",l=R.Name||"";return D.localeCompare(l)}),y.value=m,H(m.slice(0,20)),K()}catch(u){E.value=((g=(r=u==null?void 0:u.response)==null?void 0:r.data)==null?void 0:g.result)||(u==null?void 0:u.message)||"Erro ao carregar grupos"}finally{N.value=!1}}V([t,$],()=>{p.value=1}),V([G,w],()=>{p.value>w.value&&(p.value=w.value),p.value<1&&(p.value=1)});function F(o){o>=1&&o<=w.value&&(p.value=o)}function j(){p.value1&&p.value--}async function H(o){var r;for(const g of o)try{const u=await J.get(`/api/picinfo/${encodeURIComponent(g.JID)}?token=${encodeURIComponent(h)}`);(r=u.data)!=null&&r.url&&(T.value[g.JID]=u.data.url)}catch{}}async function K(){var o,r,g,u,m;try{const R=((o=(await J.get(`/api/server/${h}/messages`)).data)==null?void 0:o.messages)||[],D={};for(const l of R){const c=(r=l.chat)==null?void 0:r.id;if(!(!c||!c.endsWith("@g.us"))&&!(l.type==="unhandled"||l.type==="revoked"||l.type==="system")&&((g=l.debug)==null?void 0:g.reason)!=="discard"&&!(!l.text&&!l.attachment&&!l.inreply)&&(!D[c]||new Date(l.timestamp)>new Date(D[c].timestamp))){let f=l.text||"";if(l.attachment){const k=l.attachment.mimetype||"";let I="";k.startsWith("image/")?I="📷 ":k.startsWith("video/")?I="🎥 ":k.startsWith("audio/")||l.type==="ptt"?I="🎵 ":k.includes("pdf")?I="📄 ":I="📎 ",f?f=I+f:k.startsWith("image/")?f="📷 Imagem":k.startsWith("video/")?f="🎥 Vídeo":k.startsWith("audio/")||l.type==="ptt"?f="🎵 Áudio":k.includes("pdf")?f="📄 PDF":f="📎 Arquivo"}if(l.type==="sticker"&&(f="🏷️ Sticker"),!f&&l.inreply&&(f="↩️ Resposta"),!f)continue;D[c]={timestamp:l.timestamp,senderName:((u=l.participant)==null?void 0:u.title)||((m=l.participant)==null?void 0:m.phone)||"Desconhecido",text:f}}}y.value=y.value.map(l=>({...l,lastMessage:D[l.JID]})),y.value.sort((l,c)=>l.lastMessage&&c.lastMessage?new Date(c.lastMessage.timestamp).getTime()-new Date(l.lastMessage.timestamp).getTime():l.lastMessage?-1:c.lastMessage?1:(l.Name||"").localeCompare(c.Name||""))}catch{}}function X(o){delete T.value[o]}function Y(o){if(!o)return"";const r=new Date(o),g=new Date,u=g.getTime()-r.getTime(),m=24*60*60*1e3;return uv.trim()).filter(Boolean);try{await J.post("/api/groups/create",{title:o,participants:g,token:h}),A("Grupo criado","success"),await S()}catch(v){A(((m=(u=v==null?void 0:v.response)==null?void 0:u.data)==null?void 0:m.result)||(v==null?void 0:v.message)||"Erro ao criar grupo","error")}}return ae(()=>{S()}),{token:h,groups:y,groupPictures:T,loading:N,error:E,searchQuery:t,viewMode:C,filteredGroups:G,displayGroups:q,currentPage:p,totalPages:w,pageSize:$,createGroup:x,load:S,goToGroup:_,goToPage:F,nextPage:j,prevPage:O,handleImageError:X,formatTime:Y,truncateMessage:Z}}}),de={class:"groups-page"},pe={class:"page-header"},ge={class:"header-left"},me={key:0,class:"group-count"},fe={class:"header-actions"},ve={class:"view-toggle"},ce={class:"search-bar"},be={key:0,class:"pagination-controls"},ye=["disabled"],ke=["disabled"],Pe={class:"page-info"},he=["disabled"],Ce=["disabled"],Me=["disabled"],we={key:1,class:"loading-container"},De={key:2,class:"error-box"},Ie={key:3,class:"empty-state"},Ee={key:0},$e={key:1},Te={key:4,class:"groups-grid"},Ne=["onClick"],Ge={class:"card-avatar"},Je=["src","alt","onError"],Se={key:1,class:"avatar-placeholder"},Re={class:"card-content"},ze={class:"card-header"},Be={class:"group-name"},Le={key:0,class:"message-time"},Ve={class:"card-body"},Ae={key:0,class:"last-message"},Qe={class:"sender-name"},Ue={key:1,class:"last-message empty"},We={class:"card-footer"},qe={class:"participants-count"},Fe={key:0,class:"badge badge-announce",title:"Apenas admins podem enviar"},je={key:1,class:"badge badge-community",title:"Comunidade"},Oe={key:5,class:"groups-list"},He=["onClick"],Ke={class:"item-avatar"},Xe=["src","alt","onError"],Ye={key:1,class:"avatar-placeholder"},Ze={class:"item-content"},_e={class:"item-header"},xe={class:"group-name"},es={key:0,class:"message-time"},ss={class:"item-body"},as={key:0,class:"last-message"},ts={class:"sender-name"},os={key:1,class:"last-message empty"},ns={class:"participants-info"},is={class:"item-badges"},ls={key:0,class:"badge badge-announce",title:"Apenas admins podem enviar"},rs={key:1,class:"badge badge-community",title:"Comunidade"},us={key:6,class:"pagination-controls"},ds=["disabled"],ps=["disabled"],gs={class:"page-info"},ms=["disabled"],fs=["disabled"],vs=["disabled"];function cs(s,e,h,y,T,N){const E=le("router-link");return i(),n("div",de,[a("div",pe,[a("div",ge,[ne(E,{to:`/server/${s.token}`,class:"back-btn"},{default:ie(()=>[...e[16]||(e[16]=[a("i",{class:"fa fa-arrow-left"},null,-1)])]),_:1},8,["to"]),e[17]||(e[17]=a("h1",null,"Grupos",-1)),s.groups.length>0?(i(),n("span",me,"("+d(s.groups.length)+")",1)):b("",!0)]),a("div",fe,[a("div",ve,[a("button",{class:B(["toggle-btn",{active:s.viewMode==="card"}]),onClick:e[0]||(e[0]=t=>s.viewMode="card"),title:"Modo Card"},[...e[18]||(e[18]=[a("i",{class:"fa fa-th-large"},null,-1)])],2),a("button",{class:B(["toggle-btn",{active:s.viewMode==="list"}]),onClick:e[1]||(e[1]=t=>s.viewMode="list"),title:"Modo Lista"},[...e[19]||(e[19]=[a("i",{class:"fa fa-list"},null,-1)])],2)]),a("button",{onClick:e[2]||(e[2]=(...t)=>s.load&&s.load(...t)),class:"btn-icon",title:"Atualizar"},[a("i",{class:B(["fa fa-refresh",{"fa-spin":s.loading}])},null,2)]),a("button",{onClick:e[3]||(e[3]=(...t)=>s.createGroup&&s.createGroup(...t)),class:"btn-primary"},[...e[20]||(e[20]=[a("i",{class:"fa fa-plus me-2"},null,-1),M("Criar grupo ",-1)])])])]),a("div",ce,[e[22]||(e[22]=a("i",{class:"fa fa-search"},null,-1)),L(a("input",{"onUpdate:modelValue":e[4]||(e[4]=t=>s.searchQuery=t),type:"text",placeholder:"Pesquisar grupos...",class:"search-input"},null,512),[[re,s.searchQuery]]),s.searchQuery?(i(),n("button",{key:0,onClick:e[5]||(e[5]=t=>s.searchQuery=""),class:"clear-search"},[...e[21]||(e[21]=[a("i",{class:"fa fa-times"},null,-1)])])):b("",!0)]),s.groups.length>0?(i(),n("div",be,[a("button",{onClick:e[6]||(e[6]=t=>s.goToPage(1)),disabled:s.currentPage===1||s.loading,class:"btn-page"},[...e[23]||(e[23]=[a("i",{class:"fa fa-angle-double-left"},null,-1)])],8,ye),a("button",{onClick:e[7]||(e[7]=(...t)=>s.prevPage&&s.prevPage(...t)),disabled:s.currentPage===1||s.loading,class:"btn-page"},[...e[24]||(e[24]=[a("i",{class:"fa fa-angle-left"},null,-1)])],8,ke),a("span",Pe,"Página "+d(s.currentPage)+" de "+d(s.totalPages),1),a("button",{onClick:e[8]||(e[8]=(...t)=>s.nextPage&&s.nextPage(...t)),disabled:s.currentPage>=s.totalPages||s.loading,class:"btn-page"},[...e[25]||(e[25]=[a("i",{class:"fa fa-angle-right"},null,-1)])],8,he),a("button",{onClick:e[9]||(e[9]=t=>s.goToPage(s.totalPages)),disabled:s.currentPage>=s.totalPages||s.loading,class:"btn-page"},[...e[26]||(e[26]=[a("i",{class:"fa fa-angle-double-right"},null,-1)])],8,Ce),L(a("select",{"onUpdate:modelValue":e[10]||(e[10]=t=>s.pageSize=t),class:"page-size-select",disabled:s.loading},[...e[27]||(e[27]=[a("option",{value:5},"5 por página",-1),a("option",{value:10},"10 por página",-1),a("option",{value:15},"15 por página",-1),a("option",{value:25},"25 por página",-1),a("option",{value:50},"50 por página",-1),a("option",{value:100},"100 por página",-1),a("option",{value:200},"200 por página",-1)])],8,Me),[[Q,s.pageSize,void 0,{number:!0}]])])):b("",!0),s.loading?(i(),n("div",we,[...e[28]||(e[28]=[a("div",{class:"loading-spinner"},null,-1),a("p",null,"Carregando grupos...",-1)])])):s.error?(i(),n("div",De,[e[29]||(e[29]=a("i",{class:"fa fa-exclamation-triangle"},null,-1)),M(" "+d(s.error),1)])):s.filteredGroups.length===0?(i(),n("div",Ie,[e[30]||(e[30]=a("i",{class:"fa fa-users"},null,-1)),s.searchQuery?(i(),n("p",Ee,'Nenhum grupo encontrado para "'+d(s.searchQuery)+'"',1)):(i(),n("p",$e,"Nenhum grupo encontrado"))])):s.viewMode==="card"?(i(),n("div",Te,[(i(!0),n(U,null,W(s.displayGroups,t=>{var C;return i(),n("div",{key:t.JID,class:"group-card",onClick:p=>s.goToGroup(t.JID)},[a("div",Ge,[s.groupPictures[t.JID]?(i(),n("img",{key:0,src:s.groupPictures[t.JID],alt:t.Name,onError:p=>s.handleImageError(t.JID)},null,40,Je)):(i(),n("div",Se,[...e[31]||(e[31]=[a("i",{class:"fa fa-users"},null,-1)])]))]),a("div",Re,[a("div",ze,[a("h3",Be,d(t.Name||"Grupo sem nome"),1),t.lastMessage?(i(),n("span",Le,d(s.formatTime(t.lastMessage.timestamp)),1)):b("",!0)]),a("div",Ve,[t.lastMessage?(i(),n("p",Ae,[a("span",Qe,d(t.lastMessage.senderName)+":",1),M(" "+d(s.truncateMessage(t.lastMessage.text)),1)])):(i(),n("p",Ue,[...e[32]||(e[32]=[a("i",{class:"fa fa-comment-o me-1"},null,-1),M("Sem mensagens recentes ",-1)])]))]),a("div",We,[a("span",qe,[e[33]||(e[33]=a("i",{class:"fa fa-user me-1"},null,-1)),M(d(((C=t.Participants)==null?void 0:C.length)||0),1)]),t.IsAnnounce?(i(),n("span",Fe,[...e[34]||(e[34]=[a("i",{class:"fa fa-bullhorn"},null,-1)])])):b("",!0),t.IsParent?(i(),n("span",je,[...e[35]||(e[35]=[a("i",{class:"fa fa-sitemap"},null,-1)])])):b("",!0)])])],8,Ne)}),128))])):(i(),n("div",Oe,[(i(!0),n(U,null,W(s.displayGroups,t=>{var C;return i(),n("div",{key:t.JID,class:"group-item",onClick:p=>s.goToGroup(t.JID)},[a("div",Ke,[s.groupPictures[t.JID]?(i(),n("img",{key:0,src:s.groupPictures[t.JID],alt:t.Name,onError:p=>s.handleImageError(t.JID)},null,40,Xe)):(i(),n("div",Ye,[...e[36]||(e[36]=[a("i",{class:"fa fa-users"},null,-1)])]))]),a("div",Ze,[a("div",_e,[a("h3",xe,d(t.Name||"Grupo sem nome"),1),t.lastMessage?(i(),n("span",es,d(s.formatTime(t.lastMessage.timestamp)),1)):b("",!0)]),a("div",ss,[t.lastMessage?(i(),n("p",as,[a("span",ts,d(t.lastMessage.senderName)+":",1),M(" "+d(s.truncateMessage(t.lastMessage.text)),1)])):(i(),n("p",os,[a("span",ns,[e[37]||(e[37]=a("i",{class:"fa fa-user me-1"},null,-1)),M(d(((C=t.Participants)==null?void 0:C.length)||0)+" participantes ",1)])]))])]),a("div",is,[t.IsAnnounce?(i(),n("span",ls,[...e[38]||(e[38]=[a("i",{class:"fa fa-bullhorn"},null,-1)])])):b("",!0),t.IsParent?(i(),n("span",rs,[...e[39]||(e[39]=[a("i",{class:"fa fa-sitemap"},null,-1)])])):b("",!0)])],8,He)}),128))])),s.totalPages>1?(i(),n("div",us,[a("button",{onClick:e[11]||(e[11]=t=>s.goToPage(1)),disabled:s.currentPage===1||s.loading,class:"btn-page"},[...e[40]||(e[40]=[a("i",{class:"fa fa-angle-double-left"},null,-1)])],8,ds),a("button",{onClick:e[12]||(e[12]=(...t)=>s.prevPage&&s.prevPage(...t)),disabled:s.currentPage===1||s.loading,class:"btn-page"},[...e[41]||(e[41]=[a("i",{class:"fa fa-angle-left"},null,-1)])],8,ps),a("span",gs,"Página "+d(s.currentPage)+" de "+d(s.totalPages),1),a("button",{onClick:e[13]||(e[13]=(...t)=>s.nextPage&&s.nextPage(...t)),disabled:s.currentPage>=s.totalPages||s.loading,class:"btn-page"},[...e[42]||(e[42]=[a("i",{class:"fa fa-angle-right"},null,-1)])],8,ms),a("button",{onClick:e[14]||(e[14]=t=>s.goToPage(s.totalPages)),disabled:s.currentPage>=s.totalPages||s.loading,class:"btn-page"},[...e[43]||(e[43]=[a("i",{class:"fa fa-angle-double-right"},null,-1)])],8,fs),L(a("select",{"onUpdate:modelValue":e[15]||(e[15]=t=>s.pageSize=t),class:"page-size-select",disabled:s.loading},[...e[44]||(e[44]=[a("option",{value:5},"5 por página",-1),a("option",{value:10},"10 por página",-1),a("option",{value:15},"15 por página",-1),a("option",{value:25},"25 por página",-1),a("option",{value:50},"50 por página",-1),a("option",{value:100},"100 por página",-1),a("option",{value:200},"200 por página",-1)])],8,vs),[[Q,s.pageSize,void 0,{number:!0}]])])):b("",!0)])}const ys=oe(ue,[["render",cs],["__scopeId","data-v-6c4bb8c9"]]);export{ys as default}; diff --git a/src/assets/frontend/assets/index.css b/src/assets/frontend/assets/index.css new file mode 100644 index 00000000..254ea0ae --- /dev/null +++ b/src/assets/frontend/assets/index.css @@ -0,0 +1,5 @@ +@charset "UTF-8";.toast[data-v-e78c0add]{min-width:220px}.navbar-logo{height:32px;width:auto}.app-footer{margin-top:2rem;padding:1rem 0;border-top:1px solid #e9ecef;background:#f8f9fa}.footer-content{display:flex;justify-content:space-between;align-items:center;max-width:1200px;margin:0 auto;padding:0 1rem}.footer-left{display:flex;align-items:center;gap:.5rem;color:#6c757d;font-size:.875rem}.company-link{color:var(--branding-primary, #7C3AED);text-decoration:none}.company-link:hover{text-decoration:underline}.footer-right{display:flex;align-items:center}.version-badge{background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;padding:.25rem .75rem;border-radius:1rem;font-size:.75rem;font-weight:600}.offcanvas .nav-link{padding:.75rem 1rem;color:#333;font-size:1rem}.offcanvas .nav-link:hover{background:#f8f9fa}@media (max-width: 991.98px){.offcanvas{width:100%!important}}@media (max-width: 768px){#app.container{max-width:100%;padding-left:0;padding-right:0;padding-top:0}header.mb-4{margin-bottom:0!important;position:sticky;top:0;z-index:1000}.navbar.rounded{border-radius:0!important}.footer-content{flex-direction:column;gap:.5rem;text-align:center}}.home-page[data-v-cec6a771]{max-width:1400px;margin:0 auto}.page-header[data-v-cec6a771]{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px;flex-wrap:wrap;gap:16px}.header-content h1[data-v-cec6a771]{font-size:28px;font-weight:700;color:#111827;margin:0 0 4px}.header-content p[data-v-cec6a771]{color:#6b7280;margin:0}.header-actions[data-v-cec6a771],.desktop-controls[data-v-cec6a771]{display:flex;align-items:center;gap:12px}.search-box[data-v-cec6a771]{display:flex;align-items:center;gap:8px;background:#fff;border:1px solid #e5e7eb;padding:6px 8px;border-radius:8px}.search-input[data-v-cec6a771]{border:none;outline:none;min-width:220px}.search-clear[data-v-cec6a771]{background:transparent;border:none;color:#9ca3af;cursor:pointer}.no-results[data-v-cec6a771]{text-align:center;padding:40px;color:#6b7280}.view-toggle[data-v-cec6a771]{display:flex;background:#f3f4f6;border-radius:8px;overflow:hidden}.view-btn[data-v-cec6a771]{padding:8px 12px;border:none;background:transparent;color:#6b7280;cursor:pointer;transition:all .2s}.view-btn[data-v-cec6a771]:hover{background:#e5e7eb}.view-btn.active[data-v-cec6a771]{background:var(--branding-primary, #7C3AED);color:#fff}.btn-add[data-v-cec6a771]{display:flex;align-items:center;gap:8px;padding:12px 20px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border-radius:12px;text-decoration:none;font-weight:600;transition:all .2s}.btn-add[data-v-cec6a771]:hover{transform:translateY(-2px);box-shadow:0 8px 16px #7c3aed40}.stats-bar[data-v-cec6a771]{display:flex;gap:16px;margin-bottom:24px;flex-wrap:wrap}.stat-item[data-v-cec6a771]{display:flex;flex-direction:column;align-items:center;padding:16px 24px;background:#fff;border-radius:12px;box-shadow:0 2px 4px #0000000d}.stat-value[data-v-cec6a771]{font-size:28px;font-weight:700;color:#111827}.stat-label[data-v-cec6a771]{font-size:13px;color:#6b7280}.stat-item.connected .stat-value[data-v-cec6a771]{color:var(--branding-primary, #7C3AED)}.stat-item.disconnected .stat-value[data-v-cec6a771]{color:#6b7280}.loading-state[data-v-cec6a771]{text-align:center;padding:60px 0}.spinner-large[data-v-cec6a771]{width:50px;height:50px;border:4px solid #e5e7eb;border-top-color:var(--branding-primary, #7C3AED);border-radius:50%;animation:spin-cec6a771 1s linear infinite;margin:0 auto 16px}.spinner-small[data-v-cec6a771]{width:18px;height:18px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin-cec6a771 .8s linear infinite}@keyframes spin-cec6a771{to{transform:rotate(360deg)}}.loading-state p[data-v-cec6a771]{color:#6b7280}.error-box[data-v-cec6a771]{display:flex;align-items:center;gap:10px;padding:16px 20px;background:#fef2f2;border:1px solid #fecaca;border-radius:12px;color:#dc2626}.retry-btn[data-v-cec6a771]{margin-left:auto;padding:8px 16px;background:#fff;border:1px solid #dc2626;border-radius:8px;color:#dc2626;font-weight:600;cursor:pointer}.retry-btn[data-v-cec6a771]:hover{background:#fef2f2}.empty-state[data-v-cec6a771]{text-align:center;padding:60px 20px;background:#fff;border-radius:20px;box-shadow:0 4px 6px #0000000d}.empty-icon[data-v-cec6a771]{color:#d1d5db;margin-bottom:20px}.empty-state h2[data-v-cec6a771]{font-size:24px;font-weight:700;color:#111827;margin:0 0 8px}.empty-state p[data-v-cec6a771]{color:#6b7280;margin:0 0 24px}.btn-primary-large[data-v-cec6a771]{display:inline-flex;align-items:center;gap:10px;padding:16px 32px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border-radius:14px;text-decoration:none;font-size:18px;font-weight:600;transition:all .2s}.btn-primary-large[data-v-cec6a771]:hover{transform:translateY(-2px);box-shadow:0 10px 20px #7c3aed40}.servers-table-wrapper[data-v-cec6a771]{background:#fff;border-radius:16px;box-shadow:0 2px 4px #0000000d}.servers-table[data-v-cec6a771]{width:100%;border-collapse:collapse}.servers-table th[data-v-cec6a771]{background:#f9fafb;padding:14px 16px;text-align:left;font-size:12px;font-weight:600;color:#6b7280;text-transform:uppercase;letter-spacing:.5px;border-bottom:1px solid #e5e7eb}.servers-table td[data-v-cec6a771]{padding:14px 16px;border-bottom:1px solid #f3f4f6;vertical-align:middle}.servers-table tbody tr[data-v-cec6a771]:hover{background:#f9fafb}.status-cell[data-v-cec6a771]{text-align:center;width:60px}.phone-cell[data-v-cec6a771]{font-weight:500;color:#111827}.token-cell[data-v-cec6a771]{font-family:monospace}.token-code[data-v-cec6a771]{cursor:pointer;padding:4px 8px;background:#f3f4f6;border-radius:6px;font-size:12px;transition:all .2s}.token-code[data-v-cec6a771]:hover{background:#e5e7eb}.token-code.truncated[data-v-cec6a771]{display:inline-block;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.connection-cell[data-v-cec6a771]{width:120px}.connection-badge[data-v-cec6a771]{display:inline-block;padding:4px 10px;border-radius:12px;font-size:11px;font-weight:600;text-transform:uppercase}.connection-badge.ready[data-v-cec6a771]{background:#f5efff;color:var(--branding-secondary, #5B21B6)}.connection-badge.connecting[data-v-cec6a771]{background:#fef3c7;color:#92400e}.connection-badge.unverified[data-v-cec6a771]{background:#fef2f2;color:#dc2626}.connection-badge.disconnected[data-v-cec6a771]{background:#f3f4f6;color:#6b7280}.dispatch-cell[data-v-cec6a771]{display:flex;align-items:center;justify-content:center;gap:6px}.dispatch-count[data-v-cec6a771]{font-weight:600}.actions-cell[data-v-cec6a771]{width:80px;text-align:center}.action-dropdown-btn[data-v-cec6a771]{width:36px;height:36px;display:flex;align-items:center;justify-content:center;border:none;background:#f3f4f6;border-radius:8px;color:#6b7280;cursor:pointer;transition:all .2s}.action-dropdown-btn[data-v-cec6a771]:hover{background:var(--branding-primary, #7C3AED);color:#fff}.action-dropdown-btn[data-v-cec6a771]:disabled{opacity:.5;cursor:not-allowed}.dropdown-menu[data-v-cec6a771]{min-width:200px;padding:8px 0;border-radius:12px;box-shadow:0 10px 40px #00000026;border:1px solid #e5e7eb}.dropdown-item[data-v-cec6a771]{padding:10px 16px;font-size:14px;display:flex;align-items:center}.dropdown-item[data-v-cec6a771]:hover{background:#f3f4f6}.dropdown-item.active[data-v-cec6a771]{background:#7c3aed1a;color:var(--branding-primary, #7C3AED)}.dropdown-item i[data-v-cec6a771]{width:20px}.action-buttons[data-v-cec6a771]{display:flex;gap:6px;flex-wrap:wrap}.action-btn[data-v-cec6a771]{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;background:#f3f4f6;border-radius:6px;color:#6b7280;cursor:pointer;transition:all .2s;text-decoration:none}.action-btn[data-v-cec6a771]:hover{background:#e5e7eb;color:#374151}.action-btn.active[data-v-cec6a771]{background:var(--branding-primary, #7C3AED);color:#fff}.action-btn.success[data-v-cec6a771]{background:#dcfce7;color:#16a34a}.action-btn.success[data-v-cec6a771]:hover{background:#bbf7d0}.action-btn.danger[data-v-cec6a771]{background:#fef2f2;color:#dc2626}.action-btn.danger[data-v-cec6a771]:hover{background:#fecaca}.action-btn[data-v-cec6a771]:disabled{opacity:.5;cursor:not-allowed}.servers-grid[data-v-cec6a771]{display:grid;grid-template-columns:repeat(2,1fr);gap:20px}.server-card[data-v-cec6a771]{background:#fff;border-radius:16px;padding:20px;box-shadow:0 2px 4px #0000000d;border-left:4px solid #e5e7eb;transition:all .2s}.server-card[data-v-cec6a771]:hover{box-shadow:0 8px 16px #0000001a}.server-card.connected[data-v-cec6a771]{border-left-color:var(--branding-primary, #7C3AED)}.server-card.connecting[data-v-cec6a771]{border-left-color:#f59e0b}.server-card.disconnected[data-v-cec6a771]{border-left-color:#9ca3af}.server-header[data-v-cec6a771]{display:flex;align-items:center;gap:14px;margin-bottom:16px}.server-avatar[data-v-cec6a771]{width:52px;height:52px;border-radius:14px;display:flex;align-items:center;justify-content:center;color:#fff}.server-avatar.connected[data-v-cec6a771]{background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6))}.server-avatar.connecting[data-v-cec6a771]{background:linear-gradient(135deg,#f59e0b,#d97706)}.server-avatar.disconnected[data-v-cec6a771]{background:linear-gradient(135deg,#9ca3af,#6b7280)}.server-info h3[data-v-cec6a771]{font-size:16px;font-weight:600;color:#111827;margin:0 0 6px}.status-badge[data-v-cec6a771]{display:inline-block;padding:3px 10px;border-radius:12px;font-size:11px;font-weight:600;text-transform:uppercase}.status-badge.connected[data-v-cec6a771]{background:#f5efff;color:var(--branding-secondary, #5B21B6)}.status-badge.connecting[data-v-cec6a771]{background:#fef3c7;color:#92400e}.status-badge.disconnected[data-v-cec6a771]{background:#f3f4f6;color:#6b7280}.server-details[data-v-cec6a771]{margin-bottom:16px;padding:12px;background:#f9fafb;border-radius:10px}.detail-row[data-v-cec6a771]{display:flex;justify-content:space-between;align-items:center;padding:4px 0}.detail-label[data-v-cec6a771]{font-size:13px;color:#6b7280}.detail-value[data-v-cec6a771]{font-size:13px;color:#111827;font-weight:500}.flags-row[data-v-cec6a771]{display:flex;gap:4px}.flag-badge[data-v-cec6a771]{width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:4px;background:#e5e7eb;color:#9ca3af;font-size:11px}.flag-badge.state-unset[data-v-cec6a771]{background:#f3f4f6;color:#9ca3af}.flag-badge.state-off[data-v-cec6a771]{background:#fee2e2;color:#dc2626}.flag-badge.state-on[data-v-cec6a771]{background:#dcfce7;color:#16a34a}.flag-badge.active[data-v-cec6a771]{background:var(--branding-primary, #7C3AED);color:#fff}.server-actions[data-v-cec6a771]{display:flex;flex-wrap:wrap;gap:8px}.btn-action[data-v-cec6a771]{display:flex;align-items:center;gap:6px;padding:8px 12px;background:#f3f4f6;border:none;border-radius:8px;text-decoration:none;font-size:13px;font-weight:500;color:#374151;transition:all .2s;cursor:pointer}.btn-action[data-v-cec6a771]:hover{background:#e5e7eb}.btn-action.primary[data-v-cec6a771]{background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff}.btn-action.primary[data-v-cec6a771]:hover{box-shadow:0 4px 8px #7c3aed40}.btn-action.success[data-v-cec6a771]{background:#dcfce7;color:#16a34a}.btn-action.success[data-v-cec6a771]:hover{background:#bbf7d0}.btn-action.danger[data-v-cec6a771]{background:#fef2f2;color:#dc2626}.btn-action.danger[data-v-cec6a771]:hover{background:#fecaca}.btn-action.active[data-v-cec6a771]{background:var(--branding-primary, #7C3AED);color:#fff}.btn-action[data-v-cec6a771]:disabled{opacity:.5;cursor:not-allowed}.quick-toggles[data-v-cec6a771]{display:flex;gap:8px;margin-bottom:12px;padding:8px;background:#f8fafc;border-radius:8px;justify-content:center}.toggle-btn[data-v-cec6a771]{width:36px;height:36px;border:1px solid #e5e7eb;border-radius:8px;background:#fff;color:#9ca3af;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.toggle-btn[data-v-cec6a771]:hover{background:#f3f4f6;color:#6b7280}.toggle-btn.active[data-v-cec6a771]{background:#10b981;color:#fff;border-color:#10b981}.toggle-btn[data-v-cec6a771]:disabled{opacity:.5;cursor:not-allowed}.btn-action.warning[data-v-cec6a771]{background:#f59e0b;color:#fff}.btn-action.warning[data-v-cec6a771]:hover{background:#d97706}.text-success[data-v-cec6a771]{color:#16a34a}.text-warning[data-v-cec6a771]{color:#f59e0b}.text-muted[data-v-cec6a771]{color:#9ca3af}.ms-1[data-v-cec6a771]{margin-left:4px}.pagination-bar[data-v-cec6a771]{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;background:var(--card-bg);border-radius:8px;margin-top:20px;gap:16px;flex-wrap:wrap}.pagination-info[data-v-cec6a771]{color:var(--text-secondary);font-size:.9rem}.pagination-controls[data-v-cec6a771]{display:flex;align-items:center;gap:24px}.page-size-selector[data-v-cec6a771]{display:flex;align-items:center;gap:8px}.page-size-selector label[data-v-cec6a771]{color:var(--text-secondary);font-size:.9rem}.page-size-selector select[data-v-cec6a771]{padding:6px 12px;border-radius:6px;border:1px solid var(--border-color);background:var(--input-bg);color:var(--text-primary);font-size:.9rem;cursor:pointer}.page-nav[data-v-cec6a771]{display:flex;align-items:center;gap:12px}.page-btn[data-v-cec6a771]{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:1px solid var(--border-color);border-radius:6px;background:var(--input-bg);color:var(--text-primary);cursor:pointer;transition:all .2s}.page-btn[data-v-cec6a771]:hover:not(:disabled){background:var(--hover-bg);border-color:var(--primary-color)}.page-btn[data-v-cec6a771]:disabled{opacity:.4;cursor:not-allowed}.page-indicator[data-v-cec6a771]{color:var(--text-secondary);font-size:.9rem;min-width:100px;text-align:center}@media (max-width: 768px){.hide-mobile[data-v-cec6a771]{display:none!important}.home-page[data-v-cec6a771]{padding:0;margin:0}.page-header[data-v-cec6a771]{position:sticky;top:0;z-index:100;background:#fff;margin:0;padding:12px 16px;border-radius:0;box-shadow:0 2px 4px #0000001a}.header-content h1[data-v-cec6a771]{font-size:20px}.mobile-controls[data-v-cec6a771]{display:flex;align-items:center;gap:8px;padding:12px 16px;background:#f9fafb;position:sticky;top:60px;z-index:99}.mobile-controls .search-box[data-v-cec6a771]{flex:1}.mobile-controls .search-input[data-v-cec6a771]{min-width:0;width:100%}.btn-add-mobile[data-v-cec6a771]{display:flex;align-items:center;justify-content:center;width:40px;height:40px;background:var(--branding-primary, #7C3AED);color:#fff;border-radius:8px;text-decoration:none;flex-shrink:0}.servers-table-wrapper[data-v-cec6a771]{overflow-x:auto}.servers-table[data-v-cec6a771]{min-width:800px}.servers-grid[data-v-cec6a771]{grid-template-columns:1fr;padding:0 16px}.stats-bar[data-v-cec6a771]{margin:0 16px 16px}.pagination-bar[data-v-cec6a771]{flex-direction:column;align-items:stretch;text-align:center;margin:16px}.pagination-controls[data-v-cec6a771]{justify-content:center;flex-wrap:wrap}.desktop-controls[data-v-cec6a771],.btn-add span[data-v-cec6a771]{display:none}.btn-add[data-v-cec6a771]{padding:10px;border-radius:8px}}@media (min-width: 769px){.mobile-controls[data-v-cec6a771],.btn-add-mobile[data-v-cec6a771]{display:none}}.account-page[data-v-4be79a22]{max-width:800px;margin:0 auto}.page-header[data-v-4be79a22]{margin-bottom:24px}.page-header h1[data-v-4be79a22]{display:flex;align-items:center;gap:12px;font-size:28px;font-weight:700;color:#111827;margin:0 0 4px}.page-header h1 i[data-v-4be79a22]{color:var(--branding-primary, #7C3AED)}.page-header p[data-v-4be79a22]{color:#6b7280;margin:0}.error-box[data-v-4be79a22]{display:flex;align-items:center;gap:10px;padding:16px 20px;background:#fef2f2;border:1px solid #fecaca;border-radius:12px;color:#dc2626;margin-bottom:24px}.loading-state[data-v-4be79a22]{text-align:center;padding:60px 0}.spinner[data-v-4be79a22]{width:40px;height:40px;border:4px solid #e5e7eb;border-top-color:var(--branding-primary, #7C3AED);border-radius:50%;animation:spin-4be79a22 1s linear infinite;margin:0 auto 16px}@keyframes spin-4be79a22{to{transform:rotate(360deg)}}.account-content[data-v-4be79a22]{display:flex;flex-direction:column;gap:20px}.info-card[data-v-4be79a22]{background:#fff;border-radius:16px;box-shadow:0 2px 4px #0000000d;overflow:hidden}.card-header[data-v-4be79a22]{display:flex;align-items:center;gap:10px;padding:16px 20px;background:#f9fafb;border-bottom:1px solid #e5e7eb}.card-header i[data-v-4be79a22]{color:var(--branding-primary, #7C3AED)}.card-header h2[data-v-4be79a22]{font-size:16px;font-weight:600;color:#111827;margin:0}.card-body[data-v-4be79a22]{padding:20px}.info-row[data-v-4be79a22]{display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid #f3f4f6}.info-row[data-v-4be79a22]:last-child{border-bottom:none}.info-label[data-v-4be79a22]{font-size:14px;color:#6b7280}.info-value[data-v-4be79a22]{font-size:14px;font-weight:500;color:#111827}.info-value code[data-v-4be79a22]{background:#f3f4f6;padding:4px 8px;border-radius:6px;font-family:monospace;font-size:13px}.badge[data-v-4be79a22]{display:inline-block;padding:4px 10px;border-radius:12px;font-size:11px;font-weight:600;text-transform:uppercase}.badge-admin[data-v-4be79a22]{background:#fee2e2;color:#dc2626}.badge-user[data-v-4be79a22]{background:#f5efff;color:var(--branding-secondary, #5B21B6)}.badge-success[data-v-4be79a22]{background:#dcfce7;color:#16a34a}.branding-preview[data-v-4be79a22]{display:flex;gap:12px;margin-bottom:16px}.color-swatch[data-v-4be79a22]{width:80px;height:60px;border-radius:8px;display:flex;align-items:flex-end;justify-content:center;padding-bottom:6px;color:#fff;font-size:10px;font-weight:600;text-shadow:0 1px 2px rgba(0,0,0,.3)}.logo-preview[data-v-4be79a22]{max-height:40px;width:auto}.master-key[data-v-4be79a22]{display:flex;align-items:center;gap:8px;background:#f3f4f6;padding:8px 12px;border-radius:8px;font-family:monospace;font-size:13px;cursor:pointer}.toggle-btn[data-v-4be79a22]{padding:4px;background:none;border:none;color:#6b7280;cursor:pointer}.toggle-btn[data-v-4be79a22]:hover{color:#374151}.actions-section[data-v-4be79a22]{display:flex;gap:12px;justify-content:flex-end;margin-top:8px}.btn-primary[data-v-4be79a22]{display:flex;align-items:center;gap:8px;padding:12px 20px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s}.btn-primary[data-v-4be79a22]:hover{transform:translateY(-2px);box-shadow:0 4px 12px #7c3aed40}.btn-secondary[data-v-4be79a22]{display:flex;align-items:center;gap:8px;padding:10px 16px;background:#f3f4f6;color:#374151;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s}.btn-secondary[data-v-4be79a22]:hover{background:#e5e7eb}[data-v-d8fc6c09]:root{--branding-primary: #7C3AED;--branding-secondary: #5B21B6;--branding-accent: #8B5CF6}.login-wrapper[data-v-d8fc6c09]{min-height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#1a1a2e,#16213e,#0f3460);position:relative;overflow:hidden;padding:20px}.login-bg[data-v-d8fc6c09]{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden}.login-bg-shape[data-v-d8fc6c09]{position:absolute;border-radius:50%;opacity:.1;animation:float-d8fc6c09 20s ease-in-out infinite}.shape-1[data-v-d8fc6c09]{width:600px;height:600px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));top:-200px;right:-200px}.shape-2[data-v-d8fc6c09]{width:400px;height:400px;background:linear-gradient(135deg,var(--branding-accent, #8B5CF6),var(--branding-primary, #7C3AED));bottom:-150px;left:-150px;animation-delay:-5s}.shape-3[data-v-d8fc6c09]{width:300px;height:300px;background:linear-gradient(135deg,var(--branding-secondary, #5B21B6),var(--branding-primary, #7C3AED));top:50%;left:50%;transform:translate(-50%,-50%);animation-delay:-10s}@keyframes float-d8fc6c09{0%,to{transform:translate(0) rotate(0)}25%{transform:translate(20px,-20px) rotate(5deg)}50%{transform:translate(-10px,20px) rotate(-5deg)}75%{transform:translate(-20px,-10px) rotate(3deg)}}.login-container[data-v-d8fc6c09]{display:flex;max-width:1000px;width:100%;background:#fffffff2;border-radius:24px;box-shadow:0 25px 50px -12px #0006;overflow:hidden;position:relative;z-index:1}.login-card[data-v-d8fc6c09]{flex:1;padding:48px;display:flex;flex-direction:column}.login-header[data-v-d8fc6c09]{text-align:center;margin-bottom:32px}.login-logo-wrapper[data-v-d8fc6c09]{margin-bottom:16px}.login-logo[data-v-d8fc6c09]{max-width:120px;height:auto}.login-logo-placeholder[data-v-d8fc6c09]{width:80px;height:80px;margin:0 auto 16px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));border-radius:20px;display:flex;align-items:center;justify-content:center;color:#fff}.login-title[data-v-d8fc6c09]{font-size:28px;font-weight:700;color:#1a1a2e;margin:0 0 8px}.login-subtitle[data-v-d8fc6c09]{font-size:14px;color:#64748b;margin:0}.login-warning[data-v-d8fc6c09]{display:flex;align-items:center;gap:8px;padding:12px 16px;background:#fef3c7;border:1px solid #f59e0b;border-radius:12px;color:#92400e;font-size:14px;margin-bottom:24px}.login-error[data-v-d8fc6c09]{display:flex;align-items:center;gap:8px;padding:12px 16px;background:#fef2f2;border:1px solid #ef4444;border-radius:12px;color:#dc2626;font-size:14px;margin-bottom:16px}.login-form[data-v-d8fc6c09]{flex:1}.form-group[data-v-d8fc6c09]{margin-bottom:20px}.form-group label[data-v-d8fc6c09]{display:block;font-size:14px;font-weight:600;color:#374151;margin-bottom:8px}.input-wrapper[data-v-d8fc6c09]{position:relative}.input-icon[data-v-d8fc6c09]{position:absolute;left:16px;top:50%;transform:translateY(-50%);color:#9ca3af}.form-input[data-v-d8fc6c09]{width:100%;padding:14px 16px 14px 48px;border:2px solid #e5e7eb;border-radius:12px;font-size:16px;transition:all .2s;background:#f9fafb}.form-input[data-v-d8fc6c09]:focus{outline:none;border-color:var(--branding-primary, #7C3AED);background:#fff;box-shadow:0 0 0 4px #25d3661a}.form-input[data-v-d8fc6c09]::placeholder{color:#9ca3af}.login-button[data-v-d8fc6c09]{width:100%;padding:16px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border:none;border-radius:12px;font-size:16px;font-weight:600;cursor:pointer;transition:all .2s;display:flex;align-items:center;justify-content:center;gap:8px}.login-button[data-v-d8fc6c09]:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 10px 20px #25d3664d}.login-button[data-v-d8fc6c09]:active:not(:disabled){transform:translateY(0)}.login-button[data-v-d8fc6c09]:disabled{opacity:.7;cursor:not-allowed}.setup-link[data-v-d8fc6c09]{text-align:center;margin-top:16px}.setup-link-text[data-v-d8fc6c09]{display:inline-flex;align-items:center;gap:6px;color:var(--branding-primary, #7C3AED);text-decoration:none;font-size:14px;font-weight:500;transition:all .2s}.setup-link-text[data-v-d8fc6c09]:hover{color:var(--branding-secondary, #5B21B6);text-decoration:underline}.spinner[data-v-d8fc6c09]{width:20px;height:20px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin-d8fc6c09 .8s linear infinite}@keyframes spin-d8fc6c09{to{transform:rotate(360deg)}}.login-footer[data-v-d8fc6c09]{text-align:center;margin-top:24px;font-size:12px;color:#9ca3af}.login-info[data-v-d8fc6c09]{flex:1;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));padding:48px;display:flex;align-items:center;justify-content:center;color:#fff}.info-content h2[data-v-d8fc6c09]{font-size:28px;font-weight:700;margin:0 0 16px}.info-content p[data-v-d8fc6c09]{font-size:16px;opacity:.9;line-height:1.6;margin:0 0 32px}.features[data-v-d8fc6c09]{display:flex;flex-direction:column;gap:16px}.feature[data-v-d8fc6c09]{display:flex;align-items:center;gap:12px;padding:12px 16px;background:#ffffff26;border-radius:12px;font-size:15px;font-weight:500}.feature svg[data-v-d8fc6c09]{flex-shrink:0}@media (max-width: 768px){.login-container[data-v-d8fc6c09]{flex-direction:column}.login-info[data-v-d8fc6c09]{display:none}.login-card[data-v-d8fc6c09]{padding:32px 24px}}.tri-state-toggle[data-v-83eb2759]{display:inline-flex;border-radius:8px;overflow:hidden;border:1px solid #e5e7eb;background:#f9fafb}.tri-state-toggle.disabled[data-v-83eb2759]{opacity:.6;pointer-events:none}.tri-state-toggle.state-off[data-v-83eb2759]{border-color:#fca5a5}.tri-state-toggle.state-on[data-v-83eb2759]{border-color:#86efac}.tri-btn[data-v-83eb2759]{display:flex;align-items:center;justify-content:center;width:36px;height:32px;border:none;background:transparent;color:#9ca3af;cursor:pointer;transition:all .2s ease}.tri-btn[data-v-83eb2759]:hover:not(:disabled){background:#e5e7eb}.tri-btn[data-v-83eb2759]:not(:last-child){border-right:1px solid #e5e7eb}.tri-btn.off.active[data-v-83eb2759]{background:#fee2e2;color:#dc2626}.tri-btn.default.active[data-v-83eb2759]{background:#f3f4f6;color:#6b7280}.tri-btn.on.active[data-v-83eb2759]{background:#dcfce7;color:#16a34a}.tri-btn i[data-v-83eb2759]{font-size:12px}.webhooks-page[data-v-ba92e7b0]{max-width:1000px;margin:0 auto}.back-link[data-v-ba92e7b0]{display:inline-flex;align-items:center;gap:6px;color:#6b7280;text-decoration:none;font-size:14px;margin-bottom:16px}.back-link[data-v-ba92e7b0]:hover{color:#374151}.page-header[data-v-ba92e7b0]{margin-bottom:24px}.page-header h1[data-v-ba92e7b0]{display:flex;align-items:center;gap:12px;font-size:28px;font-weight:700;color:#111827;margin:0 0 4px}.page-header h1 i[data-v-ba92e7b0]{color:var(--branding-primary, #7C3AED)}.page-header p[data-v-ba92e7b0]{color:#6b7280;margin:0}.error-box[data-v-ba92e7b0]{display:flex;align-items:center;gap:10px;padding:16px 20px;background:#fef2f2;border:1px solid #fecaca;border-radius:12px;color:#dc2626;margin-bottom:24px}.no-token-warning[data-v-ba92e7b0]{text-align:center;padding:60px 20px;background:#fffbeb;border:1px solid #fde68a;border-radius:16px}.no-token-warning .warning-icon[data-v-ba92e7b0]{width:80px;height:80px;margin:0 auto 20px;background:#fef3c7;border-radius:50%;display:flex;align-items:center;justify-content:center}.no-token-warning .warning-icon i[data-v-ba92e7b0]{font-size:40px;color:#f59e0b}.no-token-warning h2[data-v-ba92e7b0]{font-size:24px;font-weight:700;color:#92400e;margin:0 0 8px}.no-token-warning p[data-v-ba92e7b0]{color:#b45309;margin:0 0 24px}.no-token-warning .btn-primary[data-v-ba92e7b0]{display:inline-flex;align-items:center;gap:8px;padding:12px 24px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border-radius:10px;text-decoration:none;font-weight:600}.loading-state[data-v-ba92e7b0]{text-align:center;padding:60px 0}.spinner[data-v-ba92e7b0]{width:40px;height:40px;border:4px solid #e5e7eb;border-top-color:var(--branding-primary, #7C3AED);border-radius:50%;animation:spin-ba92e7b0 1s linear infinite;margin:0 auto 16px}@keyframes spin-ba92e7b0{to{transform:rotate(360deg)}}.webhooks-content[data-v-ba92e7b0]{display:flex;flex-direction:column;gap:24px}.add-card[data-v-ba92e7b0],.list-card[data-v-ba92e7b0]{background:#fff;border-radius:16px;box-shadow:0 2px 4px #0000000d;overflow:hidden}.card-header[data-v-ba92e7b0]{display:flex;align-items:center;gap:10px;padding:16px 20px;background:#f9fafb;border-bottom:1px solid #e5e7eb}.card-header i[data-v-ba92e7b0]{color:var(--branding-primary, #7C3AED)}.card-header h2[data-v-ba92e7b0]{font-size:16px;font-weight:600;color:#111827;margin:0}.count-badge[data-v-ba92e7b0]{margin-left:auto;background:var(--branding-primary, #7C3AED);color:#fff;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:600}.card-body[data-v-ba92e7b0]{padding:20px}.add-form[data-v-ba92e7b0]{display:flex;flex-direction:column;gap:16px}.form-row[data-v-ba92e7b0]{display:flex;gap:12px}.form-group[data-v-ba92e7b0]{display:flex;flex-direction:column;gap:6px}.form-group.flex-grow[data-v-ba92e7b0]{flex:1}.form-group label[data-v-ba92e7b0]{font-size:13px;font-weight:600;color:#374151}.form-input[data-v-ba92e7b0]{padding:10px 14px;border:2px solid #e5e7eb;border-radius:8px;font-size:14px;transition:all .2s}.form-input[data-v-ba92e7b0]:focus{outline:none;border-color:var(--branding-primary, #7C3AED);box-shadow:0 0 0 3px #7c3aed1a}.options-row[data-v-ba92e7b0]{gap:20px;flex-wrap:wrap}.checkbox-label[data-v-ba92e7b0]{display:flex;align-items:center;gap:6px;font-size:14px;color:#374151;cursor:pointer}.checkbox-label input[type=checkbox][data-v-ba92e7b0]{width:16px;height:16px;accent-color:var(--branding-primary, #7C3AED)}.btn-primary[data-v-ba92e7b0]{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:12px 20px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s;align-self:flex-start}.btn-primary[data-v-ba92e7b0]:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 4px 12px #7c3aed40}.btn-primary[data-v-ba92e7b0]:disabled{opacity:.6;cursor:not-allowed}.empty-state[data-v-ba92e7b0]{text-align:center;padding:40px 20px;color:#9ca3af}.empty-state i[data-v-ba92e7b0]{font-size:48px;margin-bottom:12px;display:block}.webhook-list[data-v-ba92e7b0]{display:flex;flex-direction:column;gap:12px}.webhook-item[data-v-ba92e7b0]{display:flex;flex-direction:column;gap:12px;padding:16px;background:#f9fafb;border-radius:12px;border:1px solid #e5e7eb}.item-header[data-v-ba92e7b0]{display:flex;align-items:flex-start;gap:16px}.item-info[data-v-ba92e7b0]{flex:1;min-width:0}.item-main[data-v-ba92e7b0]{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.webhook-url[data-v-ba92e7b0]{font-size:14px;color:#111827;word-break:break-all}.track-id[data-v-ba92e7b0]{font-size:12px;background:#e0e7ff;color:#4338ca;padding:2px 8px;border-radius:8px}.item-status[data-v-ba92e7b0]{margin-top:6px}.status-indicator[data-v-ba92e7b0]{display:inline-flex;align-items:center;gap:4px;font-size:12px;padding:2px 8px;border-radius:8px}.status-indicator.success[data-v-ba92e7b0]{background:#dcfce7;color:#16a34a}.status-indicator.error[data-v-ba92e7b0]{background:#fef2f2;color:#dc2626}.item-flags[data-v-ba92e7b0]{display:flex;gap:6px}.flag-btn[data-v-ba92e7b0]{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;background:#e5e7eb;border-radius:6px;color:#6b7280;cursor:pointer;transition:all .2s}.flag-btn[data-v-ba92e7b0]:hover{background:#d1d5db}.flag-btn.active[data-v-ba92e7b0]{background:var(--branding-primary, #7C3AED);color:#fff}.btn-delete[data-v-ba92e7b0]{width:36px;height:36px;display:flex;align-items:center;justify-content:center;border:none;background:#fef2f2;border-radius:8px;color:#dc2626;cursor:pointer;transition:all .2s}.btn-delete[data-v-ba92e7b0]:hover{background:#fecaca}.flag-btn.state-unset[data-v-ba92e7b0]{background:#f3f4f6;color:#9ca3af}.flag-btn.state-off[data-v-ba92e7b0]{background:#fee2e2;color:#dc2626}.flag-btn.state-on[data-v-ba92e7b0]{background:#dcfce7;color:#16a34a}.item-actions[data-v-ba92e7b0]{display:flex;gap:8px;flex-shrink:0}.btn-edit[data-v-ba92e7b0]{width:36px;height:36px;display:flex;align-items:center;justify-content:center;border:none;background:#e0e7ff;border-radius:8px;color:#4f46e5;cursor:pointer;transition:all .2s}.btn-edit[data-v-ba92e7b0]:hover{background:#c7d2fe}.item-extra[data-v-ba92e7b0]{display:flex;gap:8px;align-items:flex-start;padding:8px 12px;background:#f3f4f6;border-radius:8px;font-size:12px}.extra-label[data-v-ba92e7b0]{color:#6b7280;font-weight:600;flex-shrink:0}.extra-value[data-v-ba92e7b0]{color:#374151;font-family:Fira Code,Consolas,monospace;white-space:pre-wrap;word-break:break-all;max-height:100px;overflow-y:auto}.modal-overlay[data-v-ba92e7b0]{position:fixed;top:0;left:0;right:0;bottom:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;padding:20px}.modal-content.edit-modal[data-v-ba92e7b0]{background:#fff;border-radius:16px;width:100%;max-width:600px;max-height:90vh;overflow-y:auto;box-shadow:0 20px 50px #0003}.modal-header[data-v-ba92e7b0]{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid #e5e7eb}.modal-header h3[data-v-ba92e7b0]{display:flex;align-items:center;gap:10px;margin:0;font-size:18px;color:#111827}.modal-header h3 i[data-v-ba92e7b0]{color:var(--branding-primary, #7C3AED)}.modal-close[data-v-ba92e7b0]{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;background:#f3f4f6;border-radius:8px;color:#6b7280;cursor:pointer;transition:all .2s}.modal-close[data-v-ba92e7b0]:hover{background:#e5e7eb;color:#374151}.modal-body[data-v-ba92e7b0]{padding:24px}.modal-body .form-group[data-v-ba92e7b0]{margin-bottom:16px}.modal-body .form-input[data-v-ba92e7b0]{width:100%}.extra-textarea[data-v-ba92e7b0]{font-family:Fira Code,Consolas,monospace;font-size:13px;resize:vertical}.form-hint[data-v-ba92e7b0]{color:#6b7280;font-size:12px;margin-top:4px}.options-grid[data-v-ba92e7b0]{display:grid;grid-template-columns:repeat(2,1fr);gap:16px}.option-item[data-v-ba92e7b0]{display:flex;flex-direction:column;gap:6px}.option-item label[data-v-ba92e7b0]{font-size:13px;font-weight:600;color:#374151}.modal-actions[data-v-ba92e7b0]{display:flex;justify-content:flex-end;gap:12px;margin-top:24px;padding-top:16px;border-top:1px solid #e5e7eb}.btn-secondary[data-v-ba92e7b0]{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:12px 20px;background:#f3f4f6;color:#374151;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s}.btn-secondary[data-v-ba92e7b0]:hover{background:#e5e7eb}@media (max-width: 768px){.form-row[data-v-ba92e7b0]{flex-direction:column}.webhook-item[data-v-ba92e7b0]{flex-direction:column;align-items:stretch}.item-flags[data-v-ba92e7b0]{justify-content:center;padding-top:12px;border-top:1px solid #e5e7eb;margin-top:12px}.btn-delete[data-v-ba92e7b0]{position:absolute;top:12px;right:12px}.webhook-item[data-v-ba92e7b0]{position:relative;padding-right:56px}}.rabbitmq-page[data-v-7f963124]{max-width:1000px;margin:0 auto}.back-link[data-v-7f963124]{display:inline-flex;align-items:center;gap:6px;color:#6b7280;text-decoration:none;font-size:14px;margin-bottom:16px}.back-link[data-v-7f963124]:hover{color:#374151}.page-header[data-v-7f963124]{margin-bottom:24px}.page-header h1[data-v-7f963124]{display:flex;align-items:center;gap:12px;font-size:28px;font-weight:700;color:#111827;margin:0 0 4px}.page-header h1 i[data-v-7f963124]{color:var(--branding-primary, #7C3AED)}.page-header p[data-v-7f963124]{color:#6b7280;margin:0}.error-box[data-v-7f963124]{display:flex;align-items:center;gap:10px;padding:16px 20px;background:#fef2f2;border:1px solid #fecaca;border-radius:12px;color:#dc2626;margin-bottom:24px}.no-token-warning[data-v-7f963124]{text-align:center;padding:60px 20px;background:#fffbeb;border:1px solid #fde68a;border-radius:16px}.no-token-warning .warning-icon[data-v-7f963124]{width:80px;height:80px;margin:0 auto 20px;background:#fef3c7;border-radius:50%;display:flex;align-items:center;justify-content:center}.no-token-warning .warning-icon i[data-v-7f963124]{font-size:40px;color:#f59e0b}.no-token-warning h2[data-v-7f963124]{font-size:24px;font-weight:700;color:#92400e;margin:0 0 8px}.no-token-warning p[data-v-7f963124]{color:#b45309;margin:0 0 24px}.no-token-warning .btn-primary[data-v-7f963124]{display:inline-flex;align-items:center;gap:8px;padding:12px 24px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border-radius:10px;text-decoration:none;font-weight:600}.loading-state[data-v-7f963124]{text-align:center;padding:60px 0}.spinner[data-v-7f963124]{width:40px;height:40px;border:4px solid #e5e7eb;border-top-color:var(--branding-primary, #7C3AED);border-radius:50%;animation:spin-7f963124 1s linear infinite;margin:0 auto 16px}@keyframes spin-7f963124{to{transform:rotate(360deg)}}.rabbitmq-content[data-v-7f963124]{display:flex;flex-direction:column;gap:24px}.add-card[data-v-7f963124],.list-card[data-v-7f963124]{background:#fff;border-radius:16px;box-shadow:0 2px 4px #0000000d;overflow:hidden}.card-header[data-v-7f963124]{display:flex;align-items:center;gap:10px;padding:16px 20px;background:#f9fafb;border-bottom:1px solid #e5e7eb}.card-header i[data-v-7f963124]{color:var(--branding-primary, #7C3AED)}.card-header h2[data-v-7f963124]{font-size:16px;font-weight:600;color:#111827;margin:0}.count-badge[data-v-7f963124]{margin-left:auto;background:var(--branding-primary, #7C3AED);color:#fff;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:600}.card-body[data-v-7f963124]{padding:20px}.add-form[data-v-7f963124]{display:flex;flex-direction:column;gap:16px}.form-row[data-v-7f963124]{display:flex;gap:12px}.form-group[data-v-7f963124]{display:flex;flex-direction:column;gap:6px}.form-group.flex-grow[data-v-7f963124]{flex:1}.form-group label[data-v-7f963124]{font-size:13px;font-weight:600;color:#374151}.form-input[data-v-7f963124]{padding:10px 14px;border:2px solid #e5e7eb;border-radius:8px;font-size:14px;transition:all .2s}.form-input[data-v-7f963124]:focus{outline:none;border-color:var(--branding-primary, #7C3AED);box-shadow:0 0 0 3px #7c3aed1a}.options-row[data-v-7f963124]{gap:20px}.checkbox-label[data-v-7f963124]{display:flex;align-items:center;gap:6px;font-size:14px;color:#374151;cursor:pointer}.checkbox-label input[type=checkbox][data-v-7f963124]{width:16px;height:16px;accent-color:var(--branding-primary, #7C3AED)}.btn-primary[data-v-7f963124]{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:12px 20px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s;align-self:flex-start}.btn-primary[data-v-7f963124]:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 4px 12px #7c3aed40}.btn-primary[data-v-7f963124]:disabled{opacity:.6;cursor:not-allowed}.empty-state[data-v-7f963124]{text-align:center;padding:40px 20px;color:#9ca3af}.empty-state i[data-v-7f963124]{font-size:48px;margin-bottom:12px;display:block}.rabbitmq-list[data-v-7f963124]{display:flex;flex-direction:column;gap:12px}.rabbitmq-item[data-v-7f963124]{display:flex;align-items:center;gap:16px;padding:16px;background:#f9fafb;border-radius:12px;border:1px solid #e5e7eb}.item-info[data-v-7f963124]{flex:1;min-width:0}.item-main[data-v-7f963124]{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.connection-string[data-v-7f963124]{font-size:14px;color:#111827;word-break:break-all}.track-id[data-v-7f963124]{font-size:12px;background:#e0e7ff;color:#4338ca;padding:2px 8px;border-radius:8px}.item-meta[data-v-7f963124]{display:flex;gap:12px;margin-top:6px;font-size:12px;color:#6b7280}.item-meta i[data-v-7f963124]{margin-right:4px}.item-flags[data-v-7f963124]{display:flex;gap:6px}.flag-btn[data-v-7f963124]{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;background:#e5e7eb;border-radius:6px;color:#6b7280;cursor:pointer;transition:all .2s}.flag-btn[data-v-7f963124]:hover{background:#d1d5db}.flag-btn.active[data-v-7f963124]{background:var(--branding-primary, #7C3AED);color:#fff}.btn-delete[data-v-7f963124]{width:36px;height:36px;display:flex;align-items:center;justify-content:center;border:none;background:#fef2f2;border-radius:8px;color:#dc2626;cursor:pointer;transition:all .2s}.btn-delete[data-v-7f963124]:hover{background:#fecaca}@media (max-width: 768px){.form-row[data-v-7f963124]{flex-direction:column}.rabbitmq-item[data-v-7f963124]{flex-direction:column;align-items:stretch}.item-flags[data-v-7f963124]{justify-content:center;padding-top:12px;border-top:1px solid #e5e7eb;margin-top:12px}.btn-delete[data-v-7f963124]{position:absolute;top:12px;right:12px}.rabbitmq-item[data-v-7f963124]{position:relative;padding-right:56px}}.server-page[data-v-0a139a54]{margin:0 auto}.server-header[data-v-0a139a54]{margin-bottom:32px}.header-top[data-v-0a139a54]{margin-bottom:24px}.back-link[data-v-0a139a54]{display:inline-flex;align-items:center;gap:6px;color:#6b7280;text-decoration:none;font-size:14px}.back-link[data-v-0a139a54]:hover{color:#374151}.loading-placeholder[data-v-0a139a54]{display:flex;align-items:center;gap:12px;color:#6b7280}.spinner[data-v-0a139a54]{width:24px;height:24px;border:3px solid #e5e7eb;border-top-color:var(--branding-primary, #7C3AED);border-radius:50%;animation:spin-0a139a54 1s linear infinite}.server-info[data-v-0a139a54]{display:flex;align-items:center;gap:20px}.server-avatar[data-v-0a139a54]{width:80px;height:80px;border-radius:20px;display:flex;align-items:center;justify-content:center;color:#fff}.server-avatar.connected[data-v-0a139a54]{background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6))}.server-avatar.connecting[data-v-0a139a54]{background:linear-gradient(135deg,#f59e0b,#d97706)}.server-avatar.disconnected[data-v-0a139a54]{background:linear-gradient(135deg,#6b7280,#4b5563)}.server-details h1[data-v-0a139a54]{font-size:28px;font-weight:700;color:#111827;margin:0 0 8px}.server-meta[data-v-0a139a54]{display:flex;gap:10px}.status-badge[data-v-0a139a54]{padding:4px 12px;border-radius:20px;font-size:12px;font-weight:600;text-transform:uppercase}.status-badge.connected[data-v-0a139a54]{background:#f5efff;color:var(--branding-secondary, #5B21B6)}.status-badge.connecting[data-v-0a139a54]{background:#fef3c7;color:#92400e}.status-badge.disconnected[data-v-0a139a54]{background:#f3f4f6;color:#6b7280}.version-badge[data-v-0a139a54]{padding:4px 12px;border-radius:20px;font-size:12px;font-weight:500;background:#e0e7ff;color:#4338ca}.error-banner[data-v-0a139a54]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fef2f2;border:1px solid #fecaca;border-radius:12px;color:#dc2626;margin-top:16px}.quick-actions[data-v-0a139a54]{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:16px;margin-bottom:32px}.action-card[data-v-0a139a54]{display:flex;align-items:center;gap:16px;padding:20px;background:#fff;border-radius:16px;text-decoration:none;box-shadow:0 2px 4px #0000000d;transition:all .2s;border:2px solid transparent}.action-card[data-v-0a139a54]:hover{transform:translateY(-2px);box-shadow:0 8px 16px #0000001a;border-color:var(--branding-primary, #7C3AED)}.action-card.primary[data-v-0a139a54]{background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff}.action-card.primary[data-v-0a139a54]:hover{border-color:#fff}.action-card.disabled[data-v-0a139a54]{opacity:.5;pointer-events:none}.action-icon[data-v-0a139a54]{width:56px;height:56px;background:#7c3aed14;border-radius:14px;display:flex;align-items:center;justify-content:center;color:var(--branding-primary, #7C3AED)}.action-card.primary .action-icon[data-v-0a139a54]{background:#fff3;color:#fff}.action-info[data-v-0a139a54]{display:flex;flex-direction:column}.action-title[data-v-0a139a54]{font-size:16px;font-weight:600;color:#111827}.action-card.primary .action-title[data-v-0a139a54]{color:#fff}.action-desc[data-v-0a139a54]{font-size:13px;color:#6b7280;margin-top:2px}.action-card.primary .action-desc[data-v-0a139a54]{color:#fffc}.details-section[data-v-0a139a54],.endpoints-section[data-v-0a139a54],.danger-section[data-v-0a139a54]{background:#fff;border-radius:16px;padding:24px;margin-bottom:24px;box-shadow:0 2px 4px #0000000d}.details-section h2[data-v-0a139a54],.endpoints-section h2[data-v-0a139a54],.danger-section h2[data-v-0a139a54]{display:flex;align-items:center;gap:10px;font-size:18px;font-weight:600;color:#111827;margin:0 0 20px}.danger-section[data-v-0a139a54]{margin-top:32px}.details-section h2 svg[data-v-0a139a54]{color:#3b82f6}.endpoints-section h2 svg[data-v-0a139a54]{color:#8b5cf6}.danger-section h2 svg[data-v-0a139a54]{color:#ef4444}.details-grid[data-v-0a139a54]{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:16px}.detail-card[data-v-0a139a54]{padding:16px;background:#f9fafb;border-radius:12px}.detail-label[data-v-0a139a54]{display:block;font-size:12px;font-weight:600;color:#6b7280;text-transform:uppercase;margin-bottom:8px}.detail-value[data-v-0a139a54]{font-size:15px;color:#111827;display:flex;align-items:center;gap:8px}.detail-value.token[data-v-0a139a54]{justify-content:space-between}.detail-value code[data-v-0a139a54]{font-size:12px;background:#e5e7eb;padding:4px 8px;border-radius:6px;word-break:break-all}.copy-btn[data-v-0a139a54]{padding:6px;background:none;border:none;color:#6b7280;cursor:pointer;border-radius:6px}.copy-btn[data-v-0a139a54]:hover{background:#e5e7eb}.copy-btn.copied[data-v-0a139a54]{color:var(--branding-primary, #7C3AED)}.status-dot[data-v-0a139a54]{width:10px;height:10px;border-radius:50%}.status-dot.connected[data-v-0a139a54]{background:var(--branding-primary, #7C3AED)}.status-dot.connecting[data-v-0a139a54]{background:#f59e0b}.status-dot.disconnected[data-v-0a139a54]{background:#9ca3af}.endpoints-list[data-v-0a139a54]{display:flex;flex-direction:column;gap:12px}.endpoint-item[data-v-0a139a54]{display:flex;align-items:center;gap:12px;padding:12px;background:#f9fafb;border-radius:10px}.endpoint-method[data-v-0a139a54]{padding:4px 10px;border-radius:6px;font-size:11px;font-weight:700}.endpoint-method.get[data-v-0a139a54]{background:#f5efff;color:var(--branding-secondary, #5B21B6)}.endpoint-method.post[data-v-0a139a54]{background:#dbeafe;color:#1e40af}.endpoint-url[data-v-0a139a54]{flex:1;font-size:13px;background:transparent;word-break:break-all}.endpoint-desc[data-v-0a139a54]{font-size:12px;color:#6b7280}.danger-actions[data-v-0a139a54]{display:flex;gap:12px;flex-wrap:wrap}.btn-danger-outline[data-v-0a139a54],.btn-danger[data-v-0a139a54],.btn-warning-outline[data-v-0a139a54]{display:flex;align-items:center;gap:8px;padding:12px 20px;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s}.btn-danger-outline[data-v-0a139a54]{background:#fff;border:2px solid #ef4444;color:#ef4444}.btn-danger-outline[data-v-0a139a54]:hover:not(:disabled){background:#fef2f2}.btn-warning-outline[data-v-0a139a54]{background:#fff;border:2px solid #f59e0b;color:#f59e0b}.btn-warning-outline[data-v-0a139a54]:hover:not(:disabled){background:#fffbeb}.btn-warning-outline[data-v-0a139a54]:disabled{opacity:.5;cursor:not-allowed}.btn-danger[data-v-0a139a54]{background:#ef4444;border:2px solid #ef4444;color:#fff}.btn-danger[data-v-0a139a54]:hover:not(:disabled){background:#dc2626}.btn-danger-outline[data-v-0a139a54]:disabled,.btn-danger[data-v-0a139a54]:disabled{opacity:.5;cursor:not-allowed}.modal-overlay[data-v-0a139a54]{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;padding:20px}.modal-content[data-v-0a139a54]{background:#fff;border-radius:20px;padding:32px;max-width:400px;text-align:center}.modal-icon[data-v-0a139a54]{width:80px;height:80px;margin:0 auto 20px;border-radius:50%;display:flex;align-items:center;justify-content:center}.modal-icon.danger[data-v-0a139a54]{background:#fef2f2;color:#ef4444}.modal-content h3[data-v-0a139a54]{font-size:22px;font-weight:700;color:#111827;margin:0 0 12px}.modal-content p[data-v-0a139a54]{color:#6b7280;margin:0 0 24px;line-height:1.5}.modal-actions[data-v-0a139a54]{display:flex;gap:12px;justify-content:center}.btn-secondary[data-v-0a139a54]{padding:12px 24px;background:#f3f4f6;border:none;border-radius:10px;font-size:14px;font-weight:600;color:#374151;cursor:pointer}.btn-secondary[data-v-0a139a54]:hover{background:#e5e7eb}.options-section[data-v-0a139a54]{margin-top:32px}.options-section h2[data-v-0a139a54]{display:flex;align-items:center;gap:10px;font-size:18px;font-weight:600;color:#374151;margin:0 0 16px}.options-list[data-v-0a139a54]{display:flex;flex-direction:column;gap:12px}.option-card[data-v-0a139a54]{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:16px 20px;background:#fff;border-radius:12px;box-shadow:0 1px 3px #0000001a}.option-info[data-v-0a139a54]{flex:1}.option-header[data-v-0a139a54]{display:flex;align-items:center;gap:10px;margin-bottom:6px}.option-header svg[data-v-0a139a54]{color:var(--branding-primary, #7C3AED)}.option-title[data-v-0a139a54]{font-weight:600;color:#374151;font-size:15px}.option-desc[data-v-0a139a54]{color:#6b7280;font-size:13px;line-height:1.5;margin:0}.toggle-switch[data-v-0a139a54]{position:relative;display:inline-block;width:52px;height:28px;flex-shrink:0}.toggle-switch input[data-v-0a139a54]{opacity:0;width:0;height:0}.toggle-slider[data-v-0a139a54]{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#d1d5db;transition:.3s;border-radius:28px}.toggle-slider[data-v-0a139a54]:before{position:absolute;content:"";height:22px;width:22px;left:3px;bottom:3px;background-color:#fff;transition:.3s;border-radius:50%;box-shadow:0 2px 4px #0003}.toggle-switch input:checked+.toggle-slider[data-v-0a139a54]{background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6))}.toggle-switch input:checked+.toggle-slider[data-v-0a139a54]:before{transform:translate(24px)}.toggle-switch input:disabled+.toggle-slider[data-v-0a139a54]{opacity:.5;cursor:not-allowed}.history-sync-card[data-v-0a139a54]{flex-wrap:wrap}.history-sync-control[data-v-0a139a54]{display:flex;align-items:center;gap:8px;flex-shrink:0}.history-input-group[data-v-0a139a54]{display:flex;align-items:center;background:#f3f4f6;border:2px solid #e5e7eb;border-radius:10px;overflow:hidden;transition:border-color .2s}.history-input-group[data-v-0a139a54]:focus-within{border-color:var(--branding-primary, #7C3AED);background:#fff}.history-input[data-v-0a139a54]{width:60px;padding:10px 12px;border:none;background:transparent;font-size:15px;font-weight:600;color:#374151;text-align:center;outline:none}.history-input[data-v-0a139a54]::placeholder{color:#9ca3af;font-weight:400}.history-input[data-v-0a139a54]::-webkit-outer-spin-button,.history-input[data-v-0a139a54]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.history-input-suffix[data-v-0a139a54]{padding:10px 12px 10px 0;color:#6b7280;font-size:14px;font-weight:500}.btn-save[data-v-0a139a54]{width:40px;height:40px;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));border:none;border-radius:10px;color:#fff;cursor:pointer;transition:transform .2s,box-shadow .2s}.btn-save[data-v-0a139a54]:hover:not(:disabled){transform:scale(1.05);box-shadow:0 4px 12px #7c3aed4d}.btn-save[data-v-0a139a54]:disabled{opacity:.6;cursor:not-allowed}.spinner-tiny[data-v-0a139a54]{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin-0a139a54 .8s linear infinite}@keyframes spin-0a139a54{to{transform:rotate(360deg)}}@media (max-width: 768px){.hide-mobile[data-v-0a139a54]{display:none!important}.server-page[data-v-0a139a54]{padding:0}.server-header[data-v-0a139a54]{position:sticky;top:0;z-index:100;margin:0;border-radius:0;padding:16px}.danger-actions[data-v-0a139a54]{flex-direction:column}.danger-actions button[data-v-0a139a54]{width:100%}.quick-actions[data-v-0a139a54],.details-grid[data-v-0a139a54]{grid-template-columns:1fr}}.setup-page[data-v-700a0a46]{max-width:600px;margin:0 auto}.page-header[data-v-700a0a46]{margin-bottom:24px}.page-header h1[data-v-700a0a46]{display:flex;align-items:center;gap:12px;font-size:28px;font-weight:700;color:#111827;margin:0 0 4px}.page-header h1 i[data-v-700a0a46]{color:var(--branding-primary, #7C3AED)}.page-header p[data-v-700a0a46]{color:#6b7280;margin:0}.setup-content[data-v-700a0a46]{display:flex;flex-direction:column;gap:20px}.setup-card[data-v-700a0a46]{background:#fff;border-radius:16px;box-shadow:0 2px 4px #0000000d;overflow:hidden}.card-header[data-v-700a0a46]{display:flex;align-items:center;gap:10px;padding:16px 20px;background:#f9fafb;border-bottom:1px solid #e5e7eb}.card-header i[data-v-700a0a46]{color:var(--branding-primary, #7C3AED)}.card-header h2[data-v-700a0a46]{font-size:16px;font-weight:600;color:#111827;margin:0}.card-body[data-v-700a0a46]{padding:24px}.setup-form[data-v-700a0a46]{display:flex;flex-direction:column;gap:20px}.error-box[data-v-700a0a46]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fef2f2;border:1px solid #fecaca;border-radius:10px;color:#dc2626;font-size:14px}.success-box[data-v-700a0a46]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#dcfce7;border:1px solid #bbf7d0;border-radius:10px;color:#16a34a;font-size:14px}.form-group[data-v-700a0a46]{display:flex;flex-direction:column;gap:8px}.form-group label[data-v-700a0a46]{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600;color:#374151}.form-group label i[data-v-700a0a46]{color:#9ca3af}.form-input[data-v-700a0a46]{width:100%;padding:12px 16px;border:2px solid #e5e7eb;border-radius:10px;font-size:16px;transition:all .2s;background:#f9fafb}.form-input[data-v-700a0a46]:focus{outline:none;border-color:var(--branding-primary, #7C3AED);background:#fff;box-shadow:0 0 0 4px #7c3aed1a}.password-wrapper[data-v-700a0a46]{position:relative}.password-wrapper .form-input[data-v-700a0a46]{padding-right:48px}.toggle-password[data-v-700a0a46]{position:absolute;right:12px;top:50%;transform:translateY(-50%);padding:8px;background:none;border:none;color:#9ca3af;cursor:pointer}.toggle-password[data-v-700a0a46]:hover{color:#6b7280}.password-strength[data-v-700a0a46]{height:4px;background:#e5e7eb;border-radius:2px;overflow:hidden}.strength-bar[data-v-700a0a46]{height:100%;transition:all .3s}.strength-bar.weak[data-v-700a0a46]{background:#ef4444}.strength-bar.medium[data-v-700a0a46]{background:#f59e0b}.strength-bar.strong[data-v-700a0a46]{background:#10b981}.password-hint[data-v-700a0a46]{font-size:12px;color:#9ca3af}.error-hint[data-v-700a0a46]{font-size:12px;color:#dc2626}.btn-primary[data-v-700a0a46]{display:flex;align-items:center;justify-content:center;gap:8px;padding:14px 24px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border:none;border-radius:10px;font-size:16px;font-weight:600;cursor:pointer;transition:all .2s}.btn-primary[data-v-700a0a46]:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 6px 16px #7c3aed4d}.btn-primary[data-v-700a0a46]:disabled{opacity:.6;cursor:not-allowed}.info-row[data-v-700a0a46]{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-bottom:1px solid #f3f4f6}.info-row[data-v-700a0a46]:last-child{border-bottom:none}.info-label[data-v-700a0a46]{font-size:14px;color:#6b7280}.info-value[data-v-700a0a46]{font-size:14px;font-weight:500;color:#111827}.info-value code[data-v-700a0a46]{background:#f3f4f6;padding:4px 8px;border-radius:6px;font-family:monospace}.badge[data-v-700a0a46]{display:inline-block;padding:4px 10px;border-radius:12px;font-size:11px;font-weight:600;text-transform:uppercase}.badge-success[data-v-700a0a46]{background:#dcfce7;color:#16a34a}.connect-page[data-v-180bf89a]{margin:0 auto;padding:2rem 1rem}.connect-header[data-v-180bf89a]{text-align:center;margin-bottom:2rem}.back-link[data-v-180bf89a]{display:inline-flex;align-items:center;gap:.5rem;color:#6c757d;text-decoration:none;margin-bottom:1rem;transition:color .2s}.back-link[data-v-180bf89a]:hover{color:#7c3aed}.connect-header h1[data-v-180bf89a]{font-size:2rem;font-weight:700;color:#1a1a2e;margin:.5rem 0}.subtitle[data-v-180bf89a]{color:#6c757d;margin:0}.loading-state[data-v-180bf89a],.error-state[data-v-180bf89a]{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:4rem;color:#6c757d}.spinner[data-v-180bf89a]{width:48px;height:48px;border:4px solid #e9ecef;border-top-color:#7c3aed;border-radius:50%;animation:spin-180bf89a 1s linear infinite;margin-bottom:1rem}@keyframes spin-180bf89a{to{transform:rotate(360deg)}}.error-state svg[data-v-180bf89a]{color:#dc3545;margin-bottom:1rem}.btn-retry[data-v-180bf89a]{margin-top:1rem;padding:.75rem 1.5rem;background:#7c3aed;color:#fff;border:none;border-radius:8px;cursor:pointer;font-weight:500;transition:background .2s}.btn-retry[data-v-180bf89a]:hover{background:#1da851}.connection-methods[data-v-180bf89a]{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:2rem;margin-bottom:3rem}.method-card[data-v-180bf89a]{background:#fff;border:2px solid #e9ecef;border-radius:16px;padding:2rem;text-align:center;cursor:pointer;transition:all .3s ease}.method-card[data-v-180bf89a]:hover{border-color:#7c3aed;box-shadow:0 8px 30px #25d36626;transform:translateY(-4px)}.method-icon[data-v-180bf89a]{width:100px;height:100px;margin:0 auto 1.5rem;border-radius:20px;display:flex;align-items:center;justify-content:center}.qrcode-icon[data-v-180bf89a]{background:linear-gradient(135deg,#7c3aed,#5b21b6);color:#fff}.paircode-icon[data-v-180bf89a]{background:linear-gradient(135deg,#8b5cf6,#7c3aed);color:#fff}.method-card h3[data-v-180bf89a]{font-size:1.5rem;font-weight:700;color:#1a1a2e;margin:0 0 .5rem}.method-card>p[data-v-180bf89a]{color:#6c757d;margin:0 0 1.5rem}.method-features[data-v-180bf89a]{list-style:none;padding:0;margin:0 0 1.5rem;text-align:left}.method-features li[data-v-180bf89a]{padding:.5rem 0;color:#495057;font-size:.95rem}.method-action[data-v-180bf89a]{display:inline-block;color:#7c3aed;font-weight:600;font-size:1rem}.method-card:hover .method-action[data-v-180bf89a]{text-decoration:underline}.help-section[data-v-180bf89a]{background:#f8f9fa;border-radius:12px;padding:1.5rem 2rem}.help-section h4[data-v-180bf89a]{font-size:1.1rem;font-weight:600;color:#1a1a2e;margin:0 0 1rem}.help-section ol[data-v-180bf89a]{margin:0;padding-left:1.5rem;color:#495057}.help-section li[data-v-180bf89a]{padding:.3rem 0}.help-section strong[data-v-180bf89a]{color:#1a1a2e}@media (max-width: 768px){.connect-page[data-v-180bf89a]{padding:1rem}.connect-header h1[data-v-180bf89a]{font-size:1.5rem}.connection-methods[data-v-180bf89a]{grid-template-columns:1fr;gap:1rem}.method-card[data-v-180bf89a]{padding:1.5rem}.method-icon[data-v-180bf89a]{width:80px;height:80px}.method-icon svg[data-v-180bf89a]{width:48px;height:48px}}.users-page[data-v-425a59c2]{max-width:800px;margin:0 auto}.page-header[data-v-425a59c2]{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px;flex-wrap:wrap;gap:16px}.header-content h1[data-v-425a59c2]{font-size:24px;font-weight:700;color:#111827;margin:0 0 4px;display:flex;align-items:center;gap:10px}.header-content p[data-v-425a59c2]{color:#6b7280;margin:0}.btn-primary[data-v-425a59c2]{display:flex;align-items:center;gap:8px;padding:10px 20px;background:var(--branding-primary, #7C3AED);color:#fff;border:none;border-radius:8px;font-weight:600;text-decoration:none;cursor:pointer}.btn-primary[data-v-425a59c2]:hover{opacity:.9}.loading-state[data-v-425a59c2]{text-align:center;padding:60px 20px;color:#6b7280}.spinner-large[data-v-425a59c2]{width:40px;height:40px;border:3px solid #e5e7eb;border-top-color:var(--branding-primary, #7C3AED);border-radius:50%;animation:spin-425a59c2 1s linear infinite;margin:0 auto 16px}@keyframes spin-425a59c2{to{transform:rotate(360deg)}}.error-box[data-v-425a59c2]{display:flex;align-items:center;gap:12px;padding:16px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px;color:#dc2626}.retry-btn[data-v-425a59c2]{margin-left:auto;padding:6px 12px;background:#dc2626;color:#fff;border:none;border-radius:6px;cursor:pointer}.empty-state[data-v-425a59c2]{text-align:center;padding:60px 20px;background:#f9fafb;border-radius:12px}.empty-icon[data-v-425a59c2]{color:#9ca3af;margin-bottom:16px}.empty-state h2[data-v-425a59c2]{font-size:20px;color:#374151;margin:0 0 8px}.empty-state p[data-v-425a59c2]{color:#6b7280;margin:0 0 24px}.btn-primary-large[data-v-425a59c2]{display:inline-flex;align-items:center;gap:8px;padding:14px 28px;background:var(--branding-primary, #7C3AED);color:#fff;border:none;border-radius:10px;font-size:16px;font-weight:600;text-decoration:none}.users-list[data-v-425a59c2]{display:flex;flex-direction:column;gap:12px}.user-card[data-v-425a59c2]{display:flex;align-items:center;justify-content:space-between;padding:16px;background:#fff;border:1px solid #e5e7eb;border-radius:10px}.user-card.user-self[data-v-425a59c2]{border:2px solid var(--branding-primary, #7C3AED);background:#f5f3ff}.user-info[data-v-425a59c2]{display:flex;align-items:center;gap:12px}.user-avatar[data-v-425a59c2]{width:44px;height:44px;background:var(--branding-primary, #7C3AED);color:#fff;border-radius:50%;display:flex;align-items:center;justify-content:center}.user-avatar.avatar-self[data-v-425a59c2]{background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));box-shadow:0 2px 8px #7c3aed66}.user-details h3[data-v-425a59c2]{font-size:16px;font-weight:600;color:#111827;margin:0 0 2px;display:flex;align-items:center;gap:8px}.self-badge[data-v-425a59c2]{font-size:10px;padding:2px 6px;background:var(--branding-primary, #7C3AED);color:#fff;border-radius:4px;font-weight:600;text-transform:uppercase}.user-details small[data-v-425a59c2]{color:#6b7280}.btn-danger-small[data-v-425a59c2]{width:36px;height:36px;display:flex;align-items:center;justify-content:center;background:#fef2f2;color:#dc2626;border:1px solid #fecaca;border-radius:8px;cursor:pointer}.btn-danger-small[data-v-425a59c2]:hover{background:#fee2e2}.btn-danger-small[data-v-425a59c2]:disabled{opacity:.5;cursor:not-allowed}.modal-overlay[data-v-425a59c2]{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;padding:20px}.modal-content[data-v-425a59c2]{background:#fff;border-radius:16px;padding:32px;max-width:400px;width:100%;text-align:center}.modal-icon[data-v-425a59c2]{width:72px;height:72px;margin:0 auto 20px;border-radius:50%;display:flex;align-items:center;justify-content:center}.modal-icon.danger[data-v-425a59c2]{background:#fef2f2;color:#dc2626}.modal-content h3[data-v-425a59c2]{font-size:20px;font-weight:700;color:#111827;margin:0 0 12px}.modal-content p[data-v-425a59c2]{color:#6b7280;margin:0 0 24px}.modal-actions[data-v-425a59c2]{display:flex;gap:12px;justify-content:center}.btn-secondary[data-v-425a59c2]{padding:12px 24px;background:#f3f4f6;border:none;border-radius:10px;font-weight:600;color:#374151;cursor:pointer}.btn-secondary[data-v-425a59c2]:hover{background:#e5e7eb}.btn-danger[data-v-425a59c2]{padding:12px 24px;background:#dc2626;color:#fff;border:none;border-radius:10px;font-weight:600;cursor:pointer}.btn-danger[data-v-425a59c2]:hover{background:#b91c1c}@media (max-width: 768px){.hide-mobile[data-v-425a59c2]{display:none!important}.users-page[data-v-425a59c2]{padding:0 16px}.page-header[data-v-425a59c2]{position:sticky;top:0;background:#fff;padding:16px 0;margin:0 0 16px;z-index:100}}.user-create-page[data-v-0fc64e90]{max-width:500px;margin:0 auto}.back-link[data-v-0fc64e90]{display:inline-flex;align-items:center;gap:6px;color:#6b7280;text-decoration:none;font-size:14px;margin-bottom:16px}.back-link[data-v-0fc64e90]:hover{color:#374151}.page-header[data-v-0fc64e90]{margin-bottom:24px}.page-header h1[data-v-0fc64e90]{display:flex;align-items:center;gap:12px;font-size:28px;font-weight:700;color:#111827;margin:0 0 4px}.page-header h1 i[data-v-0fc64e90]{color:var(--branding-primary, #7C3AED)}.page-header p[data-v-0fc64e90]{color:#6b7280;margin:0}.create-card[data-v-0fc64e90]{background:#fff;border-radius:16px;padding:24px;box-shadow:0 2px 4px #0000000d}.create-form[data-v-0fc64e90]{display:flex;flex-direction:column;gap:20px}.error-box[data-v-0fc64e90]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fef2f2;border:1px solid #fecaca;border-radius:10px;color:#dc2626;font-size:14px}.success-box[data-v-0fc64e90]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#dcfce7;border:1px solid #bbf7d0;border-radius:10px;color:#16a34a;font-size:14px}.form-group[data-v-0fc64e90]{display:flex;flex-direction:column;gap:8px}.form-group label[data-v-0fc64e90]{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600;color:#374151}.form-group label i[data-v-0fc64e90]{color:#9ca3af}.form-input[data-v-0fc64e90]{width:100%;padding:12px 16px;border:2px solid #e5e7eb;border-radius:10px;font-size:16px;transition:all .2s;background:#f9fafb}.form-input[data-v-0fc64e90]:focus{outline:none;border-color:var(--branding-primary, #7C3AED);background:#fff;box-shadow:0 0 0 4px #7c3aed1a}.password-wrapper[data-v-0fc64e90]{position:relative}.password-wrapper .form-input[data-v-0fc64e90]{padding-right:48px}.toggle-password[data-v-0fc64e90]{position:absolute;right:12px;top:50%;transform:translateY(-50%);padding:8px;background:none;border:none;color:#9ca3af;cursor:pointer}.toggle-password[data-v-0fc64e90]:hover{color:#6b7280}.password-strength[data-v-0fc64e90]{height:4px;background:#e5e7eb;border-radius:2px;overflow:hidden}.strength-bar[data-v-0fc64e90]{height:100%;transition:all .3s}.strength-bar.weak[data-v-0fc64e90]{background:#ef4444}.strength-bar.medium[data-v-0fc64e90]{background:#f59e0b}.strength-bar.strong[data-v-0fc64e90]{background:#10b981}.error-hint[data-v-0fc64e90]{font-size:12px;color:#dc2626}.form-actions[data-v-0fc64e90]{display:flex;gap:12px;justify-content:flex-end;margin-top:8px}.btn-primary[data-v-0fc64e90]{display:flex;align-items:center;gap:8px;padding:12px 20px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s}.btn-primary[data-v-0fc64e90]:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 4px 12px #7c3aed40}.btn-primary[data-v-0fc64e90]:disabled{opacity:.6;cursor:not-allowed}.btn-secondary[data-v-0fc64e90]{display:flex;align-items:center;gap:8px;padding:12px 20px;background:#f3f4f6;color:#374151;border:none;border-radius:10px;font-size:14px;font-weight:500;text-decoration:none;cursor:pointer;transition:all .2s}.btn-secondary[data-v-0fc64e90]:hover{background:#e5e7eb}.environment-page[data-v-89157469]{max-width:1200px;margin:0 auto}.category-badge[data-v-89157469]{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;background:var(--branding-primary, #7C3AED);color:#fff;font-size:.75rem;font-weight:600}.accordion-button[data-v-89157469]:not(.collapsed){background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff}.accordion-button:not(.collapsed) .category-badge[data-v-89157469]{background:#ffffff4d}.env-value[data-v-89157469]{background:#f8f9fa;padding:2px 6px;border-radius:4px;font-size:.85rem;word-break:break-all}.table td[data-v-89157469]{vertical-align:middle}@media (max-width: 768px){.hide-mobile[data-v-89157469]{display:none!important}.table[data-v-89157469]{font-size:.85rem}.table th[data-v-89157469]:nth-child(3),.table td[data-v-89157469]:nth-child(3){display:none}.table th[data-v-89157469]:nth-child(1),.table td[data-v-89157469]:nth-child(1){width:40%}.table th[data-v-89157469]:nth-child(2),.table td[data-v-89157469]:nth-child(2){width:60%}}.qrcode-page[data-v-1576019b]{max-width:600px;margin:0 auto}.page-header[data-v-1576019b]{margin-bottom:24px}.header-content[data-v-1576019b]{text-align:center}.back-link[data-v-1576019b]{display:inline-flex;align-items:center;gap:6px;color:#6b7280;text-decoration:none;font-size:14px;margin-bottom:16px}.back-link[data-v-1576019b]:hover{color:#374151}.page-header h1[data-v-1576019b]{font-size:28px;font-weight:700;color:#111827;margin:0 0 8px}.page-header p[data-v-1576019b]{color:#6b7280;margin:0}.content-card[data-v-1576019b]{background:#fff;border-radius:16px;padding:32px;box-shadow:0 4px 6px -1px #0000001a}.error-box[data-v-1576019b]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fef2f2;border:1px solid #fecaca;border-radius:12px;color:#dc2626;margin-bottom:24px}.qr-container[data-v-1576019b]{text-align:center}.qr-loading[data-v-1576019b]{padding:60px 0}.spinner-large[data-v-1576019b]{width:50px;height:50px;border:4px solid #e5e7eb;border-top-color:var(--branding-primary, #7C3AED);border-radius:50%;animation:spin-1576019b 1s linear infinite;margin:0 auto 16px}@keyframes spin-1576019b{to{transform:rotate(360deg)}}.qr-loading p[data-v-1576019b]{color:#6b7280}.qr-success[data-v-1576019b]{padding:40px 0;color:var(--branding-primary, #7C3AED)}.qr-success h3[data-v-1576019b]{font-size:24px;margin:16px 0 8px}.qr-success p[data-v-1576019b]{color:#6b7280;margin:0 0 24px}.btn-success[data-v-1576019b]{display:inline-flex;align-items:center;gap:8px;padding:12px 24px;background:var(--branding-primary, #7C3AED);color:#fff;border-radius:10px;text-decoration:none;font-weight:600}.btn-success[data-v-1576019b]:hover{background:var(--branding-secondary, #5B21B6)}.qr-display[data-v-1576019b]{padding:24px;background:#f9fafb;border-radius:16px;margin-bottom:24px}.qr-image[data-v-1576019b]{width:256px;height:256px;border-radius:12px}.qr-placeholder[data-v-1576019b]{padding:60px 0;color:#9ca3af}.qr-placeholder p[data-v-1576019b]{margin:16px 0 0}.qr-actions[data-v-1576019b]{margin-bottom:32px}.btn-primary[data-v-1576019b]{display:inline-flex;align-items:center;gap:8px;padding:14px 28px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border:none;border-radius:12px;font-size:16px;font-weight:600;cursor:pointer;transition:all .2s}.btn-primary[data-v-1576019b]:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 16px #7c3aed40}.btn-primary[data-v-1576019b]:disabled{opacity:.6;cursor:not-allowed}.qr-instructions[data-v-1576019b]{text-align:left;padding:20px;background:#f8f6ff;border-radius:12px;margin-bottom:24px}.qr-instructions h4[data-v-1576019b]{font-size:16px;color:var(--branding-secondary, #5B21B6);margin:0 0 12px}.qr-instructions ol[data-v-1576019b]{margin:0;padding-left:20px;color:#15803d}.qr-instructions li[data-v-1576019b]{margin-bottom:8px}.qr-instructions li[data-v-1576019b]:last-child{margin-bottom:0}.alt-method[data-v-1576019b]{text-align:center;padding-top:20px;border-top:1px solid #e5e7eb}.alt-method p[data-v-1576019b]{color:#6b7280;margin:0 0 8px;font-size:14px}.link-primary[data-v-1576019b]{color:var(--branding-primary, #7C3AED);text-decoration:none;font-weight:600}.link-primary[data-v-1576019b]:hover{text-decoration:underline}.paircode-page[data-v-8958d222]{max-width:600px;margin:0 auto}.page-header[data-v-8958d222]{margin-bottom:24px}.header-content[data-v-8958d222]{text-align:center}.back-link[data-v-8958d222]{display:inline-flex;align-items:center;gap:6px;color:#6b7280;text-decoration:none;font-size:14px;margin-bottom:16px}.back-link[data-v-8958d222]:hover{color:#374151}.page-header h1[data-v-8958d222]{font-size:28px;font-weight:700;color:#111827;margin:0 0 8px}.page-header p[data-v-8958d222]{color:#6b7280;margin:0}.content-card[data-v-8958d222]{background:#fff;border-radius:16px;padding:32px;box-shadow:0 4px 6px -1px #0000001a}.error-box[data-v-8958d222]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fef2f2;border:1px solid #fecaca;border-radius:12px;color:#dc2626;margin-bottom:24px}.success-section[data-v-8958d222]{text-align:center;padding:40px 0}.success-icon[data-v-8958d222]{color:var(--branding-primary, #7C3AED)}.success-section h3[data-v-8958d222]{font-size:24px;color:var(--branding-primary, #7C3AED);margin:16px 0 8px}.success-section p[data-v-8958d222]{color:#6b7280;margin:0 0 24px}.btn-success[data-v-8958d222]{display:inline-flex;align-items:center;gap:8px;padding:12px 24px;background:var(--branding-primary, #7C3AED);color:#fff;border-radius:10px;text-decoration:none;font-weight:600}.step-section[data-v-8958d222]{margin-bottom:24px}.step-header[data-v-8958d222]{display:flex;align-items:flex-start;gap:16px;margin-bottom:16px}.step-number[data-v-8958d222]{width:32px;height:32px;background:linear-gradient(135deg,#7c3aed,#5b21b6);color:#fff;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:14px;flex-shrink:0}.step-number.completed[data-v-8958d222]{background:var(--branding-primary, #7C3AED)}.step-info h3[data-v-8958d222]{font-size:16px;font-weight:600;color:#111827;margin:0 0 4px}.step-info p[data-v-8958d222]{font-size:14px;color:#6b7280;margin:0}.btn-link[data-v-8958d222]{background:none;border:none;color:#7c3aed;font-size:14px;cursor:pointer;padding:0}.btn-link[data-v-8958d222]:hover{text-decoration:underline}.phone-input-group[data-v-8958d222]{display:flex;gap:12px}.input-wrapper[data-v-8958d222]{flex:1;position:relative}.input-prefix[data-v-8958d222]{position:absolute;left:16px;top:50%;transform:translateY(-50%);color:#6b7280;font-weight:600}.phone-input[data-v-8958d222]{width:100%;padding:14px 16px 14px 32px;border:2px solid #e5e7eb;border-radius:12px;font-size:18px;letter-spacing:1px}.phone-input[data-v-8958d222]:focus{outline:none;border-color:#7c3aed}.btn-primary[data-v-8958d222]{display:flex;align-items:center;gap:8px;padding:14px 24px;background:linear-gradient(135deg,#7c3aed,#5b21b6);color:#fff;border:none;border-radius:12px;font-size:16px;font-weight:600;cursor:pointer;white-space:nowrap}.btn-primary[data-v-8958d222]:disabled{opacity:.6;cursor:not-allowed}.spinner[data-v-8958d222]{width:20px;height:20px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin-8958d222 .8s linear infinite}@keyframes spin-8958d222{to{transform:rotate(360deg)}}.code-display[data-v-8958d222]{text-align:center;padding:24px;background:#f0fdf4;border-radius:16px;margin-bottom:16px}.code-box[data-v-8958d222]{display:flex;justify-content:center;gap:4px;margin-bottom:16px}.code-char[data-v-8958d222]{width:44px;height:56px;background:#fff;border:2px solid #7C3AED;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:26px;font-weight:700;color:#111827}.code-char.separator[data-v-8958d222]{width:20px;background:transparent;border:none;color:#7c3aed;font-size:24px}.btn-copy[data-v-8958d222]{display:inline-flex;align-items:center;gap:6px;padding:10px 20px;background:#fff;border:2px solid #7C3AED;border-radius:10px;color:#7c3aed;font-weight:600;cursor:pointer;transition:all .2s}.btn-copy[data-v-8958d222]:hover{background:#7c3aed;color:#fff}.btn-copy.copied[data-v-8958d222]{background:var(--branding-primary, #7C3AED);border-color:var(--branding-primary, #7C3AED);color:#fff}.code-timer[data-v-8958d222]{display:flex;align-items:center;justify-content:center;gap:6px;color:#6b7280;font-size:14px;margin-bottom:16px}.btn-secondary[data-v-8958d222]{display:inline-flex;align-items:center;gap:8px;padding:12px 20px;background:#f3f4f6;border:none;border-radius:10px;color:#374151;font-weight:600;cursor:pointer}.btn-secondary[data-v-8958d222]:hover{background:#e5e7eb}.action-buttons[data-v-8958d222]{display:flex;flex-direction:column;gap:12px;align-items:center}.btn-confirm[data-v-8958d222]{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;max-width:300px;padding:14px 24px;background:linear-gradient(135deg,#10b981,#059669);color:#fff;border:none;border-radius:12px;font-size:16px;font-weight:600;cursor:pointer;transition:all .2s}.btn-confirm[data-v-8958d222]:hover:not(:disabled){background:linear-gradient(135deg,#059669,#047857);transform:translateY(-1px)}.btn-confirm[data-v-8958d222]:disabled{opacity:.7;cursor:not-allowed}.instructions-box[data-v-8958d222]{padding:20px;background:#fef3c7;border-radius:12px;margin:24px 0}.instructions-box h4[data-v-8958d222]{font-size:16px;color:#92400e;margin:0 0 12px}.instructions-box ol[data-v-8958d222]{margin:0;padding-left:20px;color:#a16207}.instructions-box li[data-v-8958d222]{margin-bottom:8px}.alt-method[data-v-8958d222]{text-align:center;padding-top:20px;border-top:1px solid #e5e7eb}.alt-method p[data-v-8958d222]{color:#6b7280;margin:0 0 8px;font-size:14px}.link-primary[data-v-8958d222]{color:#7c3aed;text-decoration:none;font-weight:600}.link-primary[data-v-8958d222]:hover{text-decoration:underline}.messages-page[data-v-9fa98ea1]{margin:0 auto}.page-header[data-v-9fa98ea1]{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px;flex-wrap:wrap;gap:16px}.header-left[data-v-9fa98ea1]{display:flex;align-items:center;gap:16px}.header-sub[data-v-9fa98ea1]{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.ws-status[data-v-9fa98ea1]{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:12px;font-size:11px;font-weight:600;margin-left:8px}.ws-connected[data-v-9fa98ea1]{background:#dcfce7;color:#166534}.ws-connected svg[data-v-9fa98ea1]{color:#22c55e;animation:pulse-9fa98ea1 2s infinite}.ws-disconnected[data-v-9fa98ea1]{background:#fee2e2;color:#991b1b}.ws-disconnected svg[data-v-9fa98ea1]{color:#ef4444}@keyframes pulse-9fa98ea1{0%,to{opacity:1}50%{opacity:.5}}.back-link[data-v-9fa98ea1]{display:flex;align-items:center;gap:6px;color:#6b7280;text-decoration:none;font-size:14px;background:none;border:none;cursor:pointer;padding:0}.back-link[data-v-9fa98ea1]:hover{color:#374151}.page-header h1[data-v-9fa98ea1]{font-size:24px;font-weight:700;color:#111827;margin:0}.btn-refresh[data-v-9fa98ea1]{display:flex;align-items:center;gap:8px;padding:10px 16px;background:#fff;border:2px solid #e5e7eb;border-radius:10px;color:#374151;font-weight:600;cursor:pointer}.btn-refresh[data-v-9fa98ea1]:hover:not(:disabled){border-color:#7c3aed;color:#7c3aed}.btn-refresh svg.spinning[data-v-9fa98ea1]{animation:spin-9fa98ea1 1s linear infinite}@keyframes spin-9fa98ea1{to{transform:rotate(360deg)}}.error-box[data-v-9fa98ea1]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fef2f2;border:1px solid #fecaca;border-radius:12px;color:#dc2626;margin-bottom:24px}.filters-bar[data-v-9fa98ea1]{display:flex;align-items:center;gap:16px;padding:16px;background:#fff;border-radius:12px;margin-bottom:24px;flex-wrap:wrap}.search-box[data-v-9fa98ea1]{flex:1;min-width:200px;position:relative}.search-box svg[data-v-9fa98ea1]{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:#9ca3af}.search-input[data-v-9fa98ea1]{width:100%;padding:10px 12px 10px 40px;border:2px solid #e5e7eb;border-radius:10px;font-size:14px}.search-input[data-v-9fa98ea1]:focus{outline:none;border-color:#7c3aed}.filter-group[data-v-9fa98ea1]{display:flex;align-items:center;gap:8px}.filter-group label[data-v-9fa98ea1]{font-size:14px;color:#6b7280}.filter-select[data-v-9fa98ea1]{padding:10px 12px;border:2px solid #e5e7eb;border-radius:10px;font-size:14px}.filter-checkbox[data-v-9fa98ea1]{margin-right:6px;accent-color:#7C3AED}.filter-group label[data-v-9fa98ea1]{display:flex;align-items:center;cursor:pointer}.messages-count[data-v-9fa98ea1]{font-size:14px;color:#6b7280;padding:10px 16px;background:#f3f4f6;border-radius:8px}.loading-container[data-v-9fa98ea1]{text-align:center;padding:60px 0}.spinner-large[data-v-9fa98ea1]{width:50px;height:50px;border:4px solid #e5e7eb;border-top-color:#7c3aed;border-radius:50%;animation:spin-9fa98ea1 1s linear infinite;margin:0 auto 16px}.loading-container p[data-v-9fa98ea1]{color:#6b7280}.empty-state[data-v-9fa98ea1]{text-align:center;padding:60px 0;color:#9ca3af}.empty-state h3[data-v-9fa98ea1]{font-size:20px;color:#6b7280;margin:16px 0 8px}.empty-state p[data-v-9fa98ea1]{margin:0}.messages-list[data-v-9fa98ea1]{display:flex;flex-direction:column;gap:16px}.message-card[data-v-9fa98ea1]{background:#fff;border-radius:16px;padding:20px;box-shadow:0 2px 4px #0000000d}.message-card.from-me[data-v-9fa98ea1]{border-left:4px solid #7C3AED}.message-header[data-v-9fa98ea1]{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.message-sender[data-v-9fa98ea1]{display:flex;align-items:center;gap:12px}.sender-avatar[data-v-9fa98ea1]{width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:16px}.sender-info[data-v-9fa98ea1]{display:flex;flex-direction:column}.sender-name[data-v-9fa98ea1]{font-weight:600;color:#111827}.sender-phone[data-v-9fa98ea1]{font-size:12px;color:#6b7280}.message-meta[data-v-9fa98ea1]{display:flex;flex-direction:column;align-items:flex-end;gap:8px}.message-time[data-v-9fa98ea1]{font-size:12px;color:#9ca3af}.message-badges[data-v-9fa98ea1]{display:flex;flex-wrap:wrap;gap:4px;justify-content:flex-end}.badge[data-v-9fa98ea1]{font-size:10px;padding:2px 6px;border-radius:4px;font-weight:600;text-transform:uppercase}.badge-sent[data-v-9fa98ea1]{background:#f5efff;color:#7c3aed}.badge-received[data-v-9fa98ea1]{background:#ecfdf5;color:#059669}.badge-status[data-v-9fa98ea1]{background:#eff6ff;color:#2563eb}.badge-warning[data-v-9fa98ea1]{background:#fefce8;color:#ca8a04}.badge-secondary[data-v-9fa98ea1]{background:#f3f4f6;color:#6b7280}.badge-danger[data-v-9fa98ea1]{background:#fef2f2;color:#dc2626}.message-participant[data-v-9fa98ea1]{display:flex;align-items:center;gap:6px;font-size:13px;color:#6b7280;margin-bottom:8px;padding:6px 10px;background:#f9fafb;border-radius:8px;width:fit-content}.message-participant svg[data-v-9fa98ea1]{flex-shrink:0}.message-participant .participant-field[data-v-9fa98ea1]{font-size:13px;color:#374151}.message-participant .participant-lid[data-v-9fa98ea1]{display:block;font-size:12px;color:#6b7280;margin-top:4px}.message-body[data-v-9fa98ea1]{margin-bottom:12px}.message-text[data-v-9fa98ea1]{color:#374151;line-height:1.5;white-space:pre-wrap;word-break:break-word}.message-attachment[data-v-9fa98ea1]{margin-top:12px}.attachment-meta[data-v-9fa98ea1]{margin-top:6px;font-size:11px;color:#9ca3af}.mime-type[data-v-9fa98ea1]{font-family:monospace}.message-url[data-v-9fa98ea1]{margin-top:12px}.url-preview[data-v-9fa98ea1]{padding:12px;background:#f9fafb;border-radius:8px;border-left:3px solid #7C3AED}.url-preview strong[data-v-9fa98ea1]{display:block;color:#111827;margin-bottom:4px}.url-preview p[data-v-9fa98ea1]{font-size:13px;color:#6b7280;margin:0 0 8px}.url-link[data-v-9fa98ea1]{font-size:12px;color:#7c3aed;text-decoration:none;word-break:break-all}.url-link[data-v-9fa98ea1]:hover{text-decoration:underline}.message-ads[data-v-9fa98ea1]{margin-top:12px;padding:10px;background:#fef2f2;border-radius:8px;border-left:3px solid #dc2626}.ads-header[data-v-9fa98ea1]{display:flex;align-items:center;gap:6px;font-size:13px;color:#dc2626;font-weight:600}.ads-link[data-v-9fa98ea1]{display:inline-block;margin-top:6px;font-size:12px;color:#dc2626;text-decoration:none}.ads-link[data-v-9fa98ea1]:hover{text-decoration:underline}.message-reply[data-v-9fa98ea1]{display:flex;align-items:center;gap:6px;font-size:12px;color:#6b7280;margin-top:8px;padding:6px 10px;background:#f3f4f6;border-radius:8px}.message-reply svg[data-v-9fa98ea1]{flex-shrink:0}.message-exceptions[data-v-9fa98ea1]{margin-top:12px;padding:10px;background:#fef2f2;border-radius:8px}.exceptions-header[data-v-9fa98ea1]{display:flex;align-items:center;gap:6px;font-size:13px;color:#dc2626;font-weight:600;margin-bottom:8px}.exceptions-list[data-v-9fa98ea1]{margin:0;padding-left:20px;font-size:12px;color:#991b1b}.exceptions-list li[data-v-9fa98ea1]{margin-bottom:4px}.message-card.has-exceptions[data-v-9fa98ea1]{border-left:4px solid #dc2626}.attachment-image img[data-v-9fa98ea1]{max-width:300px;max-height:300px;border-radius:12px;cursor:pointer}.attachment-audio audio[data-v-9fa98ea1]{width:100%;max-width:400px}.attachment-video video[data-v-9fa98ea1]{max-width:100%;max-height:300px;border-radius:12px}.attachment-file[data-v-9fa98ea1]{display:flex;align-items:center;gap:12px;padding:12px;background:#f3f4f6;border-radius:12px}.attachment-file svg[data-v-9fa98ea1]{color:#6b7280}.file-info[data-v-9fa98ea1]{flex:1;display:flex;flex-direction:column}.file-name[data-v-9fa98ea1]{font-weight:600;color:#111827}.file-size[data-v-9fa98ea1]{font-size:12px;color:#6b7280}.btn-download[data-v-9fa98ea1]{padding:8px;background:#7c3aed;border-radius:8px;color:#fff}.message-footer[data-v-9fa98ea1]{display:flex;align-items:center;justify-content:flex-start;gap:12px;flex-wrap:wrap;padding-top:12px;border-top:1px solid #f3f4f6}.message-id[data-v-9fa98ea1],.message-trackid[data-v-9fa98ea1]{font-size:11px;color:#9ca3af;font-family:monospace}.message-type[data-v-9fa98ea1]{font-size:11px;padding:2px 6px;background:#f3f4f6;color:#6b7280;border-radius:4px;font-family:monospace;margin-left:auto}.sender-lid[data-v-9fa98ea1]{display:block;font-size:12px;color:#6b7280}.sender-avatar-img[data-v-9fa98ea1]{padding:0;overflow:hidden}.sender-avatar-img .avatar-img[data-v-9fa98ea1]{width:40px;height:40px;border-radius:50%;object-fit:cover;display:block}.pagination-controls[data-v-9fa98ea1]{display:flex;align-items:center;justify-content:center;gap:12px;padding:16px;background:#fff;border-radius:12px;margin:16px 0;box-shadow:0 1px 3px #0000001a}.btn-page[data-v-9fa98ea1]{padding:8px 12px;background:#7c3aed;color:#fff;border:none;border-radius:8px;cursor:pointer;transition:all .2s;display:flex;align-items:center;justify-content:center}.btn-page[data-v-9fa98ea1]:hover:not(:disabled){background:#6d28d9;transform:translateY(-1px)}.btn-page[data-v-9fa98ea1]:disabled{background:#e5e7eb;color:#9ca3af;cursor:not-allowed;opacity:.6}.page-info[data-v-9fa98ea1]{padding:8px 16px;background:#f3f4f6;border-radius:8px;color:#374151;font-weight:500;min-width:150px;text-align:center}.page-size-select[data-v-9fa98ea1]{padding:8px 12px;border:1px solid #D1D5DB;border-radius:8px;background:#fff;color:#374151;font-size:14px;cursor:pointer;transition:border-color .2s}.page-size-select[data-v-9fa98ea1]:hover:not(:disabled){border-color:#7c3aed}.page-size-select[data-v-9fa98ea1]:disabled{background:#f3f4f6;cursor:not-allowed;opacity:.6}.participant-avatar[data-v-9fa98ea1]{width:28px;height:28px;border-radius:50%;object-fit:cover}.ads-thumbnail img[data-v-9fa98ea1],.url-thumbnail img[data-v-9fa98ea1]{max-width:200px;max-height:120px;border-radius:8px;display:block;margin-top:8px}.attachment-status[data-v-9fa98ea1]{margin-top:8px}.header-sub[data-v-9fa98ea1]{margin-top:6px}.chat-title[data-v-9fa98ea1]{display:block;font-size:12px;color:#6b7280;margin-top:4px}.json-message .json-controls[data-v-9fa98ea1]{display:flex;gap:8px;justify-content:flex-end;margin-bottom:8px}.json-block[data-v-9fa98ea1]{background:#0b1221;color:#e6eef8;padding:12px;border-radius:8px;overflow:auto;max-height:240px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Roboto Mono,Noto Sans Mono,monospace;font-size:12px}.json-collapsed[data-v-9fa98ea1]{color:#6b7280;font-style:italic}.btn-small[data-v-9fa98ea1]{background:#eef2ff;border:1px solid #c7d2fe;padding:6px 10px;border-radius:6px;cursor:pointer;font-size:12px}.btn-small[data-v-9fa98ea1]:hover{background:#e0e7ff}.send-page[data-v-f1e3bd8f]{max-width:1100px;margin:0 auto}.page-header[data-v-f1e3bd8f]{margin-bottom:24px}.header-content[data-v-f1e3bd8f]{text-align:center}.back-link[data-v-f1e3bd8f]{display:inline-flex;align-items:center;gap:6px;color:#6b7280;text-decoration:none;font-size:14px;margin-bottom:16px}.page-header h1[data-v-f1e3bd8f]{font-size:28px;font-weight:700;color:#111827;margin:0 0 8px}.page-header p[data-v-f1e3bd8f]{color:#6b7280;margin:0}.content-grid[data-v-f1e3bd8f]{display:grid;grid-template-columns:1fr 360px;gap:24px}@media (max-width: 900px){.content-grid[data-v-f1e3bd8f]{grid-template-columns:1fr}}.send-card[data-v-f1e3bd8f],.preview-card[data-v-f1e3bd8f]{background:#fff;border-radius:16px;padding:24px;box-shadow:0 4px 6px -1px #0000001a}.error-box[data-v-f1e3bd8f]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fef2f2;border:1px solid #fecaca;border-radius:12px;color:#dc2626;margin-bottom:16px}.success-box[data-v-f1e3bd8f]{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#f5efff;border:1px solid rgba(124,58,237,.12);border-radius:12px;color:var(--branding-secondary, #5B21B6);margin-bottom:16px}.form-group[data-v-f1e3bd8f]{margin-bottom:20px}.form-group label[data-v-f1e3bd8f]{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600;color:#374151;margin-bottom:8px}.form-group label svg[data-v-f1e3bd8f]{color:#6b7280}.input-wrapper[data-v-f1e3bd8f]{position:relative}.contact-search[data-v-f1e3bd8f]{margin-top:8px;border:1px solid #e5e7eb;padding:8px;border-radius:8px;background:#fff}.contact-search-controls[data-v-f1e3bd8f]{display:flex;gap:8px;margin-bottom:8px}.contact-search-list ul[data-v-f1e3bd8f]{list-style:none;padding:0;margin:0;display:grid;gap:8px}.contact-result[data-v-f1e3bd8f]{width:100%;text-align:left;padding:8px;border:1px solid #eee;border-radius:6px;background:#f9fafb;cursor:pointer}.contact-result[data-v-f1e3bd8f]:hover{background:#f3f4f6}.contact-search-btn[data-v-f1e3bd8f]{position:absolute;right:8px;top:50%;transform:translateY(-50%)}.input-prefix[data-v-f1e3bd8f]{position:absolute;left:16px;top:50%;transform:translateY(-50%);color:#6b7280;font-weight:600}.form-input[data-v-f1e3bd8f]{width:100%;padding:14px 16px;border:2px solid #e5e7eb;border-radius:12px;font-size:16px;transition:all .2s}.form-input.with-prefix[data-v-f1e3bd8f]{padding-left:32px}.form-input[data-v-f1e3bd8f]:focus{outline:none;border-color:var(--branding-primary, #7C3AED)}.form-textarea[data-v-f1e3bd8f]{width:100%;padding:14px 16px;border:2px solid #e5e7eb;border-radius:12px;font-size:16px;resize:vertical;min-height:120px}.form-textarea[data-v-f1e3bd8f]:focus{outline:none;border-color:var(--branding-primary, #7C3AED)}.input-hint[data-v-f1e3bd8f]{display:block;font-size:12px;color:#9ca3af;margin-top:6px}.message-tabs[data-v-f1e3bd8f]{display:flex;gap:8px;flex-wrap:wrap}.message-tabs button[data-v-f1e3bd8f]{display:flex;align-items:center;gap:6px;padding:10px 16px;background:#f3f4f6;border:2px solid transparent;border-radius:10px;font-size:14px;font-weight:500;color:#6b7280;cursor:pointer;transition:all .2s}.message-tabs button[data-v-f1e3bd8f]:hover{background:#e5e7eb}.message-tabs button.active[data-v-f1e3bd8f]{background:#f5efff;border-color:var(--branding-primary, #7C3AED);color:var(--branding-secondary, #5B21B6)}.btn-send[data-v-f1e3bd8f]{width:100%;display:flex;align-items:center;justify-content:center;gap:10px;padding:16px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border:none;border-radius:12px;font-size:16px;font-weight:600;cursor:pointer;transition:all .2s}.btn-send[data-v-f1e3bd8f]:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 16px #7c3aed40}.btn-send[data-v-f1e3bd8f]:disabled{opacity:.6;cursor:not-allowed}.spinner[data-v-f1e3bd8f]{width:20px;height:20px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin-f1e3bd8f .8s linear infinite}@keyframes spin-f1e3bd8f{to{transform:rotate(360deg)}}.preview-card h3[data-v-f1e3bd8f]{display:flex;align-items:center;gap:8px;font-size:16px;color:#374151;margin:0 0 16px}.phone-mockup[data-v-f1e3bd8f]{background:#e5ddd5;border-radius:16px;overflow:hidden}.phone-header[data-v-f1e3bd8f]{background:#075e54;padding:12px 16px}.contact-info[data-v-f1e3bd8f]{display:flex;align-items:center;gap:10px;color:#fff}.contact-avatar[data-v-f1e3bd8f]{width:36px;height:36px;background:#128c7e;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700}.phone-messages[data-v-f1e3bd8f]{padding:16px;min-height:200px}.message-bubble[data-v-f1e3bd8f]{max-width:80%;margin-left:auto;background:#dcf8c6;padding:8px 12px;border-radius:8px 0 8px 8px;position:relative}.bubble-text[data-v-f1e3bd8f]{color:#111827;font-size:14px;line-height:1.4;word-break:break-word}.bubble-media[data-v-f1e3bd8f]{margin-bottom:4px}.media-placeholder[data-v-f1e3bd8f]{width:100%;height:120px;background:#0000001a;border-radius:8px;display:flex;align-items:center;justify-content:center;color:#6b7280;margin-bottom:8px}.media-placeholder.file[data-v-f1e3bd8f]{flex-direction:column;gap:8px;height:80px}.media-placeholder.file span[data-v-f1e3bd8f]{font-size:12px}.bubble-time[data-v-f1e3bd8f]{font-size:11px;color:#667781;text-align:right;margin-top:4px}.recent-sends[data-v-f1e3bd8f]{margin-top:24px;padding-top:24px;border-top:1px solid #e5e7eb}.recent-sends h4[data-v-f1e3bd8f]{font-size:14px;color:#6b7280;margin:0 0 12px}.recent-list[data-v-f1e3bd8f]{display:flex;flex-direction:column;gap:8px}.recent-item[data-v-f1e3bd8f]{display:flex;justify-content:space-between;padding:8px 12px;background:#f0fdf4;border-radius:8px;font-size:13px}.recent-item.failed[data-v-f1e3bd8f]{background:#fef2f2}.recent-to[data-v-f1e3bd8f]{font-weight:500;color:#374151}.recent-status[data-v-f1e3bd8f]{color:var(--branding-secondary, #5B21B6)}.recent-item.failed .recent-status[data-v-f1e3bd8f]{color:#dc2626}.source-tabs[data-v-f1e3bd8f]{display:flex;gap:8px;flex-wrap:wrap}.source-tabs button[data-v-f1e3bd8f]{display:flex;align-items:center;gap:6px;padding:10px 16px;background:#f3f4f6;border:2px solid transparent;border-radius:10px;font-size:14px;font-weight:500;color:#6b7280;cursor:pointer;transition:all .2s}.source-tabs button[data-v-f1e3bd8f]:hover{background:#e5e7eb}.source-tabs button.active[data-v-f1e3bd8f]{background:#f5efff;border-color:var(--branding-primary, #7C3AED);color:var(--branding-secondary, #5B21B6)}.file-upload[data-v-f1e3bd8f]{border:2px dashed #d1d5db;border-radius:12px;padding:24px;cursor:pointer;transition:all .2s;background:#fafafa}.file-upload[data-v-f1e3bd8f]:hover{border-color:var(--branding-primary, #7C3AED);background:#f5efff}.file-upload.has-file[data-v-f1e3bd8f]{border-style:solid;border-color:var(--branding-primary, #7C3AED);background:#f5efff}.upload-placeholder[data-v-f1e3bd8f]{display:flex;flex-direction:column;align-items:center;gap:8px;color:#6b7280}.upload-placeholder svg[data-v-f1e3bd8f]{color:#9ca3af}.file-hint[data-v-f1e3bd8f]{font-size:12px;color:#9ca3af}.file-selected[data-v-f1e3bd8f]{display:flex;align-items:center;gap:12px}.file-selected svg[data-v-f1e3bd8f]{color:var(--branding-primary, #7C3AED);flex-shrink:0}.file-info[data-v-f1e3bd8f]{flex:1;min-width:0}.file-name[data-v-f1e3bd8f]{display:block;font-weight:500;color:#374151;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-size[data-v-f1e3bd8f]{font-size:12px;color:#9ca3af}.file-remove[data-v-f1e3bd8f]{width:28px;height:28px;background:#fee2e2;color:#dc2626;border:none;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;transition:all .2s}.file-remove[data-v-f1e3bd8f]:hover{background:#fecaca}.audio-recorder[data-v-f1e3bd8f]{background:#f8fafc;border:2px solid #e5e7eb;border-radius:12px;padding:24px;text-align:center}.audio-recorder.recording[data-v-f1e3bd8f]{border-color:#ef4444;background:#fef2f2}.recorder-idle[data-v-f1e3bd8f]{display:flex;flex-direction:column;align-items:center;gap:12px}.btn-record[data-v-f1e3bd8f]{width:64px;height:64px;background:linear-gradient(135deg,var(--branding-primary, #7C3AED),var(--branding-secondary, #5B21B6));color:#fff;border:none;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s}.btn-record[data-v-f1e3bd8f]:hover{transform:scale(1.1);box-shadow:0 8px 16px #7c3aed40}.recorder-active[data-v-f1e3bd8f]{display:flex;flex-direction:column;align-items:center;gap:16px}.recording-indicator[data-v-f1e3bd8f]{display:flex;align-items:center;gap:12px}.recording-dot[data-v-f1e3bd8f]{width:12px;height:12px;background:#ef4444;border-radius:50%;animation:pulse-f1e3bd8f 1s ease-in-out infinite}@keyframes pulse-f1e3bd8f{0%,to{opacity:1}50%{opacity:.4}}.recording-time[data-v-f1e3bd8f]{font-size:24px;font-weight:600;color:#ef4444;font-variant-numeric:tabular-nums}.btn-stop[data-v-f1e3bd8f]{display:flex;align-items:center;gap:8px;padding:12px 24px;background:#ef4444;color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s}.btn-stop[data-v-f1e3bd8f]:hover{background:#dc2626}.recorder-done[data-v-f1e3bd8f]{display:flex;flex-direction:column;align-items:center;gap:12px}.audio-preview[data-v-f1e3bd8f]{width:100%;max-width:280px}.btn-clear[data-v-f1e3bd8f]{display:flex;align-items:center;gap:6px;padding:8px 16px;background:#fee2e2;color:#dc2626;border:none;border-radius:8px;font-size:14px;cursor:pointer;transition:all .2s}.btn-clear[data-v-f1e3bd8f]:hover{background:#fecaca}/*! + * Bootstrap v5.3.8 (https://getbootstrap.com/) + * Copyright 2011-2025 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-primary-text-emphasis:#052c65;--bs-secondary-text-emphasis:#2b2f32;--bs-success-text-emphasis:#0a3622;--bs-info-text-emphasis:#055160;--bs-warning-text-emphasis:#664d03;--bs-danger-text-emphasis:#58151c;--bs-light-text-emphasis:#495057;--bs-dark-text-emphasis:#495057;--bs-primary-bg-subtle:#cfe2ff;--bs-secondary-bg-subtle:#e2e3e5;--bs-success-bg-subtle:#d1e7dd;--bs-info-bg-subtle:#cff4fc;--bs-warning-bg-subtle:#fff3cd;--bs-danger-bg-subtle:#f8d7da;--bs-light-bg-subtle:#fcfcfd;--bs-dark-bg-subtle:#ced4da;--bs-primary-border-subtle:#9ec5fe;--bs-secondary-border-subtle:#c4c8cb;--bs-success-border-subtle:#a3cfbb;--bs-info-border-subtle:#9eeaf9;--bs-warning-border-subtle:#ffe69c;--bs-danger-border-subtle:#f1aeb5;--bs-light-border-subtle:#e9ecef;--bs-dark-border-subtle:#adb5bd;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, .15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-color-rgb:33,37,41;--bs-body-bg:#fff;--bs-body-bg-rgb:255,255,255;--bs-emphasis-color:#000;--bs-emphasis-color-rgb:0,0,0;--bs-secondary-color:rgba(33, 37, 41, .75);--bs-secondary-color-rgb:33,37,41;--bs-secondary-bg:#e9ecef;--bs-secondary-bg-rgb:233,236,239;--bs-tertiary-color:rgba(33, 37, 41, .5);--bs-tertiary-color-rgb:33,37,41;--bs-tertiary-bg:#f8f9fa;--bs-tertiary-bg-rgb:248,249,250;--bs-heading-color:inherit;--bs-link-color:#0d6efd;--bs-link-color-rgb:13,110,253;--bs-link-decoration:underline;--bs-link-hover-color:#0a58ca;--bs-link-hover-color-rgb:10,88,202;--bs-code-color:#d63384;--bs-highlight-color:#212529;--bs-highlight-bg:#fff3cd;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, .175);--bs-border-radius:.375rem;--bs-border-radius-sm:.25rem;--bs-border-radius-lg:.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-xxl:2rem;--bs-border-radius-2xl:var(--bs-border-radius-xxl);--bs-border-radius-pill:50rem;--bs-box-shadow:0 .5rem 1rem rgba(0, 0, 0, .15);--bs-box-shadow-sm:0 .125rem .25rem rgba(0, 0, 0, .075);--bs-box-shadow-lg:0 1rem 3rem rgba(0, 0, 0, .175);--bs-box-shadow-inset:inset 0 1px 2px rgba(0, 0, 0, .075);--bs-focus-ring-width:.25rem;--bs-focus-ring-opacity:.25;--bs-focus-ring-color:rgba(13, 110, 253, .25);--bs-form-valid-color:#198754;--bs-form-valid-border-color:#198754;--bs-form-invalid-color:#dc3545;--bs-form-invalid-border-color:#dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color:#dee2e6;--bs-body-color-rgb:222,226,230;--bs-body-bg:#212529;--bs-body-bg-rgb:33,37,41;--bs-emphasis-color:#fff;--bs-emphasis-color-rgb:255,255,255;--bs-secondary-color:rgba(222, 226, 230, .75);--bs-secondary-color-rgb:222,226,230;--bs-secondary-bg:#343a40;--bs-secondary-bg-rgb:52,58,64;--bs-tertiary-color:rgba(222, 226, 230, .5);--bs-tertiary-color-rgb:222,226,230;--bs-tertiary-bg:#2b3035;--bs-tertiary-bg-rgb:43,48,53;--bs-primary-text-emphasis:#6ea8fe;--bs-secondary-text-emphasis:#a7acb1;--bs-success-text-emphasis:#75b798;--bs-info-text-emphasis:#6edff6;--bs-warning-text-emphasis:#ffda6a;--bs-danger-text-emphasis:#ea868f;--bs-light-text-emphasis:#f8f9fa;--bs-dark-text-emphasis:#dee2e6;--bs-primary-bg-subtle:#031633;--bs-secondary-bg-subtle:#161719;--bs-success-bg-subtle:#051b11;--bs-info-bg-subtle:#032830;--bs-warning-bg-subtle:#332701;--bs-danger-bg-subtle:#2c0b0e;--bs-light-bg-subtle:#343a40;--bs-dark-bg-subtle:#1a1d20;--bs-primary-border-subtle:#084298;--bs-secondary-border-subtle:#41464b;--bs-success-border-subtle:#0f5132;--bs-info-border-subtle:#087990;--bs-warning-border-subtle:#997404;--bs-danger-border-subtle:#842029;--bs-light-border-subtle:#495057;--bs-dark-border-subtle:#343a40;--bs-heading-color:inherit;--bs-link-color:#6ea8fe;--bs-link-hover-color:#8bb9fe;--bs-link-color-rgb:110,168,254;--bs-link-hover-color-rgb:139,185,254;--bs-code-color:#e685b5;--bs-highlight-color:#dee2e6;--bs-highlight-bg:#664d03;--bs-border-color:#495057;--bs-border-color-translucent:rgba(255, 255, 255, .15);--bs-form-valid-color:#75b798;--bs-form-valid-border-color:#75b798;--bs-form-invalid-color:#ea868f;--bs-form-invalid-border-color:#ea868f}*,:after,:before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;border:0;border-top:var(--bs-border-width) solid;opacity:.25}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.1875em;color:var(--bs-highlight-color);background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,1));text-decoration:underline}a:hover{--bs-link-color-rgb:var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);word-wrap:break-word}a>code{color:inherit}kbd{padding:.1875rem .375rem;font-size:.875em;color:var(--bs-body-bg);background-color:var(--bs-body-color);border-radius:.25rem}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-secondary-color);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}[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}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;line-height:inherit;font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button{cursor:pointer;filter:grayscale(1)}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-weight:300;line-height:1.2;font-size:calc(1.625rem + 4.5vw)}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-weight:300;line-height:1.2;font-size:calc(1.575rem + 3.9vw)}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-weight:300;line-height:1.2;font-size:calc(1.525rem + 3.3vw)}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-weight:300;line-height:1.2;font-size:calc(1.475rem + 2.7vw)}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-weight:300;line-height:1.2;font-size:calc(1.425rem + 2.1vw)}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-weight:300;line-height:1.2;font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled,.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer:before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:var(--bs-body-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:var(--bs-secondary-color)}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{--bs-gutter-x:1.5rem;--bs-gutter-y:0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}:root{--bs-breakpoint-xs:0;--bs-breakpoint-sm:576px;--bs-breakpoint-md:768px;--bs-breakpoint-lg:992px;--bs-breakpoint-xl:1200px;--bs-breakpoint-xxl:1400px}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--bs-gutter-y));margin-right:calc(-.5 * var(--bs-gutter-x));margin-left:calc(-.5 * var(--bs-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.66666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.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%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:.25rem}.g-1,.gy-1{--bs-gutter-y:.25rem}.g-2,.gx-2{--bs-gutter-x:.5rem}.g-2,.gy-2{--bs-gutter-y:.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{flex:1 0 0}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.66666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.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%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{flex:1 0 0}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.66666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.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%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{flex:1 0 0}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.66666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.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%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{flex:1 0 0}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.66666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.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%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{flex:1 0 0}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.66666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-color-type:initial;--bs-table-bg-type:initial;--bs-table-color-state:initial;--bs-table-bg-state:initial;--bs-table-color:var(--bs-emphasis-color);--bs-table-bg:var(--bs-body-bg);--bs-table-border-color:var(--bs-border-color);--bs-table-accent-bg:transparent;--bs-table-striped-color:var(--bs-emphasis-color);--bs-table-striped-bg:rgba(var(--bs-emphasis-color-rgb), .05);--bs-table-active-color:var(--bs-emphasis-color);--bs-table-active-bg:rgba(var(--bs-emphasis-color-rgb), .1);--bs-table-hover-color:var(--bs-emphasis-color);--bs-table-hover-bg:rgba(var(--bs-emphasis-color-rgb), .075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.5rem;color:var(--bs-table-color-state,var(--bs-table-color-type,var(--bs-table-color)));background-color:var(--bs-table-bg);border-bottom-width:var(--bs-border-width);box-shadow:inset 0 0 0 9999px var(--bs-table-bg-state,var(--bs-table-bg-type,var(--bs-table-accent-bg)))}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-group-divider{border-top:calc(var(--bs-border-width) * 2) solid currentcolor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem}.table-bordered>:not(caption)>*{border-width:var(--bs-border-width) 0}.table-bordered>:not(caption)>*>*{border-width:0 var(--bs-border-width)}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(2n){--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-active{--bs-table-color-state:var(--bs-table-active-color);--bs-table-bg-state:var(--bs-table-active-bg)}.table-hover>tbody>tr:hover>*{--bs-table-color-state:var(--bs-table-hover-color);--bs-table-bg-state:var(--bs-table-hover-bg)}.table-primary{--bs-table-color:#000;--bs-table-bg:#cfe2ff;--bs-table-border-color:#a6b5cc;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color:#000;--bs-table-bg:#e2e3e5;--bs-table-border-color:#b5b6b7;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color:#000;--bs-table-bg:#d1e7dd;--bs-table-border-color:#a7b9b1;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color:#000;--bs-table-bg:#cff4fc;--bs-table-border-color:#a6c3ca;--bs-table-striped-bg:#c5e8ef;--bs-table-striped-color:#000;--bs-table-active-bg:#badce3;--bs-table-active-color:#000;--bs-table-hover-bg:#bfe2e9;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color:#000;--bs-table-bg:#fff3cd;--bs-table-border-color:#ccc2a4;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color:#000;--bs-table-bg:#f8d7da;--bs-table-border-color:#c6acae;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color:#000;--bs-table-bg:#f8f9fa;--bs-table-border-color:#c6c7c8;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color:#fff;--bs-table-bg:#212529;--bs-table-border-color:#4d5154;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + var(--bs-border-width));padding-bottom:calc(.375rem + var(--bs-border-width));margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + var(--bs-border-width));padding-bottom:calc(.5rem + var(--bs-border-width));font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + var(--bs-border-width));padding-bottom:calc(.25rem + var(--bs-border-width));font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:var(--bs-secondary-color)}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.5em;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:var(--bs-secondary-color);opacity:1}.form-control:disabled{background-color:var(--bs-secondary-bg);opacity:1}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:var(--bs-secondary-bg)}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--bs-secondary-bg)}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:var(--bs-body-color);background-color:transparent;border:solid transparent;border-width:var(--bs-border-width) 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2));padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2));padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2))}textarea.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}textarea.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-control-color{width:3rem;height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2));padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0!important;border-radius:var(--bs-border-radius)}.form-control-color::-webkit-color-swatch{border:0!important;border-radius:var(--bs-border-radius)}.form-control-color.form-control-sm{height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon,none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:var(--bs-secondary-bg)}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 var(--bs-body-color)}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}[data-bs-theme=dark] .form-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-reverse{padding-right:1.5em;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-1.5em;margin-left:0}.form-check-input{--bs-form-check-bg:var(--bs-body-bg);flex-shrink:0;width:1em;height:1em;margin-top:.25em;vertical-align:top;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-form-check-bg);background-image:var(--bs-form-check-bg-image);background-repeat:no-repeat;background-position:center;background-size:contain;border:var(--bs-border-width) solid var(--bs-border-color);-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{cursor:default;opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;filter:none;opacity:.65}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.form-range{width:100%;height:1.5rem;padding:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem #0d6efd40}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem #0d6efd40}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;-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}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-secondary-bg);border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;-moz-appearance:none;-webkit-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius: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}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-secondary-bg);border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:var(--bs-secondary-color)}.form-range:disabled::-moz-range-thumb{background-color:var(--bs-secondary-color)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(var(--bs-border-width) * 2));min-height:calc(3.5rem + calc(var(--bs-border-width) * 2));line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;z-index:2;max-width:100%;height:100%;padding:1rem .75rem;overflow:hidden;color:rgba(var(--bs-body-color-rgb),.65);text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:var(--bs-border-width) solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control-plaintext::placeholder,.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown),.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control-plaintext:-webkit-autofill,.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem;padding-left:.75rem}.form-floating>.form-control-plaintext~label,.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{transform:scale(.85) translateY(-.5rem) translate(.15rem)}.form-floating>.form-control:-webkit-autofill~label{transform:scale(.85) translateY(-.5rem) translate(.15rem)}.form-floating>textarea:focus~label:after,.form-floating>textarea:not(:placeholder-shown)~label:after{position:absolute;top:1rem;right:.375rem;bottom:1rem;left:.375rem;z-index:-1;height:1.5em;content:"";background-color:var(--bs-body-bg);border-radius:var(--bs-border-radius)}.form-floating>textarea:disabled~label:after{background-color:var(--bs-secondary-bg)}.form-floating>.form-control-plaintext~label{border-width:var(--bs-border-width) 0}.form-floating>.form-control:disabled~label,.form-floating>:disabled~label{color:#6c757d}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-floating,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-floating:focus-within,.input-group>.form-select:focus{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);text-align:center;white-space:nowrap;background-color:var(--bs-tertiary-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius)}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select,.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select,.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:calc(-1 * var(--bs-border-width));border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--bs-form-valid-color)}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-success);border-radius:var(--bs-border-radius)}.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{border-color:var(--bs-form-valid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' 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.1'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:var(--bs-form-valid-border-color)}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{--bs-form-select-bg-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' 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.1'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-control-color.is-valid,.was-validated .form-control-color:valid{width:calc(3.75rem + 1.5em)}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:var(--bs-form-valid-border-color)}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:var(--bs-form-valid-color)}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:var(--bs-form-valid-color)}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-valid,.input-group>.form-floating:not(:focus-within).is-valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-control:not(:focus):valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.was-validated .input-group>.form-select:not(:focus):valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--bs-form-invalid-color)}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-danger);border-radius:var(--bs-border-radius)}.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{border-color:var(--bs-form-invalid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%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='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:var(--bs-form-invalid-border-color)}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{--bs-form-select-bg-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%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='%23dc3545' stroke='none'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-control-color.is-invalid,.was-validated .form-control-color:invalid{width:calc(3.75rem + 1.5em)}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:var(--bs-form-invalid-border-color)}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:var(--bs-form-invalid-color)}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:var(--bs-form-invalid-color)}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-invalid,.input-group>.form-floating:not(:focus-within).is-invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-control:not(:focus):invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.was-validated .input-group>.form-select:not(:focus):invalid{z-index:4}.btn{--bs-btn-padding-x:.75rem;--bs-btn-padding-y:.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:var(--bs-body-color);--bs-btn-bg:transparent;--bs-btn-border-width:var(--bs-border-width);--bs-btn-border-color:transparent;--bs-btn-border-radius:var(--bs-border-radius);--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 rgba(255, 255, 255, .15),0 1px 1px rgba(0, 0, 0, .075);--bs-btn-disabled-opacity:.65;--bs-btn-focus-box-shadow:0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn-check:checked+.btn:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible,.btn:first-child:active:focus-visible,:not(.btn-check)+.btn:active:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked:focus-visible+.btn{box-shadow:var(--bs-btn-focus-box-shadow)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity)}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0b5ed7;--bs-btn-hover-border-color:#0a58ca;--bs-btn-focus-shadow-rgb:49,132,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0a58ca;--bs-btn-active-border-color:#0a53be;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#0d6efd;--bs-btn-disabled-border-color:#0d6efd}.btn-secondary{--bs-btn-color:#fff;--bs-btn-bg:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#5c636a;--bs-btn-hover-border-color:#565e64;--bs-btn-focus-shadow-rgb:130,138,145;--bs-btn-active-color:#fff;--bs-btn-active-bg:#565e64;--bs-btn-active-border-color:#51585e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#6c757d;--bs-btn-disabled-border-color:#6c757d}.btn-success{--bs-btn-color:#fff;--bs-btn-bg:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#157347;--bs-btn-hover-border-color:#146c43;--bs-btn-focus-shadow-rgb:60,153,110;--bs-btn-active-color:#fff;--bs-btn-active-bg:#146c43;--bs-btn-active-border-color:#13653f;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#198754;--bs-btn-disabled-border-color:#198754}.btn-info{--bs-btn-color:#000;--bs-btn-bg:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#31d2f2;--bs-btn-hover-border-color:#25cff2;--bs-btn-focus-shadow-rgb:11,172,204;--bs-btn-active-color:#000;--bs-btn-active-bg:#3dd5f3;--bs-btn-active-border-color:#25cff2;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#0dcaf0;--bs-btn-disabled-border-color:#0dcaf0}.btn-warning{--bs-btn-color:#000;--bs-btn-bg:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffca2c;--bs-btn-hover-border-color:#ffc720;--bs-btn-focus-shadow-rgb:217,164,6;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffcd39;--bs-btn-active-border-color:#ffc720;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#ffc107;--bs-btn-disabled-border-color:#ffc107}.btn-danger{--bs-btn-color:#fff;--bs-btn-bg:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#bb2d3b;--bs-btn-hover-border-color:#b02a37;--bs-btn-focus-shadow-rgb:225,83,97;--bs-btn-active-color:#fff;--bs-btn-active-bg:#b02a37;--bs-btn-active-border-color:#a52834;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#dc3545;--bs-btn-disabled-border-color:#dc3545}.btn-light{--bs-btn-color:#000;--bs-btn-bg:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#d3d4d5;--bs-btn-hover-border-color:#c6c7c8;--bs-btn-focus-shadow-rgb:211,212,213;--bs-btn-active-color:#000;--bs-btn-active-bg:#c6c7c8;--bs-btn-active-border-color:#babbbc;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#f8f9fa;--bs-btn-disabled-border-color:#f8f9fa}.btn-dark{--bs-btn-color:#fff;--bs-btn-bg:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#424649;--bs-btn-hover-border-color:#373b3e;--bs-btn-focus-shadow-rgb:66,70,73;--bs-btn-active-color:#fff;--bs-btn-active-bg:#4d5154;--bs-btn-active-border-color:#373b3e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#212529;--bs-btn-disabled-border-color:#212529}.btn-outline-primary{--bs-btn-color:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0d6efd;--bs-btn-hover-border-color:#0d6efd;--bs-btn-focus-shadow-rgb:13,110,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0d6efd;--bs-btn-active-border-color:#0d6efd;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#0d6efd;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0d6efd;--bs-gradient:none}.btn-outline-secondary{--bs-btn-color:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#6c757d;--bs-btn-hover-border-color:#6c757d;--bs-btn-focus-shadow-rgb:108,117,125;--bs-btn-active-color:#fff;--bs-btn-active-bg:#6c757d;--bs-btn-active-border-color:#6c757d;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#6c757d;--bs-gradient:none}.btn-outline-success{--bs-btn-color:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#198754;--bs-btn-hover-border-color:#198754;--bs-btn-focus-shadow-rgb:25,135,84;--bs-btn-active-color:#fff;--bs-btn-active-bg:#198754;--bs-btn-active-border-color:#198754;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#198754;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#198754;--bs-gradient:none}.btn-outline-info{--bs-btn-color:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#0dcaf0;--bs-btn-hover-border-color:#0dcaf0;--bs-btn-focus-shadow-rgb:13,202,240;--bs-btn-active-color:#000;--bs-btn-active-bg:#0dcaf0;--bs-btn-active-border-color:#0dcaf0;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#0dcaf0;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0dcaf0;--bs-gradient:none}.btn-outline-warning{--bs-btn-color:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffc107;--bs-btn-hover-border-color:#ffc107;--bs-btn-focus-shadow-rgb:255,193,7;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffc107;--bs-btn-active-border-color:#ffc107;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#ffc107;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ffc107;--bs-gradient:none}.btn-outline-danger{--bs-btn-color:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#dc3545;--bs-btn-hover-border-color:#dc3545;--bs-btn-focus-shadow-rgb:220,53,69;--bs-btn-active-color:#fff;--bs-btn-active-bg:#dc3545;--bs-btn-active-border-color:#dc3545;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#dc3545;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#dc3545;--bs-gradient:none}.btn-outline-light{--bs-btn-color:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#f8f9fa;--bs-btn-hover-border-color:#f8f9fa;--bs-btn-focus-shadow-rgb:248,249,250;--bs-btn-active-color:#000;--bs-btn-active-bg:#f8f9fa;--bs-btn-active-border-color:#f8f9fa;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#f8f9fa;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#f8f9fa;--bs-gradient:none}.btn-outline-dark{--bs-btn-color:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#212529;--bs-btn-hover-border-color:#212529;--bs-btn-focus-shadow-rgb:33,37,41;--bs-btn-active-color:#fff;--bs-btn-active-bg:#212529;--bs-btn-active-border-color:#212529;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color:#212529;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#212529;--bs-gradient:none}.btn-link{--bs-btn-font-weight:400;--bs-btn-color:var(--bs-link-color);--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-hover-color:var(--bs-link-hover-color);--bs-btn-hover-border-color:transparent;--bs-btn-active-color:var(--bs-link-hover-color);--bs-btn-active-border-color:transparent;--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-border-color:transparent;--bs-btn-box-shadow:0 0 0 #000;--bs-btn-focus-shadow-rgb:49,132,253;text-decoration:underline}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-group-lg>.btn,.btn-lg{--bs-btn-padding-y:.5rem;--bs-btn-padding-x:1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius:var(--bs-border-radius-lg)}.btn-group-sm>.btn,.btn-sm{--bs-btn-padding-y:.25rem;--bs-btn-padding-x:.5rem;--bs-btn-font-size:.875rem;--bs-btn-border-radius:var(--bs-border-radius-sm)}.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;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropdown,.dropdown-center,.dropend,.dropstart,.dropup,.dropup-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex:1000;--bs-dropdown-min-width:10rem;--bs-dropdown-padding-x:0;--bs-dropdown-padding-y:.5rem;--bs-dropdown-spacer:.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color:var(--bs-body-color);--bs-dropdown-bg:var(--bs-body-bg);--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-border-radius:var(--bs-border-radius);--bs-dropdown-border-width:var(--bs-border-width);--bs-dropdown-inner-border-radius:calc(var(--bs-border-radius) - var(--bs-border-width));--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-divider-margin-y:.5rem;--bs-dropdown-box-shadow:var(--bs-box-shadow);--bs-dropdown-link-color:var(--bs-body-color);--bs-dropdown-link-hover-color:var(--bs-body-color);--bs-dropdown-link-hover-bg:var(--bs-tertiary-bg);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:var(--bs-tertiary-color);--bs-dropdown-item-padding-x:1rem;--bs-dropdown-item-padding-y:.25rem;--bs-dropdown-header-color:#6c757d;--bs-dropdown-header-padding-x:1rem;--bs-dropdown-header-padding-y:.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty:after{margin-left:0}.dropend .dropdown-toggle:after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle:after{display:none}.dropstart .dropdown-toggle:before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty:after{margin-left:0}.dropstart .dropdown-toggle:before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0;border-radius:var(--bs-dropdown-item-border-radius,0)}.dropdown-item:focus,.dropdown-item:hover{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color:#dee2e6;--bs-dropdown-bg:#343a40;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color:#dee2e6;--bs-dropdown-link-hover-color:#fff;--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-link-hover-bg:rgba(255, 255, 255, .15);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-header-color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.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{border-radius:var(--bs-border-radius)}.btn-group>.btn-group:not(:first-child),.btn-group>:not(.btn-check:first-child)+.btn{margin-left:calc(-1 * var(--bs-border-width))}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split:after,.dropend .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropstart .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;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:calc(-1 * var(--bs-border-width))}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:nth-child(n+3),.btn-group-vertical>:not(.btn-check)+.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x:1rem;--bs-nav-link-padding-y:.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-link-color);--bs-nav-link-hover-color:var(--bs-link-hover-color);--bs-nav-link-disabled-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;background:0 0;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.nav-link.disabled,.nav-link:disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width:var(--bs-border-width);--bs-nav-tabs-border-color:var(--bs-border-color);--bs-nav-tabs-border-radius:var(--bs-border-radius);--bs-nav-tabs-link-hover-border-color:var(--bs-secondary-bg) var(--bs-secondary-bg) var(--bs-border-color);--bs-nav-tabs-link-active-color:var(--bs-emphasis-color);--bs-nav-tabs-link-active-bg:var(--bs-body-bg);--bs-nav-tabs-link-active-border-color:var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg);border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1 * var(--bs-nav-tabs-border-width));border:var(--bs-nav-tabs-border-width) solid transparent;border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius:var(--bs-border-radius);--bs-nav-pills-link-active-color:#fff;--bs-nav-pills-link-active-bg:#0d6efd}.nav-pills .nav-link{border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-underline{--bs-nav-underline-gap:1rem;--bs-nav-underline-border-width:.125rem;--bs-nav-underline-link-active-color:var(--bs-emphasis-color);gap:var(--bs-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--bs-nav-underline-border-width) solid transparent}.nav-underline .nav-link:focus,.nav-underline .nav-link:hover{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:700;color:var(--bs-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-grow:1;flex-basis:0;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:.5rem;--bs-navbar-color:rgba(var(--bs-emphasis-color-rgb), .65);--bs-navbar-hover-color:rgba(var(--bs-emphasis-color-rgb), .8);--bs-navbar-disabled-color:rgba(var(--bs-emphasis-color-rgb), .3);--bs-navbar-active-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-padding-y:.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-hover-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-nav-link-padding-x:.5rem;--bs-navbar-toggler-padding-y:.25rem;--bs-navbar-toggler-padding-x:.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2833, 37, 41, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color:rgba(var(--bs-emphasis-color-rgb), .15);--bs-navbar-toggler-border-radius:var(--bs-border-radius);--bs-navbar-toggler-focus-width:.25rem;--bs-navbar-toggler-transition:box-shadow .15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:focus,.navbar-text a:hover{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-grow:1;flex-basis:100%;align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:transparent;border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{flex-wrap: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-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.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}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:768px){.navbar-expand-md{flex-wrap: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-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.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}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:992px){.navbar-expand-lg{flex-wrap: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-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.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}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap: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-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.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-xl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark]{--bs-navbar-color:rgba(255, 255, 255, .55);--bs-navbar-hover-color:rgba(255, 255, 255, .75);--bs-navbar-disabled-color:rgba(255, 255, 255, .25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:rgba(255, 255, 255, .1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon{--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width:var(--bs-border-width);--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:var(--bs-border-radius);--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-card-cap-padding-y:.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(var(--bs-body-color-rgb), .03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:var(--bs-body-bg);--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:.75rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--bs-card-height);color:var(--bs-body-color);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y);color:var(--bs-card-title-color)}.card-subtitle{margin-top:calc(-.5 * var(--bs-card-title-spacer-y));margin-bottom:0;color:var(--bs-card-subtitle-color)}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.card-footer{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-bottom:calc(-1 * var(--bs-card-cap-padding-y));margin-left:calc(-.5 * var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-left:calc(-.5 * var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--bs-card-group-margin)}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-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-top-left-radius:0;border-bottom-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}}.accordion{--bs-accordion-color:var(--bs-body-color);--bs-accordion-bg:var(--bs-body-bg);--bs-accordion-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease;--bs-accordion-border-color:var(--bs-border-color);--bs-accordion-border-width:var(--bs-border-width);--bs-accordion-border-radius:var(--bs-border-radius);--bs-accordion-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-accordion-btn-padding-x:1.25rem;--bs-accordion-btn-padding-y:1rem;--bs-accordion-btn-color:var(--bs-body-color);--bs-accordion-btn-bg:var(--bs-accordion-bg);--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23212529' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width:1.25rem;--bs-accordion-btn-icon-transform:rotate(-180deg);--bs-accordion-btn-icon-transition:transform .2s ease-in-out;--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23052c65' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");--bs-accordion-btn-focus-box-shadow:0 0 0 .25rem rgba(13, 110, 253, .25);--bs-accordion-body-padding-x:1.25rem;--bs-accordion-body-padding-y:1rem;--bs-accordion-active-color:var(--bs-primary-text-emphasis);--bs-accordion-active-bg:var(--bs-primary-bg-subtle)}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed):after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button:after{flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media (prefers-reduced-motion:reduce){.accordion-button:after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type>.accordion-header .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type>.accordion-header .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type>.accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x)}.accordion-flush>.accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush>.accordion-item:first-child{border-top:0}.accordion-flush>.accordion-item:last-child{border-bottom:0}.accordion-flush>.accordion-item>.accordion-collapse,.accordion-flush>.accordion-item>.accordion-header .accordion-button,.accordion-flush>.accordion-item>.accordion-header .accordion-button.collapsed{border-radius:0}[data-bs-theme=dark] .accordion-button:after{--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e");--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e")}.breadcrumb{--bs-breadcrumb-padding-x:0;--bs-breadcrumb-padding-y:0;--bs-breadcrumb-margin-bottom:1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: ;--bs-breadcrumb-divider-color:var(--bs-secondary-color);--bs-breadcrumb-item-padding-x:.5rem;--bs-breadcrumb-item-active-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item:before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x:.75rem;--bs-pagination-padding-y:.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color:var(--bs-link-color);--bs-pagination-bg:var(--bs-body-bg);--bs-pagination-border-width:var(--bs-border-width);--bs-pagination-border-color:var(--bs-border-color);--bs-pagination-border-radius:var(--bs-border-radius);--bs-pagination-hover-color:var(--bs-link-hover-color);--bs-pagination-hover-bg:var(--bs-tertiary-bg);--bs-pagination-hover-border-color:var(--bs-border-color);--bs-pagination-focus-color:var(--bs-link-hover-color);--bs-pagination-focus-bg:var(--bs-secondary-bg);--bs-pagination-focus-box-shadow:0 0 0 .25rem rgba(13, 110, 253, .25);--bs-pagination-active-color:#fff;--bs-pagination-active-bg:#0d6efd;--bs-pagination-active-border-color:#0d6efd;--bs-pagination-disabled-color:var(--bs-secondary-color);--bs-pagination-disabled-bg:var(--bs-secondary-bg);--bs-pagination-disabled-border-color:var(--bs-border-color);display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y) var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.active>.page-link,.page-link.active{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.disabled>.page-link,.page-link.disabled{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:calc(-1 * var(--bs-border-width))}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x:1.5rem;--bs-pagination-padding-y:.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius:var(--bs-border-radius-lg)}.pagination-sm{--bs-pagination-padding-x:.5rem;--bs-pagination-padding-y:.25rem;--bs-pagination-font-size:.875rem;--bs-pagination-border-radius:var(--bs-border-radius-sm)}.badge{--bs-badge-padding-x:.65em;--bs-badge-padding-y:.35em;--bs-badge-font-size:.75em;--bs-badge-font-weight:700;--bs-badge-color:#fff;--bs-badge-border-radius:var(--bs-border-radius);display:inline-block;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius)}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:var(--bs-border-width) solid var(--bs-alert-border-color);--bs-alert-border-radius:var(--bs-border-radius);--bs-alert-link-color:inherit;position:relative;padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700;color:var(--bs-alert-link-color)}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{--bs-alert-color:var(--bs-primary-text-emphasis);--bs-alert-bg:var(--bs-primary-bg-subtle);--bs-alert-border-color:var(--bs-primary-border-subtle);--bs-alert-link-color:var(--bs-primary-text-emphasis)}.alert-secondary{--bs-alert-color:var(--bs-secondary-text-emphasis);--bs-alert-bg:var(--bs-secondary-bg-subtle);--bs-alert-border-color:var(--bs-secondary-border-subtle);--bs-alert-link-color:var(--bs-secondary-text-emphasis)}.alert-success{--bs-alert-color:var(--bs-success-text-emphasis);--bs-alert-bg:var(--bs-success-bg-subtle);--bs-alert-border-color:var(--bs-success-border-subtle);--bs-alert-link-color:var(--bs-success-text-emphasis)}.alert-info{--bs-alert-color:var(--bs-info-text-emphasis);--bs-alert-bg:var(--bs-info-bg-subtle);--bs-alert-border-color:var(--bs-info-border-subtle);--bs-alert-link-color:var(--bs-info-text-emphasis)}.alert-warning{--bs-alert-color:var(--bs-warning-text-emphasis);--bs-alert-bg:var(--bs-warning-bg-subtle);--bs-alert-border-color:var(--bs-warning-border-subtle);--bs-alert-link-color:var(--bs-warning-text-emphasis)}.alert-danger{--bs-alert-color:var(--bs-danger-text-emphasis);--bs-alert-bg:var(--bs-danger-bg-subtle);--bs-alert-border-color:var(--bs-danger-border-subtle);--bs-alert-link-color:var(--bs-danger-text-emphasis)}.alert-light{--bs-alert-color:var(--bs-light-text-emphasis);--bs-alert-bg:var(--bs-light-bg-subtle);--bs-alert-border-color:var(--bs-light-border-subtle);--bs-alert-link-color:var(--bs-light-text-emphasis)}.alert-dark{--bs-alert-color:var(--bs-dark-text-emphasis);--bs-alert-bg:var(--bs-dark-bg-subtle);--bs-alert-border-color:var(--bs-dark-border-subtle);--bs-alert-link-color:var(--bs-dark-text-emphasis)}@keyframes progress-bar-stripes{0%{background-position-x:var(--bs-progress-height)}}.progress,.progress-stacked{--bs-progress-height:1rem;--bs-progress-font-size:.75rem;--bs-progress-bg:var(--bs-secondary-bg);--bs-progress-border-radius:var(--bs-border-radius);--bs-progress-box-shadow:var(--bs-box-shadow-inset);--bs-progress-bar-color:#fff;--bs-progress-bar-bg:#0d6efd;--bs-progress-bar-transition:width .6s ease;display:flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius)}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:var(--bs-progress-height) var(--bs-progress-height)}.progress-stacked>.progress{overflow:visible}.progress-stacked>.progress>.progress-bar{width:100%}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color:var(--bs-body-color);--bs-list-group-bg:var(--bs-body-bg);--bs-list-group-border-color:var(--bs-border-color);--bs-list-group-border-width:var(--bs-border-width);--bs-list-group-border-radius:var(--bs-border-radius);--bs-list-group-item-padding-x:1rem;--bs-list-group-item-padding-y:.5rem;--bs-list-group-action-color:var(--bs-secondary-color);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-tertiary-bg);--bs-list-group-action-active-color:var(--bs-body-color);--bs-list-group-action-active-bg:var(--bs-secondary-bg);--bs-list-group-disabled-color:var(--bs-secondary-color);--bs-list-group-disabled-bg:var(--bs-body-bg);--bs-list-group-active-color:#fff;--bs-list-group-active-bg:#0d6efd;--bs-list-group-active-border-color:#0d6efd;display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item:before{content:counters(section,".") ". ";counter-increment:section}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width) solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1 * var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:not(.active):focus,.list-group-item-action:not(.active):hover{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:not(.active):active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{--bs-list-group-color:var(--bs-primary-text-emphasis);--bs-list-group-bg:var(--bs-primary-bg-subtle);--bs-list-group-border-color:var(--bs-primary-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-primary-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-primary-border-subtle);--bs-list-group-active-color:var(--bs-primary-bg-subtle);--bs-list-group-active-bg:var(--bs-primary-text-emphasis);--bs-list-group-active-border-color:var(--bs-primary-text-emphasis)}.list-group-item-secondary{--bs-list-group-color:var(--bs-secondary-text-emphasis);--bs-list-group-bg:var(--bs-secondary-bg-subtle);--bs-list-group-border-color:var(--bs-secondary-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-secondary-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-secondary-border-subtle);--bs-list-group-active-color:var(--bs-secondary-bg-subtle);--bs-list-group-active-bg:var(--bs-secondary-text-emphasis);--bs-list-group-active-border-color:var(--bs-secondary-text-emphasis)}.list-group-item-success{--bs-list-group-color:var(--bs-success-text-emphasis);--bs-list-group-bg:var(--bs-success-bg-subtle);--bs-list-group-border-color:var(--bs-success-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-success-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-success-border-subtle);--bs-list-group-active-color:var(--bs-success-bg-subtle);--bs-list-group-active-bg:var(--bs-success-text-emphasis);--bs-list-group-active-border-color:var(--bs-success-text-emphasis)}.list-group-item-info{--bs-list-group-color:var(--bs-info-text-emphasis);--bs-list-group-bg:var(--bs-info-bg-subtle);--bs-list-group-border-color:var(--bs-info-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-info-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-info-border-subtle);--bs-list-group-active-color:var(--bs-info-bg-subtle);--bs-list-group-active-bg:var(--bs-info-text-emphasis);--bs-list-group-active-border-color:var(--bs-info-text-emphasis)}.list-group-item-warning{--bs-list-group-color:var(--bs-warning-text-emphasis);--bs-list-group-bg:var(--bs-warning-bg-subtle);--bs-list-group-border-color:var(--bs-warning-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-warning-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-warning-border-subtle);--bs-list-group-active-color:var(--bs-warning-bg-subtle);--bs-list-group-active-bg:var(--bs-warning-text-emphasis);--bs-list-group-active-border-color:var(--bs-warning-text-emphasis)}.list-group-item-danger{--bs-list-group-color:var(--bs-danger-text-emphasis);--bs-list-group-bg:var(--bs-danger-bg-subtle);--bs-list-group-border-color:var(--bs-danger-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-danger-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-danger-border-subtle);--bs-list-group-active-color:var(--bs-danger-bg-subtle);--bs-list-group-active-bg:var(--bs-danger-text-emphasis);--bs-list-group-active-border-color:var(--bs-danger-text-emphasis)}.list-group-item-light{--bs-list-group-color:var(--bs-light-text-emphasis);--bs-list-group-bg:var(--bs-light-bg-subtle);--bs-list-group-border-color:var(--bs-light-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-light-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-light-border-subtle);--bs-list-group-active-color:var(--bs-light-bg-subtle);--bs-list-group-active-bg:var(--bs-light-text-emphasis);--bs-list-group-active-border-color:var(--bs-light-text-emphasis)}.list-group-item-dark{--bs-list-group-color:var(--bs-dark-text-emphasis);--bs-list-group-bg:var(--bs-dark-bg-subtle);--bs-list-group-border-color:var(--bs-dark-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-dark-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-dark-border-subtle);--bs-list-group-active-color:var(--bs-dark-bg-subtle);--bs-list-group-active-bg:var(--bs-dark-text-emphasis);--bs-list-group-active-border-color:var(--bs-dark-text-emphasis)}.btn-close{--bs-btn-close-color:#000;--bs-btn-close-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3e%3c/svg%3e");--bs-btn-close-opacity:.5;--bs-btn-close-hover-opacity:.75;--bs-btn-close-focus-shadow:0 0 0 .25rem rgba(13, 110, 253, .25);--bs-btn-close-focus-opacity:1;--bs-btn-close-disabled-opacity:.25;box-sizing:content-box;width:1em;height:1em;padding:.25em;color:var(--bs-btn-close-color);background:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;filter:var(--bs-btn-close-filter);border:0;border-radius:.375rem;opacity:var(--bs-btn-close-opacity)}.btn-close:hover{color:var(--bs-btn-close-color);text-decoration:none;opacity:var(--bs-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity)}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:var(--bs-btn-close-disabled-opacity)}.btn-close-white{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}:root,[data-bs-theme=light]{--bs-btn-close-filter: }[data-bs-theme=dark]{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:.75rem;--bs-toast-padding-y:.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(var(--bs-body-bg-rgb), .85);--bs-toast-border-width:var(--bs-border-width);--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:var(--bs-border-radius);--bs-toast-box-shadow:var(--bs-box-shadow);--bs-toast-header-color:var(--bs-secondary-color);--bs-toast-header-bg:rgba(var(--bs-body-bg-rgb), .85);--bs-toast-header-border-color:var(--bs-border-color-translucent);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex:1090;position:absolute;z-index:var(--bs-toast-zindex);width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;align-items:center;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-.5 * var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:.5rem;--bs-modal-color:var(--bs-body-color);--bs-modal-bg:var(--bs-body-bg);--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:var(--bs-border-width);--bs-modal-border-radius:var(--bs-border-radius-lg);--bs-modal-box-shadow:var(--bs-box-shadow-sm);--bs-modal-inner-border-radius:calc(var(--bs-border-radius-lg) - (var(--bs-border-width)));--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:var(--bs-border-width);--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:var(--bs-border-width);position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.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{height:calc(100% - var(--bs-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--bs-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-backdrop{--bs-backdrop-zindex:1050;--bs-backdrop-bg:#000;--bs-backdrop-opacity:.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y) * .5) calc(var(--bs-modal-header-padding-x) * .5);margin-top:calc(-.5 * var(--bs-modal-header-padding-y));margin-right:calc(-.5 * var(--bs-modal-header-padding-x));margin-bottom:calc(-.5 * var(--bs-modal-header-padding-y));margin-left:auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap) * .5)}@media (min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:var(--bs-box-shadow)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{--bs-modal-width:800px}}@media (min-width:1200px){.modal-xl{--bs-modal-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-footer,.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-footer,.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-footer,.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-footer,.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-footer,.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-footer,.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex:1080;--bs-tooltip-max-width:200px;--bs-tooltip-padding-x:.5rem;--bs-tooltip-padding-y:.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:.875rem;--bs-tooltip-color:var(--bs-body-bg);--bs-tooltip-bg:var(--bs-emphasis-color);--bs-tooltip-border-radius:var(--bs-border-radius);--bs-tooltip-opacity:.9;--bs-tooltip-arrow-width:.8rem;--bs-tooltip-arrow-height:.4rem;z-index:var(--bs-tooltip-zindex);display:block;margin:var(--bs-tooltip-margin);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow:before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:calc(-1 * var(--bs-tooltip-arrow-height))}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow:before,.bs-tooltip-top .tooltip-arrow:before{top:-1px;border-width:var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:calc(-1 * var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow:before,.bs-tooltip-end .tooltip-arrow:before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:calc(-1 * var(--bs-tooltip-arrow-height))}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow:before,.bs-tooltip-bottom .tooltip-arrow:before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:calc(-1 * var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow:before,.bs-tooltip-start .tooltip-arrow:before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) 0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex:1070;--bs-popover-max-width:276px;--bs-popover-font-size:.875rem;--bs-popover-bg:var(--bs-body-bg);--bs-popover-border-width:var(--bs-border-width);--bs-popover-border-color:var(--bs-border-color-translucent);--bs-popover-border-radius:var(--bs-border-radius-lg);--bs-popover-inner-border-radius:calc(var(--bs-border-radius-lg) - var(--bs-border-width));--bs-popover-box-shadow:var(--bs-box-shadow);--bs-popover-header-padding-x:1rem;--bs-popover-header-padding-y:.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color:inherit;--bs-popover-header-bg:var(--bs-secondary-bg);--bs-popover-body-padding-x:1rem;--bs-popover-body-padding-y:1rem;--bs-popover-body-color:var(--bs-body-color);--bs-popover-arrow-width:1rem;--bs-popover-arrow-height:.5rem;--bs-popover-arrow-border:var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow:after,.popover .popover-arrow:before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid;border-width:0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:before,.bs-popover-top>.popover-arrow:after,.bs-popover-top>.popover-arrow:before{border-width:var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:before,.bs-popover-top>.popover-arrow:before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:after,.bs-popover-top>.popover-arrow:after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:before,.bs-popover-end>.popover-arrow:after,.bs-popover-end>.popover-arrow:before{border-width:calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:before,.bs-popover-end>.popover-arrow:before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:after,.bs-popover-end>.popover-arrow:after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:before,.bs-popover-bottom>.popover-arrow:after,.bs-popover-bottom>.popover-arrow:before{border-width:0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:before,.bs-popover-bottom>.popover-arrow:before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:after,.bs-popover-bottom>.popover-arrow:after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-.5 * var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-header-bg)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:before,.bs-popover-start>.popover-arrow:after,.bs-popover-start>.popover-arrow:before{border-width:calc(var(--bs-popover-arrow-width) * .5) 0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:before,.bs-popover-start>.popover-arrow:before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:after,.bs-popover-start>.popover-arrow:after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner:after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translate(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translate(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;filter:var(--bs-carousel-control-icon-filter);border:0;opacity:.5;transition:opacity .15s ease}@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;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:var(--bs-carousel-indicator-active-bg);background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:var(--bs-carousel-caption-color);text-align:center}.carousel-dark{--bs-carousel-indicator-active-bg:#000;--bs-carousel-caption-color:#000;--bs-carousel-control-icon-filter:invert(1) grayscale(100)}:root,[data-bs-theme=light]{--bs-carousel-indicator-active-bg:#fff;--bs-carousel-caption-color:#fff;--bs-carousel-control-icon-filter: }[data-bs-theme=dark]{--bs-carousel-indicator-active-bg:#000;--bs-carousel-caption-color:#000;--bs-carousel-control-icon-filter:invert(1) grayscale(100)}.spinner-border,.spinner-grow{display:inline-block;flex-shrink:0;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-.125em;--bs-spinner-border-width:.25em;--bs-spinner-animation-speed:.75s;--bs-spinner-animation-name:spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:transparent}.spinner-border-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem;--bs-spinner-border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-.125em;--bs-spinner-animation-speed:.75s;--bs-spinner-animation-name:spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed:1.5s}}.offcanvas,.offcanvas-lg,.offcanvas-md,.offcanvas-sm,.offcanvas-xl,.offcanvas-xxl{--bs-offcanvas-zindex:1045;--bs-offcanvas-width:400px;--bs-offcanvas-height:30vh;--bs-offcanvas-padding-x:1rem;--bs-offcanvas-padding-y:1rem;--bs-offcanvas-color:var(--bs-body-color);--bs-offcanvas-bg:var(--bs-body-bg);--bs-offcanvas-border-width:var(--bs-border-width);--bs-offcanvas-border-color:var(--bs-border-color-translucent);--bs-offcanvas-box-shadow:var(--bs-box-shadow-sm);--bs-offcanvas-transition:transform .3s ease-in-out;--bs-offcanvas-title-line-height:1.5}@media (max-width:575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:575.98px) and (prefers-reduced-motion:reduce){.offcanvas-sm{transition:none}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.show:not(.hiding),.offcanvas-sm.showing{transform:none}.offcanvas-sm.hiding,.offcanvas-sm.show,.offcanvas-sm.showing{visibility:visible}}@media (min-width:576px){.offcanvas-sm{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:767.98px) and (prefers-reduced-motion:reduce){.offcanvas-md{transition:none}}@media (max-width:767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.show:not(.hiding),.offcanvas-md.showing{transform:none}.offcanvas-md.hiding,.offcanvas-md.show,.offcanvas-md.showing{visibility:visible}}@media (min-width:768px){.offcanvas-md{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:991.98px) and (prefers-reduced-motion:reduce){.offcanvas-lg{transition:none}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.show:not(.hiding),.offcanvas-lg.showing{transform:none}.offcanvas-lg.hiding,.offcanvas-lg.show,.offcanvas-lg.showing{visibility:visible}}@media (min-width:992px){.offcanvas-lg{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:1199.98px) and (prefers-reduced-motion:reduce){.offcanvas-xl{transition:none}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.show:not(.hiding),.offcanvas-xl.showing{transform:none}.offcanvas-xl.hiding,.offcanvas-xl.show,.offcanvas-xl.showing{visibility:visible}}@media (min-width:1200px){.offcanvas-xl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:1399.98px) and (prefers-reduced-motion:reduce){.offcanvas-xxl{transition:none}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.show:not(.hiding),.offcanvas-xxl.showing{transform:none}.offcanvas-xxl.hiding,.offcanvas-xxl.show,.offcanvas-xxl.showing{visibility:visible}}@media (min-width:1400px){.offcanvas-xxl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translate(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.show:not(.hiding),.offcanvas.showing{transform:none}.offcanvas.hiding,.offcanvas.show,.offcanvas.showing{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;align-items:center;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y) * .5) calc(var(--bs-offcanvas-padding-x) * .5);margin-top:calc(-.5 * var(--bs-offcanvas-padding-y));margin-right:calc(-.5 * var(--bs-offcanvas-padding-x));margin-bottom:calc(-.5 * var(--bs-offcanvas-padding-y));margin-left:auto}.offcanvas-title{margin-bottom:0;line-height:var(--bs-offcanvas-title-line-height)}.offcanvas-body{flex-grow:1;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn:before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,#000c,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{to{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}.clearfix:after{display:block;clear:both;content:""}.text-bg-primary{color:#fff!important;background-color:RGBA(var(--bs-primary-rgb),var(--bs-bg-opacity,1))!important}.text-bg-secondary{color:#fff!important;background-color:RGBA(var(--bs-secondary-rgb),var(--bs-bg-opacity,1))!important}.text-bg-success{color:#fff!important;background-color:RGBA(var(--bs-success-rgb),var(--bs-bg-opacity,1))!important}.text-bg-info{color:#000!important;background-color:RGBA(var(--bs-info-rgb),var(--bs-bg-opacity,1))!important}.text-bg-warning{color:#000!important;background-color:RGBA(var(--bs-warning-rgb),var(--bs-bg-opacity,1))!important}.text-bg-danger{color:#fff!important;background-color:RGBA(var(--bs-danger-rgb),var(--bs-bg-opacity,1))!important}.text-bg-light{color:#000!important;background-color:RGBA(var(--bs-light-rgb),var(--bs-bg-opacity,1))!important}.text-bg-dark{color:#fff!important;background-color:RGBA(var(--bs-dark-rgb),var(--bs-bg-opacity,1))!important}.link-primary{color:RGBA(var(--bs-primary-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-primary-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-primary-rgb),var(--bs-link-underline-opacity,1))!important}.link-primary:focus,.link-primary:hover{color:RGBA(10,88,202,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(10,88,202,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(10,88,202,var(--bs-link-underline-opacity,1))!important}.link-secondary{color:RGBA(var(--bs-secondary-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-secondary-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-secondary-rgb),var(--bs-link-underline-opacity,1))!important}.link-secondary:focus,.link-secondary:hover{color:RGBA(86,94,100,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(86,94,100,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(86,94,100,var(--bs-link-underline-opacity,1))!important}.link-success{color:RGBA(var(--bs-success-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-success-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-success-rgb),var(--bs-link-underline-opacity,1))!important}.link-success:focus,.link-success:hover{color:RGBA(20,108,67,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(20,108,67,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(20,108,67,var(--bs-link-underline-opacity,1))!important}.link-info{color:RGBA(var(--bs-info-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-info-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-info-rgb),var(--bs-link-underline-opacity,1))!important}.link-info:focus,.link-info:hover{color:RGBA(61,213,243,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(61,213,243,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(61,213,243,var(--bs-link-underline-opacity,1))!important}.link-warning{color:RGBA(var(--bs-warning-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-warning-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-warning-rgb),var(--bs-link-underline-opacity,1))!important}.link-warning:focus,.link-warning:hover{color:RGBA(255,205,57,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(255,205,57,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(255,205,57,var(--bs-link-underline-opacity,1))!important}.link-danger{color:RGBA(var(--bs-danger-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-danger-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-danger-rgb),var(--bs-link-underline-opacity,1))!important}.link-danger:focus,.link-danger:hover{color:RGBA(176,42,55,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(176,42,55,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(176,42,55,var(--bs-link-underline-opacity,1))!important}.link-light{color:RGBA(var(--bs-light-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-light-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-light-rgb),var(--bs-link-underline-opacity,1))!important}.link-light:focus,.link-light:hover{color:RGBA(249,250,251,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(249,250,251,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(249,250,251,var(--bs-link-underline-opacity,1))!important}.link-dark{color:RGBA(var(--bs-dark-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-dark-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-dark-rgb),var(--bs-link-underline-opacity,1))!important}.link-dark:focus,.link-dark:hover{color:RGBA(26,30,33,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(26,30,33,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(26,30,33,var(--bs-link-underline-opacity,1))!important}.link-body-emphasis{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,1))!important}.link-body-emphasis:focus,.link-body-emphasis:hover{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity,.75))!important;-webkit-text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,.75))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,.75))!important}.focus-ring:focus{outline:0;box-shadow:var(--bs-focus-ring-x,0) var(--bs-focus-ring-y,0) var(--bs-focus-ring-blur,0) var(--bs-focus-ring-width) var(--bs-focus-ring-color)}.icon-link{display:inline-flex;gap:.375rem;align-items:center;-webkit-text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,.5));text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,.5));text-underline-offset:.25em;-webkit-backface-visibility:hidden;backface-visibility:hidden}.icon-link>.bi{flex-shrink:0;width:1em;height:1em;fill:currentcolor;transition:.2s ease-in-out transform}@media (prefers-reduced-motion:reduce){.icon-link>.bi{transition:none}}.icon-link-hover:focus-visible>.bi,.icon-link-hover:hover>.bi{transform:var(--bs-icon-link-transform,translate3d(.25em,0,0))}.ratio{position:relative;width:100%}.ratio:before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:75%}.ratio-16x9{--bs-aspect-ratio:56.25%}.ratio-21x9{--bs-aspect-ratio:42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption),.visually-hidden:not(caption){position:absolute!important}.visually-hidden *,.visually-hidden-focusable:not(:focus):not(:focus-within) *{overflow:hidden!important}.stretched-link:after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:var(--bs-border-width);min-height:1em;background-color:currentcolor;opacity:.25}.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}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.object-fit-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-none{-o-object-fit:none!important;object-fit:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.overflow-x-auto{overflow-x:auto!important}.overflow-x-hidden{overflow-x:hidden!important}.overflow-x-visible{overflow-x:visible!important}.overflow-x-scroll{overflow-x:scroll!important}.overflow-y-auto{overflow-y:auto!important}.overflow-y-hidden{overflow-y:hidden!important}.overflow-y-visible{overflow-y:visible!important}.overflow-y-scroll{overflow-y:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-inline-grid{display:inline-grid!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}.d-none{display:none!important}.shadow{box-shadow:var(--bs-box-shadow)!important}.shadow-sm{box-shadow:var(--bs-box-shadow-sm)!important}.shadow-lg{box-shadow:var(--bs-box-shadow-lg)!important}.shadow-none{box-shadow:none!important}.focus-ring-primary{--bs-focus-ring-color:rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-secondary{--bs-focus-ring-color:rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-success{--bs-focus-ring-color:rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity))}.focus-ring-info{--bs-focus-ring-color:rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity))}.focus-ring-warning{--bs-focus-ring-color:rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity))}.focus-ring-danger{--bs-focus-ring-color:rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity))}.focus-ring-light{--bs-focus-ring-color:rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity))}.focus-ring-dark{--bs-focus-ring-color:rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity))}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translate(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-0{border:0!important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-top-0{border-top:0!important}.border-end{border-right:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-start-0{border-left:0!important}.border-primary{--bs-border-opacity:1;border-color:rgba(var(--bs-primary-rgb),var(--bs-border-opacity))!important}.border-secondary{--bs-border-opacity:1;border-color:rgba(var(--bs-secondary-rgb),var(--bs-border-opacity))!important}.border-success{--bs-border-opacity:1;border-color:rgba(var(--bs-success-rgb),var(--bs-border-opacity))!important}.border-info{--bs-border-opacity:1;border-color:rgba(var(--bs-info-rgb),var(--bs-border-opacity))!important}.border-warning{--bs-border-opacity:1;border-color:rgba(var(--bs-warning-rgb),var(--bs-border-opacity))!important}.border-danger{--bs-border-opacity:1;border-color:rgba(var(--bs-danger-rgb),var(--bs-border-opacity))!important}.border-light{--bs-border-opacity:1;border-color:rgba(var(--bs-light-rgb),var(--bs-border-opacity))!important}.border-dark{--bs-border-opacity:1;border-color:rgba(var(--bs-dark-rgb),var(--bs-border-opacity))!important}.border-black{--bs-border-opacity:1;border-color:rgba(var(--bs-black-rgb),var(--bs-border-opacity))!important}.border-white{--bs-border-opacity:1;border-color:rgba(var(--bs-white-rgb),var(--bs-border-opacity))!important}.border-primary-subtle{border-color:var(--bs-primary-border-subtle)!important}.border-secondary-subtle{border-color:var(--bs-secondary-border-subtle)!important}.border-success-subtle{border-color:var(--bs-success-border-subtle)!important}.border-info-subtle{border-color:var(--bs-info-border-subtle)!important}.border-warning-subtle{border-color:var(--bs-warning-border-subtle)!important}.border-danger-subtle{border-color:var(--bs-danger-border-subtle)!important}.border-light-subtle{border-color:var(--bs-light-border-subtle)!important}.border-dark-subtle{border-color:var(--bs-dark-border-subtle)!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.border-opacity-10{--bs-border-opacity:.1}.border-opacity-25{--bs-border-opacity:.25}.border-opacity-50{--bs-border-opacity:.5}.border-opacity-75{--bs-border-opacity:.75}.border-opacity-100{--bs-border-opacity:1}.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}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!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}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.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-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}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!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}.justify-content-evenly{justify-content:space-evenly!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}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.row-gap-0{row-gap:0!important}.row-gap-1{row-gap:.25rem!important}.row-gap-2{row-gap:.5rem!important}.row-gap-3{row-gap:1rem!important}.row-gap-4{row-gap:1.5rem!important}.row-gap-5{row-gap:3rem!important}.column-gap-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-1{-moz-column-gap:.25rem!important;column-gap:.25rem!important}.column-gap-2{-moz-column-gap:.5rem!important;column-gap:.5rem!important}.column-gap-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-lighter{font-weight:lighter!important}.fw-light{font-weight:300!important}.fw-normal{font-weight:400!important}.fw-medium{font-weight:500!important}.fw-semibold{font-weight:600!important}.fw-bold{font-weight:700!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-black-50{--bs-text-opacity:1;color:#00000080!important}.text-white-50{--bs-text-opacity:1;color:#ffffff80!important}.text-body-secondary{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-body-tertiary{--bs-text-opacity:1;color:var(--bs-tertiary-color)!important}.text-body-emphasis{--bs-text-opacity:1;color:var(--bs-emphasis-color)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:.25}.text-opacity-50{--bs-text-opacity:.5}.text-opacity-75{--bs-text-opacity:.75}.text-opacity-100{--bs-text-opacity:1}.text-primary-emphasis{color:var(--bs-primary-text-emphasis)!important}.text-secondary-emphasis{color:var(--bs-secondary-text-emphasis)!important}.text-success-emphasis{color:var(--bs-success-text-emphasis)!important}.text-info-emphasis{color:var(--bs-info-text-emphasis)!important}.text-warning-emphasis{color:var(--bs-warning-text-emphasis)!important}.text-danger-emphasis{color:var(--bs-danger-text-emphasis)!important}.text-light-emphasis{color:var(--bs-light-text-emphasis)!important}.text-dark-emphasis{color:var(--bs-dark-text-emphasis)!important}.link-opacity-10,.link-opacity-10-hover:hover{--bs-link-opacity:.1}.link-opacity-25,.link-opacity-25-hover:hover{--bs-link-opacity:.25}.link-opacity-50,.link-opacity-50-hover:hover{--bs-link-opacity:.5}.link-opacity-75,.link-opacity-75-hover:hover{--bs-link-opacity:.75}.link-opacity-100,.link-opacity-100-hover:hover{--bs-link-opacity:1}.link-offset-1,.link-offset-1-hover:hover{text-underline-offset:.125em!important}.link-offset-2,.link-offset-2-hover:hover{text-underline-offset:.25em!important}.link-offset-3,.link-offset-3-hover:hover{text-underline-offset:.375em!important}.link-underline-primary{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-primary-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-primary-rgb),var(--bs-link-underline-opacity))!important}.link-underline-secondary{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-secondary-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-secondary-rgb),var(--bs-link-underline-opacity))!important}.link-underline-success{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-success-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-success-rgb),var(--bs-link-underline-opacity))!important}.link-underline-info{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-info-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-info-rgb),var(--bs-link-underline-opacity))!important}.link-underline-warning{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-warning-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-warning-rgb),var(--bs-link-underline-opacity))!important}.link-underline-danger{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-danger-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-danger-rgb),var(--bs-link-underline-opacity))!important}.link-underline-light{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-light-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-light-rgb),var(--bs-link-underline-opacity))!important}.link-underline-dark{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-dark-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-dark-rgb),var(--bs-link-underline-opacity))!important}.link-underline{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-underline-opacity,1))!important}.link-underline-opacity-0,.link-underline-opacity-0-hover:hover{--bs-link-underline-opacity:0}.link-underline-opacity-10,.link-underline-opacity-10-hover:hover{--bs-link-underline-opacity:.1}.link-underline-opacity-25,.link-underline-opacity-25-hover:hover{--bs-link-underline-opacity:.25}.link-underline-opacity-50,.link-underline-opacity-50-hover:hover{--bs-link-underline-opacity:.5}.link-underline-opacity-75,.link-underline-opacity-75-hover:hover{--bs-link-underline-opacity:.75}.link-underline-opacity-100,.link-underline-opacity-100-hover:hover{--bs-link-underline-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-bg-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-body-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-bg-rgb),var(--bs-bg-opacity))!important}.bg-body-tertiary{--bs-bg-opacity:1;background-color:rgba(var(--bs-tertiary-bg-rgb),var(--bs-bg-opacity))!important}.bg-opacity-10{--bs-bg-opacity:.1}.bg-opacity-25{--bs-bg-opacity:.25}.bg-opacity-50{--bs-bg-opacity:.5}.bg-opacity-75{--bs-bg-opacity:.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-primary-subtle{background-color:var(--bs-primary-bg-subtle)!important}.bg-secondary-subtle{background-color:var(--bs-secondary-bg-subtle)!important}.bg-success-subtle{background-color:var(--bs-success-bg-subtle)!important}.bg-info-subtle{background-color:var(--bs-info-bg-subtle)!important}.bg-warning-subtle{background-color:var(--bs-warning-bg-subtle)!important}.bg-danger-subtle{background-color:var(--bs-danger-bg-subtle)!important}.bg-light-subtle{background-color:var(--bs-light-bg-subtle)!important}.bg-dark-subtle{background-color:var(--bs-dark-bg-subtle)!important}.bg-gradient{background-image:var(--bs-gradient)!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}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:var(--bs-border-radius)!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:var(--bs-border-radius-sm)!important}.rounded-2{border-radius:var(--bs-border-radius)!important}.rounded-3{border-radius:var(--bs-border-radius-lg)!important}.rounded-4{border-radius:var(--bs-border-radius-xl)!important}.rounded-5{border-radius:var(--bs-border-radius-xxl)!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:var(--bs-border-radius-pill)!important}.rounded-top{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-top-0{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-top-1{border-top-left-radius:var(--bs-border-radius-sm)!important;border-top-right-radius:var(--bs-border-radius-sm)!important}.rounded-top-2{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-top-3{border-top-left-radius:var(--bs-border-radius-lg)!important;border-top-right-radius:var(--bs-border-radius-lg)!important}.rounded-top-4{border-top-left-radius:var(--bs-border-radius-xl)!important;border-top-right-radius:var(--bs-border-radius-xl)!important}.rounded-top-5{border-top-left-radius:var(--bs-border-radius-xxl)!important;border-top-right-radius:var(--bs-border-radius-xxl)!important}.rounded-top-circle{border-top-left-radius:50%!important;border-top-right-radius:50%!important}.rounded-top-pill{border-top-left-radius:var(--bs-border-radius-pill)!important;border-top-right-radius:var(--bs-border-radius-pill)!important}.rounded-end{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-end-0{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.rounded-end-1{border-top-right-radius:var(--bs-border-radius-sm)!important;border-bottom-right-radius:var(--bs-border-radius-sm)!important}.rounded-end-2{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-end-3{border-top-right-radius:var(--bs-border-radius-lg)!important;border-bottom-right-radius:var(--bs-border-radius-lg)!important}.rounded-end-4{border-top-right-radius:var(--bs-border-radius-xl)!important;border-bottom-right-radius:var(--bs-border-radius-xl)!important}.rounded-end-5{border-top-right-radius:var(--bs-border-radius-xxl)!important;border-bottom-right-radius:var(--bs-border-radius-xxl)!important}.rounded-end-circle{border-top-right-radius:50%!important;border-bottom-right-radius:50%!important}.rounded-end-pill{border-top-right-radius:var(--bs-border-radius-pill)!important;border-bottom-right-radius:var(--bs-border-radius-pill)!important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-bottom-0{border-bottom-right-radius:0!important;border-bottom-left-radius:0!important}.rounded-bottom-1{border-bottom-right-radius:var(--bs-border-radius-sm)!important;border-bottom-left-radius:var(--bs-border-radius-sm)!important}.rounded-bottom-2{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-bottom-3{border-bottom-right-radius:var(--bs-border-radius-lg)!important;border-bottom-left-radius:var(--bs-border-radius-lg)!important}.rounded-bottom-4{border-bottom-right-radius:var(--bs-border-radius-xl)!important;border-bottom-left-radius:var(--bs-border-radius-xl)!important}.rounded-bottom-5{border-bottom-right-radius:var(--bs-border-radius-xxl)!important;border-bottom-left-radius:var(--bs-border-radius-xxl)!important}.rounded-bottom-circle{border-bottom-right-radius:50%!important;border-bottom-left-radius:50%!important}.rounded-bottom-pill{border-bottom-right-radius:var(--bs-border-radius-pill)!important;border-bottom-left-radius:var(--bs-border-radius-pill)!important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.rounded-start-0{border-bottom-left-radius:0!important;border-top-left-radius:0!important}.rounded-start-1{border-bottom-left-radius:var(--bs-border-radius-sm)!important;border-top-left-radius:var(--bs-border-radius-sm)!important}.rounded-start-2{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.rounded-start-3{border-bottom-left-radius:var(--bs-border-radius-lg)!important;border-top-left-radius:var(--bs-border-radius-lg)!important}.rounded-start-4{border-bottom-left-radius:var(--bs-border-radius-xl)!important;border-top-left-radius:var(--bs-border-radius-xl)!important}.rounded-start-5{border-bottom-left-radius:var(--bs-border-radius-xxl)!important;border-top-left-radius:var(--bs-border-radius-xxl)!important}.rounded-start-circle{border-bottom-left-radius:50%!important;border-top-left-radius:50%!important}.rounded-start-pill{border-bottom-left-radius:var(--bs-border-radius-pill)!important;border-top-left-radius:var(--bs-border-radius-pill)!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.z-n1{z-index:-1!important}.z-0{z-index:0!important}.z-1{z-index:1!important}.z-2{z-index:2!important}.z-3{z-index:3!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.object-fit-sm-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-sm-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-sm-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-sm-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-sm-none{-o-object-fit:none!important;object-fit:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-inline-grid{display:inline-grid!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}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.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-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}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!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}.justify-content-sm-evenly{justify-content:space-evenly!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}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.row-gap-sm-0{row-gap:0!important}.row-gap-sm-1{row-gap:.25rem!important}.row-gap-sm-2{row-gap:.5rem!important}.row-gap-sm-3{row-gap:1rem!important}.row-gap-sm-4{row-gap:1.5rem!important}.row-gap-sm-5{row-gap:3rem!important}.column-gap-sm-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-sm-1{-moz-column-gap:.25rem!important;column-gap:.25rem!important}.column-gap-sm-2{-moz-column-gap:.5rem!important;column-gap:.5rem!important}.column-gap-sm-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-sm-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-sm-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.object-fit-md-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-md-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-md-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-md-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-md-none{-o-object-fit:none!important;object-fit:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-inline-grid{display:inline-grid!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}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.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-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}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!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}.justify-content-md-evenly{justify-content:space-evenly!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}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.row-gap-md-0{row-gap:0!important}.row-gap-md-1{row-gap:.25rem!important}.row-gap-md-2{row-gap:.5rem!important}.row-gap-md-3{row-gap:1rem!important}.row-gap-md-4{row-gap:1.5rem!important}.row-gap-md-5{row-gap:3rem!important}.column-gap-md-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-md-1{-moz-column-gap:.25rem!important;column-gap:.25rem!important}.column-gap-md-2{-moz-column-gap:.5rem!important;column-gap:.5rem!important}.column-gap-md-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-md-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-md-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.object-fit-lg-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-lg-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-lg-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-lg-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-lg-none{-o-object-fit:none!important;object-fit:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-inline-grid{display:inline-grid!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}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.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-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}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!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}.justify-content-lg-evenly{justify-content:space-evenly!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}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.row-gap-lg-0{row-gap:0!important}.row-gap-lg-1{row-gap:.25rem!important}.row-gap-lg-2{row-gap:.5rem!important}.row-gap-lg-3{row-gap:1rem!important}.row-gap-lg-4{row-gap:1.5rem!important}.row-gap-lg-5{row-gap:3rem!important}.column-gap-lg-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-lg-1{-moz-column-gap:.25rem!important;column-gap:.25rem!important}.column-gap-lg-2{-moz-column-gap:.5rem!important;column-gap:.5rem!important}.column-gap-lg-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-lg-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-lg-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.object-fit-xl-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-xl-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-xl-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-xl-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-xl-none{-o-object-fit:none!important;object-fit:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-inline-grid{display:inline-grid!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}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.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-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}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!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}.justify-content-xl-evenly{justify-content:space-evenly!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}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.row-gap-xl-0{row-gap:0!important}.row-gap-xl-1{row-gap:.25rem!important}.row-gap-xl-2{row-gap:.5rem!important}.row-gap-xl-3{row-gap:1rem!important}.row-gap-xl-4{row-gap:1.5rem!important}.row-gap-xl-5{row-gap:3rem!important}.column-gap-xl-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-xl-1{-moz-column-gap:.25rem!important;column-gap:.25rem!important}.column-gap-xl-2{-moz-column-gap:.5rem!important;column-gap:.5rem!important}.column-gap-xl-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-xl-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-xl-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.object-fit-xxl-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-xxl-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-xxl-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-xxl-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-xxl-none{-o-object-fit:none!important;object-fit:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-inline-grid{display:inline-grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.row-gap-xxl-0{row-gap:0!important}.row-gap-xxl-1{row-gap:.25rem!important}.row-gap-xxl-2{row-gap:.5rem!important}.row-gap-xxl-3{row-gap:1rem!important}.row-gap-xxl-4{row-gap:1.5rem!important}.row-gap-xxl-5{row-gap:3rem!important}.column-gap-xxl-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-xxl-1{-moz-column-gap:.25rem!important;column-gap:.25rem!important}.column-gap-xxl-2{-moz-column-gap:.5rem!important;column-gap:.5rem!important}.column-gap-xxl-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-xxl-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-xxl-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-inline-grid{display:inline-grid!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}.d-print-none{display:none!important}}:root{--primary-color: #00034B}body{background:#f8f9fa}.navbar.bg-primary{background:var(--primary-color)!important}.container{max-width:1100px} diff --git a/src/assets/frontend/assets/index.js b/src/assets/frontend/assets/index.js new file mode 100644 index 00000000..df541847 --- /dev/null +++ b/src/assets/frontend/assets/index.js @@ -0,0 +1,35 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/groups.js","assets/groups.css","assets/groupdetail.js","assets/groupdetail.css"])))=>i.map(i=>d[i]); +(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))s(i);new MutationObserver(i=>{for(const l of i)if(l.type==="childList")for(const r of l.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&s(r)}).observe(document,{childList:!0,subtree:!0});function n(i){const l={};return i.integrity&&(l.integrity=i.integrity),i.referrerPolicy&&(l.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?l.credentials="include":i.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function s(i){if(i.ep)return;i.ep=!0;const l=n(i);fetch(i.href,l)}})();/** +* @vue/shared v3.5.26 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Da(t){const e=Object.create(null);for(const n of t.split(","))e[n]=1;return n=>n in e}const ht={},so=[],zn=()=>{},nd=()=>!1,Xi=t=>t.charCodeAt(0)===111&&t.charCodeAt(1)===110&&(t.charCodeAt(2)>122||t.charCodeAt(2)<97),La=t=>t.startsWith("onUpdate:"),Ht=Object.assign,Na=(t,e)=>{const n=t.indexOf(e);n>-1&&t.splice(n,1)},Zp=Object.prototype.hasOwnProperty,ot=(t,e)=>Zp.call(t,e),Ie=Array.isArray,oo=t=>Yo(t)==="[object Map]",vo=t=>Yo(t)==="[object Set]",Fc=t=>Yo(t)==="[object Date]",ze=t=>typeof t=="function",At=t=>typeof t=="string",Tn=t=>typeof t=="symbol",pt=t=>t!==null&&typeof t=="object",sd=t=>(pt(t)||ze(t))&&ze(t.then)&&ze(t.catch),od=Object.prototype.toString,Yo=t=>od.call(t),eg=t=>Yo(t).slice(8,-1),id=t=>Yo(t)==="[object Object]",Fa=t=>At(t)&&t!=="NaN"&&t[0]!=="-"&&""+parseInt(t,10)===t,Do=Da(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Yi=t=>{const e=Object.create(null);return n=>e[n]||(e[n]=t(n))},tg=/-\w/g,vn=Yi(t=>t.replace(tg,e=>e.slice(1).toUpperCase())),ng=/\B([A-Z])/g,gs=Yi(t=>t.replace(ng,"-$1").toLowerCase()),Zi=Yi(t=>t.charAt(0).toUpperCase()+t.slice(1)),Jr=Yi(t=>t?`on${Zi(t)}`:""),fs=(t,e)=>!Object.is(t,e),Pi=(t,...e)=>{for(let n=0;n{Object.defineProperty(t,e,{configurable:!0,enumerable:!1,writable:s,value:n})},er=t=>{const e=parseFloat(t);return isNaN(e)?t:e};let xc;const tr=()=>xc||(xc=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Sn(t){if(Ie(t)){const e={};for(let n=0;n{if(n){const s=n.split(og);s.length>1&&(e[s[0].trim()]=s[1].trim())}}),e}function ae(t){let e="";if(At(t))e=t;else if(Ie(t))for(let n=0;nxs(n,e))}const ld=t=>!!(t&&t.__v_isRef===!0),A=t=>At(t)?t:t==null?"":Ie(t)||pt(t)&&(t.toString===od||!ze(t.toString))?ld(t)?A(t.value):JSON.stringify(t,cd,2):String(t),cd=(t,e)=>ld(e)?cd(t,e.value):oo(e)?{[`Map(${e.size})`]:[...e.entries()].reduce((n,[s,i],l)=>(n[Xr(s,l)+" =>"]=i,n),{})}:vo(e)?{[`Set(${e.size})`]:[...e.values()].map(n=>Xr(n))}:Tn(e)?Xr(e):pt(e)&&!Ie(e)&&!id(e)?String(e):e,Xr=(t,e="")=>{var n;return Tn(t)?`Symbol(${(n=t.description)!=null?n:e})`:t};/** +* @vue/reactivity v3.5.26 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let Jt;class ug{constructor(e=!1){this.detached=e,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=Jt,!e&&Jt&&(this.index=(Jt.scopes||(Jt.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let e,n;if(this.scopes)for(e=0,n=this.scopes.length;e0&&--this._on===0&&(Jt=this.prevScope,this.prevScope=void 0)}stop(e){if(this._active){this._active=!1;let n,s;for(n=0,s=this.effects.length;n0)return;if(No){let e=No;for(No=void 0;e;){const n=e.next;e.next=void 0,e.flags&=-9,e=n}}let t;for(;Lo;){let e=Lo;for(Lo=void 0;e;){const n=e.next;if(e.next=void 0,e.flags&=-9,e.flags&1)try{e.trigger()}catch(s){t||(t=s)}e=n}}if(t)throw t}function hd(t){for(let e=t.deps;e;e=e.nextDep)e.version=-1,e.prevActiveLink=e.dep.activeLink,e.dep.activeLink=e}function pd(t){let e,n=t.depsTail,s=n;for(;s;){const i=s.prevDep;s.version===-1?(s===n&&(n=i),Ha(s),fg(s)):e=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=i}t.deps=e,t.depsTail=n}function ha(t){for(let e=t.deps;e;e=e.nextDep)if(e.dep.version!==e.version||e.dep.computed&&(gd(e.dep.computed)||e.dep.version!==e.version))return!0;return!!t._dirty}function gd(t){if(t.flags&4&&!(t.flags&16)||(t.flags&=-17,t.globalVersion===Uo)||(t.globalVersion=Uo,!t.isSSR&&t.flags&128&&(!t.deps&&!t._dirty||!ha(t))))return;t.flags|=2;const e=t.dep,n=bt,s=En;bt=t,En=!0;try{hd(t);const i=t.fn(t._value);(e.version===0||fs(i,t._value))&&(t.flags|=128,t._value=i,e.version++)}catch(i){throw e.version++,i}finally{bt=n,En=s,pd(t),t.flags&=-3}}function Ha(t,e=!1){const{dep:n,prevSub:s,nextSub:i}=t;if(s&&(s.nextSub=i,t.prevSub=void 0),i&&(i.prevSub=s,t.nextSub=void 0),n.subs===t&&(n.subs=s,!s&&n.computed)){n.computed.flags&=-5;for(let l=n.computed.deps;l;l=l.nextDep)Ha(l,!0)}!e&&!--n.sc&&n.map&&n.map.delete(n.key)}function fg(t){const{prevDep:e,nextDep:n}=t;e&&(e.nextDep=n,t.prevDep=void 0),n&&(n.prevDep=e,t.nextDep=void 0)}let En=!0;const md=[];function Xn(){md.push(En),En=!1}function Yn(){const t=md.pop();En=t===void 0?!0:t}function Bc(t){const{cleanup:e}=t;if(t.cleanup=void 0,e){const n=bt;bt=void 0;try{e()}finally{bt=n}}}let Uo=0;class hg{constructor(e,n){this.sub=e,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Ua{constructor(e){this.computed=e,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(e){if(!bt||!En||bt===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==bt)n=this.activeLink=new hg(bt,this),bt.deps?(n.prevDep=bt.depsTail,bt.depsTail.nextDep=n,bt.depsTail=n):bt.deps=bt.depsTail=n,vd(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=bt.depsTail,n.nextDep=void 0,bt.depsTail.nextDep=n,bt.depsTail=n,bt.deps===n&&(bt.deps=s)}return n}trigger(e){this.version++,Uo++,this.notify(e)}notify(e){Ba();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{za()}}}function vd(t){if(t.dep.sc++,t.sub.flags&4){const e=t.dep.computed;if(e&&!t.dep.subs){e.flags|=20;for(let s=e.deps;s;s=s.nextDep)vd(s)}const n=t.dep.subs;n!==t&&(t.prevSub=n,n&&(n.nextSub=t)),t.dep.subs=t}}const pa=new WeakMap,Ms=Symbol(""),ga=Symbol(""),Vo=Symbol("");function Lt(t,e,n){if(En&&bt){let s=pa.get(t);s||pa.set(t,s=new Map);let i=s.get(n);i||(s.set(n,i=new Ua),i.map=s,i.key=n),i.track()}}function Gn(t,e,n,s,i,l){const r=pa.get(t);if(!r){Uo++;return}const c=u=>{u&&u.trigger()};if(Ba(),e==="clear")r.forEach(c);else{const u=Ie(t),h=u&&Fa(n);if(u&&n==="length"){const f=Number(s);r.forEach((g,C)=>{(C==="length"||C===Vo||!Tn(C)&&C>=f)&&c(g)})}else switch((n!==void 0||r.has(void 0))&&c(r.get(n)),h&&c(r.get(Vo)),e){case"add":u?h&&c(r.get("length")):(c(r.get(Ms)),oo(t)&&c(r.get(ga)));break;case"delete":u||(c(r.get(Ms)),oo(t)&&c(r.get(ga)));break;case"set":oo(t)&&c(r.get(Ms));break}}za()}function eo(t){const e=st(t);return e===t?e:(Lt(e,"iterate",Vo),gn(t)?e:e.map(An))}function nr(t){return Lt(t=st(t),"iterate",Vo),t}function ls(t,e){return Zn(t)?Ds(t)?co(An(e)):co(e):An(e)}const pg={__proto__:null,[Symbol.iterator](){return Zr(this,Symbol.iterator,t=>ls(this,t))},concat(...t){return eo(this).concat(...t.map(e=>Ie(e)?eo(e):e))},entries(){return Zr(this,"entries",t=>(t[1]=ls(this,t[1]),t))},every(t,e){return qn(this,"every",t,e,void 0,arguments)},filter(t,e){return qn(this,"filter",t,e,n=>n.map(s=>ls(this,s)),arguments)},find(t,e){return qn(this,"find",t,e,n=>ls(this,n),arguments)},findIndex(t,e){return qn(this,"findIndex",t,e,void 0,arguments)},findLast(t,e){return qn(this,"findLast",t,e,n=>ls(this,n),arguments)},findLastIndex(t,e){return qn(this,"findLastIndex",t,e,void 0,arguments)},forEach(t,e){return qn(this,"forEach",t,e,void 0,arguments)},includes(...t){return ea(this,"includes",t)},indexOf(...t){return ea(this,"indexOf",t)},join(t){return eo(this).join(t)},lastIndexOf(...t){return ea(this,"lastIndexOf",t)},map(t,e){return qn(this,"map",t,e,void 0,arguments)},pop(){return Ao(this,"pop")},push(...t){return Ao(this,"push",t)},reduce(t,...e){return zc(this,"reduce",t,e)},reduceRight(t,...e){return zc(this,"reduceRight",t,e)},shift(){return Ao(this,"shift")},some(t,e){return qn(this,"some",t,e,void 0,arguments)},splice(...t){return Ao(this,"splice",t)},toReversed(){return eo(this).toReversed()},toSorted(t){return eo(this).toSorted(t)},toSpliced(...t){return eo(this).toSpliced(...t)},unshift(...t){return Ao(this,"unshift",t)},values(){return Zr(this,"values",t=>ls(this,t))}};function Zr(t,e,n){const s=nr(t),i=s[e]();return s!==t&&!gn(t)&&(i._next=i.next,i.next=()=>{const l=i._next();return l.done||(l.value=n(l.value)),l}),i}const gg=Array.prototype;function qn(t,e,n,s,i,l){const r=nr(t),c=r!==t&&!gn(t),u=r[e];if(u!==gg[e]){const g=u.apply(t,l);return c?An(g):g}let h=n;r!==t&&(c?h=function(g,C){return n.call(this,ls(t,g),C,t)}:n.length>2&&(h=function(g,C){return n.call(this,g,C,t)}));const f=u.call(r,h,s);return c&&i?i(f):f}function zc(t,e,n,s){const i=nr(t);let l=n;return i!==t&&(gn(t)?n.length>3&&(l=function(r,c,u){return n.call(this,r,c,u,t)}):l=function(r,c,u){return n.call(this,r,ls(t,c),u,t)}),i[e](l,...s)}function ea(t,e,n){const s=st(t);Lt(s,"iterate",Vo);const i=s[e](...n);return(i===-1||i===!1)&&qa(n[0])?(n[0]=st(n[0]),s[e](...n)):i}function Ao(t,e,n=[]){Xn(),Ba();const s=st(t)[e].apply(t,n);return za(),Yn(),s}const mg=Da("__proto__,__v_isRef,__isVue"),bd=new Set(Object.getOwnPropertyNames(Symbol).filter(t=>t!=="arguments"&&t!=="caller").map(t=>Symbol[t]).filter(Tn));function vg(t){Tn(t)||(t=String(t));const e=st(this);return Lt(e,"has",t),e.hasOwnProperty(t)}class yd{constructor(e=!1,n=!1){this._isReadonly=e,this._isShallow=n}get(e,n,s){if(n==="__v_skip")return e.__v_skip;const i=this._isReadonly,l=this._isShallow;if(n==="__v_isReactive")return!i;if(n==="__v_isReadonly")return i;if(n==="__v_isShallow")return l;if(n==="__v_raw")return s===(i?l?Tg:kd:l?Cd:_d).get(e)||Object.getPrototypeOf(e)===Object.getPrototypeOf(s)?e:void 0;const r=Ie(e);if(!i){let u;if(r&&(u=pg[n]))return u;if(n==="hasOwnProperty")return vg}const c=Reflect.get(e,n,Bt(e)?e:s);if((Tn(n)?bd.has(n):mg(n))||(i||Lt(e,"get",n),l))return c;if(Bt(c)){const u=r&&Fa(n)?c:c.value;return i&&pt(u)?va(u):u}return pt(c)?i?va(c):Xt(c):c}}class wd extends yd{constructor(e=!1){super(!1,e)}set(e,n,s,i){let l=e[n];const r=Ie(e)&&Fa(n);if(!this._isShallow){const h=Zn(l);if(!gn(s)&&!Zn(s)&&(l=st(l),s=st(s)),!r&&Bt(l)&&!Bt(s))return h||(l.value=s),!0}const c=r?Number(n)t,Si=t=>Reflect.getPrototypeOf(t);function Cg(t,e,n){return function(...s){const i=this.__v_raw,l=st(i),r=oo(l),c=t==="entries"||t===Symbol.iterator&&r,u=t==="keys"&&r,h=i[t](...s),f=n?ma:e?co:An;return!e&&Lt(l,"iterate",u?ga:Ms),{next(){const{value:g,done:C}=h.next();return C?{value:g,done:C}:{value:c?[f(g[0]),f(g[1])]:f(g),done:C}},[Symbol.iterator](){return this}}}}function Ei(t){return function(...e){return t==="delete"?!1:t==="clear"?void 0:this}}function kg(t,e){const n={get(i){const l=this.__v_raw,r=st(l),c=st(i);t||(fs(i,c)&&Lt(r,"get",i),Lt(r,"get",c));const{has:u}=Si(r),h=e?ma:t?co:An;if(u.call(r,i))return h(l.get(i));if(u.call(r,c))return h(l.get(c));l!==r&&l.get(i)},get size(){const i=this.__v_raw;return!t&&Lt(st(i),"iterate",Ms),i.size},has(i){const l=this.__v_raw,r=st(l),c=st(i);return t||(fs(i,c)&&Lt(r,"has",i),Lt(r,"has",c)),i===c?l.has(i):l.has(i)||l.has(c)},forEach(i,l){const r=this,c=r.__v_raw,u=st(c),h=e?ma:t?co:An;return!t&&Lt(u,"iterate",Ms),c.forEach((f,g)=>i.call(l,h(f),h(g),r))}};return Ht(n,t?{add:Ei("add"),set:Ei("set"),delete:Ei("delete"),clear:Ei("clear")}:{add(i){!e&&!gn(i)&&!Zn(i)&&(i=st(i));const l=st(this);return Si(l).has.call(l,i)||(l.add(i),Gn(l,"add",i,i)),this},set(i,l){!e&&!gn(l)&&!Zn(l)&&(l=st(l));const r=st(this),{has:c,get:u}=Si(r);let h=c.call(r,i);h||(i=st(i),h=c.call(r,i));const f=u.call(r,i);return r.set(i,l),h?fs(l,f)&&Gn(r,"set",i,l):Gn(r,"add",i,l),this},delete(i){const l=st(this),{has:r,get:c}=Si(l);let u=r.call(l,i);u||(i=st(i),u=r.call(l,i)),c&&c.call(l,i);const h=l.delete(i);return u&&Gn(l,"delete",i,void 0),h},clear(){const i=st(this),l=i.size!==0,r=i.clear();return l&&Gn(i,"clear",void 0,void 0),r}}),["keys","values","entries",Symbol.iterator].forEach(i=>{n[i]=Cg(i,t,e)}),n}function Va(t,e){const n=kg(t,e);return(s,i,l)=>i==="__v_isReactive"?!t:i==="__v_isReadonly"?t:i==="__v_raw"?s:Reflect.get(ot(n,i)&&i in s?n:s,i,l)}const Sg={get:Va(!1,!1)},Eg={get:Va(!1,!0)},$g={get:Va(!0,!1)};const _d=new WeakMap,Cd=new WeakMap,kd=new WeakMap,Tg=new WeakMap;function Ag(t){switch(t){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Rg(t){return t.__v_skip||!Object.isExtensible(t)?0:Ag(eg(t))}function Xt(t){return Zn(t)?t:ja(t,!1,yg,Sg,_d)}function Sd(t){return ja(t,!1,_g,Eg,Cd)}function va(t){return ja(t,!0,wg,$g,kd)}function ja(t,e,n,s,i){if(!pt(t)||t.__v_raw&&!(e&&t.__v_isReactive))return t;const l=Rg(t);if(l===0)return t;const r=i.get(t);if(r)return r;const c=new Proxy(t,l===2?s:n);return i.set(t,c),c}function Ds(t){return Zn(t)?Ds(t.__v_raw):!!(t&&t.__v_isReactive)}function Zn(t){return!!(t&&t.__v_isReadonly)}function gn(t){return!!(t&&t.__v_isShallow)}function qa(t){return t?!!t.__v_raw:!1}function st(t){const e=t&&t.__v_raw;return e?st(e):t}function Pg(t){return!ot(t,"__v_skip")&&Object.isExtensible(t)&&rd(t,"__v_skip",!0),t}const An=t=>pt(t)?Xt(t):t,co=t=>pt(t)?va(t):t;function Bt(t){return t?t.__v_isRef===!0:!1}function O(t){return Ed(t,!1)}function Ig(t){return Ed(t,!0)}function Ed(t,e){return Bt(t)?t:new Og(t,e)}class Og{constructor(e,n){this.dep=new Ua,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?e:st(e),this._value=n?e:An(e),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(e){const n=this._rawValue,s=this.__v_isShallow||gn(e)||Zn(e);e=s?e:st(e),fs(e,n)&&(this._rawValue=e,this._value=s?e:An(e),this.dep.trigger())}}function io(t){return Bt(t)?t.value:t}const Mg={get:(t,e,n)=>e==="__v_raw"?t:io(Reflect.get(t,e,n)),set:(t,e,n,s)=>{const i=t[e];return Bt(i)&&!Bt(n)?(i.value=n,!0):Reflect.set(t,e,n,s)}};function $d(t){return Ds(t)?t:new Proxy(t,Mg)}class Dg{constructor(e,n,s){this.fn=e,this.setter=n,this._value=void 0,this.dep=new Ua(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Uo-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=s}notify(){if(this.flags|=16,!(this.flags&8)&&bt!==this)return fd(this,!0),!0}get value(){const e=this.dep.track();return gd(this),e&&(e.version=this.dep.version),this._value}set value(e){this.setter&&this.setter(e)}}function Lg(t,e,n=!1){let s,i;return ze(t)?s=t:(s=t.get,i=t.set),new Dg(s,i,n)}const $i={},Bi=new WeakMap;let Ps;function Ng(t,e=!1,n=Ps){if(n){let s=Bi.get(n);s||Bi.set(n,s=[]),s.push(t)}}function Fg(t,e,n=ht){const{immediate:s,deep:i,once:l,scheduler:r,augmentJob:c,call:u}=n,h=F=>i?F:gn(F)||i===!1||i===0?Qn(F,1):Qn(F);let f,g,C,_,y=!1,P=!1;if(Bt(t)?(g=()=>t.value,y=gn(t)):Ds(t)?(g=()=>h(t),y=!0):Ie(t)?(P=!0,y=t.some(F=>Ds(F)||gn(F)),g=()=>t.map(F=>{if(Bt(F))return F.value;if(Ds(F))return h(F);if(ze(F))return u?u(F,2):F()})):ze(t)?e?g=u?()=>u(t,2):t:g=()=>{if(C){Xn();try{C()}finally{Yn()}}const F=Ps;Ps=f;try{return u?u(t,3,[_]):t(_)}finally{Ps=F}}:g=zn,e&&i){const F=g,ne=i===!0?1/0:i;g=()=>Qn(F(),ne)}const I=dg(),H=()=>{f.stop(),I&&I.active&&Na(I.effects,f)};if(l&&e){const F=e;e=(...ne)=>{F(...ne),H()}}let W=P?new Array(t.length).fill($i):$i;const G=F=>{if(!(!(f.flags&1)||!f.dirty&&!F))if(e){const ne=f.run();if(i||y||(P?ne.some((he,ce)=>fs(he,W[ce])):fs(ne,W))){C&&C();const he=Ps;Ps=f;try{const ce=[ne,W===$i?void 0:P&&W[0]===$i?[]:W,_];W=ne,u?u(e,3,ce):e(...ce)}finally{Ps=he}}}else f.run()};return c&&c(G),f=new ud(g),f.scheduler=r?()=>r(G,!1):G,_=F=>Ng(F,!1,f),C=f.onStop=()=>{const F=Bi.get(f);if(F){if(u)u(F,4);else for(const ne of F)ne();Bi.delete(f)}},e?s?G(!0):W=f.run():r?r(G.bind(null,!0),!0):f.run(),H.pause=f.pause.bind(f),H.resume=f.resume.bind(f),H.stop=H,H}function Qn(t,e=1/0,n){if(e<=0||!pt(t)||t.__v_skip||(n=n||new Map,(n.get(t)||0)>=e))return t;if(n.set(t,e),e--,Bt(t))Qn(t.value,e,n);else if(Ie(t))for(let s=0;s{Qn(s,e,n)});else if(id(t)){for(const s in t)Qn(t[s],e,n);for(const s of Object.getOwnPropertySymbols(t))Object.prototype.propertyIsEnumerable.call(t,s)&&Qn(t[s],e,n)}return t}/** +* @vue/runtime-core v3.5.26 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Zo(t,e,n,s){try{return s?t(...s):t()}catch(i){sr(i,e,n)}}function Hn(t,e,n,s){if(ze(t)){const i=Zo(t,e,n,s);return i&&sd(i)&&i.catch(l=>{sr(l,e,n)}),i}if(Ie(t)){const i=[];for(let l=0;l>>1,i=Qt[s],l=jo(i);l=jo(n)?Qt.push(t):Qt.splice(Bg(e),0,t),t.flags|=1,Ad()}}function Ad(){zi||(zi=Td.then(Pd))}function zg(t){Ie(t)?ro.push(...t):cs&&t.id===-1?cs.splice(to+1,0,t):t.flags&1||(ro.push(t),t.flags|=1),Ad()}function Hc(t,e,n=xn+1){for(;njo(n)-jo(s));if(ro.length=0,cs){cs.push(...e);return}for(cs=e,to=0;tot.id==null?t.flags&2?-1:1/0:t.id;function Pd(t){try{for(xn=0;xn{s._d&&ji(-1);const l=Hi(e);let r;try{r=t(...i)}finally{Hi(l),s._d&&ji(1)}return r};return s._n=!0,s._c=!0,s._d=!0,s}function Be(t,e){if(Dt===null)return t;const n=ar(Dt),s=t.dirs||(t.dirs=[]);for(let i=0;i1)return n&&ze(e)?e.call(s&&s.proxy):e}}const Hg=Symbol.for("v-scx"),Ug=()=>$n(Hg);function hs(t,e,n){return Od(t,e,n)}function Od(t,e,n=ht){const{immediate:s,deep:i,flush:l,once:r}=n,c=Ht({},n),u=e&&s||!e&&l!=="post";let h;if(Go){if(l==="sync"){const _=Ug();h=_.__watcherHandles||(_.__watcherHandles=[])}else if(!u){const _=()=>{};return _.stop=zn,_.resume=zn,_.pause=zn,_}}const f=Ft;c.call=(_,y,P)=>Hn(_,f,y,P);let g=!1;l==="post"?c.scheduler=_=>{rn(_,f&&f.suspense)}:l!=="sync"&&(g=!0,c.scheduler=(_,y)=>{y?_():Ka(_)}),c.augmentJob=_=>{e&&(_.flags|=4),g&&(_.flags|=2,f&&(_.id=f.uid,_.i=f))};const C=Fg(t,e,c);return Go&&(h?h.push(C):u&&C()),C}function Vg(t,e,n){const s=this.proxy,i=At(t)?t.includes(".")?Md(s,t):()=>s[t]:t.bind(s,s);let l;ze(e)?l=e:(l=e.handler,n=e);const r=ei(this),c=Od(i,l.bind(s),n);return r(),c}function Md(t,e){const n=e.split(".");return()=>{let s=t;for(let i=0;it.__isTeleport,Wg=Symbol("_leaveCb");function Ga(t,e){t.shapeFlag&6&&t.component?(t.transition=e,Ga(t.component.subTree,e)):t.shapeFlag&128?(t.ssContent.transition=e.clone(t.ssContent),t.ssFallback.transition=e.clone(t.ssFallback)):t.transition=e}function $t(t,e){return ze(t)?Ht({name:t.name},e,{setup:t}):t}function Dd(t){t.ids=[t.ids[0]+t.ids[2]+++"-",0,0]}const Ui=new WeakMap;function Fo(t,e,n,s,i=!1){if(Ie(t)){t.forEach((y,P)=>Fo(y,e&&(Ie(e)?e[P]:e),n,s,i));return}if(ao(s)&&!i){s.shapeFlag&512&&s.type.__asyncResolved&&s.component.subTree.component&&Fo(t,e,n,s.component.subTree);return}const l=s.shapeFlag&4?ar(s.component):s.el,r=i?null:l,{i:c,r:u}=t,h=e&&e.r,f=c.refs===ht?c.refs={}:c.refs,g=c.setupState,C=st(g),_=g===ht?nd:y=>ot(C,y);if(h!=null&&h!==u){if(Uc(e),At(h))f[h]=null,_(h)&&(g[h]=null);else if(Bt(h)){h.value=null;const y=e;y.k&&(f[y.k]=null)}}if(ze(u))Zo(u,c,12,[r,f]);else{const y=At(u),P=Bt(u);if(y||P){const I=()=>{if(t.f){const H=y?_(u)?g[u]:f[u]:u.value;if(i)Ie(H)&&Na(H,l);else if(Ie(H))H.includes(l)||H.push(l);else if(y)f[u]=[l],_(u)&&(g[u]=f[u]);else{const W=[l];u.value=W,t.k&&(f[t.k]=W)}}else y?(f[u]=r,_(u)&&(g[u]=r)):P&&(u.value=r,t.k&&(f[t.k]=r))};if(r){const H=()=>{I(),Ui.delete(t)};H.id=-1,Ui.set(t,H),rn(H,n)}else Uc(t),I()}}}function Uc(t){const e=Ui.get(t);e&&(e.flags|=8,Ui.delete(t))}tr().requestIdleCallback;tr().cancelIdleCallback;const ao=t=>!!t.type.__asyncLoader,Ld=t=>t.type.__isKeepAlive;function Kg(t,e){Nd(t,"a",e)}function Gg(t,e){Nd(t,"da",e)}function Nd(t,e,n=Ft){const s=t.__wdc||(t.__wdc=()=>{let i=n;for(;i;){if(i.isDeactivated)return;i=i.parent}return t()});if(or(e,s,n),n){let i=n.parent;for(;i&&i.parent;)Ld(i.parent.vnode)&&Qg(s,e,n,i),i=i.parent}}function Qg(t,e,n,s){const i=or(e,t,s,!0);bo(()=>{Na(s[e],i)},n)}function or(t,e,n=Ft,s=!1){if(n){const i=n[t]||(n[t]=[]),l=e.__weh||(e.__weh=(...r)=>{Xn();const c=ei(n),u=Hn(e,n,t,r);return c(),Yn(),u});return s?i.unshift(l):i.push(l),l}}const ts=t=>(e,n=Ft)=>{(!Go||t==="sp")&&or(t,(...s)=>e(...s),n)},Jg=ts("bm"),cn=ts("m"),Xg=ts("bu"),Yg=ts("u"),Zg=ts("bum"),bo=ts("um"),e1=ts("sp"),t1=ts("rtg"),n1=ts("rtc");function s1(t,e=Ft){or("ec",t,e)}const o1="components";function zt(t,e){return r1(o1,t,!0,e)||t}const i1=Symbol.for("v-ndc");function r1(t,e,n=!0,s=!1){const i=Dt||Ft;if(i){const l=i.type;{const c=W1(l,!1);if(c&&(c===e||c===vn(e)||c===Zi(vn(e))))return l}const r=Vc(i[t]||l[t],e)||Vc(i.appContext[t],e);return!r&&s?l:r}}function Vc(t,e){return t&&(t[e]||t[vn(e)]||t[Zi(vn(e))])}function Yt(t,e,n,s){let i;const l=n,r=Ie(t);if(r||At(t)){const c=r&&Ds(t);let u=!1,h=!1;c&&(u=!gn(t),h=Zn(t),t=nr(t)),i=new Array(t.length);for(let f=0,g=t.length;fe(c,u,void 0,l));else{const c=Object.keys(t);i=new Array(c.length);for(let u=0,h=c.length;u0;return b(),Wo(Xe,null,[ke("slot",n,s&&s())],h?-2:64)}let l=t[e];l&&l._c&&(l._d=!1),b();const r=l&&Fd(l(n)),c=n.key||r&&r.key,u=Wo(Xe,{key:(c&&!Tn(c)?c:`_${e}`)+(!r&&s?"_fb":"")},r||(s?s():[]),r&&t._===1?64:-2);return u.scopeId&&(u.slotScopeIds=[u.scopeId+"-s"]),l&&l._c&&(l._d=!0),u}function Fd(t){return t.some(e=>Ko(e)?!(e.type===es||e.type===Xe&&!Fd(e.children)):!0)?t:null}const ba=t=>t?nf(t)?ar(t):ba(t.parent):null,xo=Ht(Object.create(null),{$:t=>t,$el:t=>t.vnode.el,$data:t=>t.data,$props:t=>t.props,$attrs:t=>t.attrs,$slots:t=>t.slots,$refs:t=>t.refs,$parent:t=>ba(t.parent),$root:t=>ba(t.root),$host:t=>t.ce,$emit:t=>t.emit,$options:t=>Bd(t),$forceUpdate:t=>t.f||(t.f=()=>{Ka(t.update)}),$nextTick:t=>t.n||(t.n=Wa.bind(t.proxy)),$watch:t=>Vg.bind(t)}),ta=(t,e)=>t!==ht&&!t.__isScriptSetup&&ot(t,e),l1={get({_:t},e){if(e==="__v_skip")return!0;const{ctx:n,setupState:s,data:i,props:l,accessCache:r,type:c,appContext:u}=t;if(e[0]!=="$"){const C=r[e];if(C!==void 0)switch(C){case 1:return s[e];case 2:return i[e];case 4:return n[e];case 3:return l[e]}else{if(ta(s,e))return r[e]=1,s[e];if(i!==ht&&ot(i,e))return r[e]=2,i[e];if(ot(l,e))return r[e]=3,l[e];if(n!==ht&&ot(n,e))return r[e]=4,n[e];ya&&(r[e]=0)}}const h=xo[e];let f,g;if(h)return e==="$attrs"&&Lt(t.attrs,"get",""),h(t);if((f=c.__cssModules)&&(f=f[e]))return f;if(n!==ht&&ot(n,e))return r[e]=4,n[e];if(g=u.config.globalProperties,ot(g,e))return g[e]},set({_:t},e,n){const{data:s,setupState:i,ctx:l}=t;return ta(i,e)?(i[e]=n,!0):s!==ht&&ot(s,e)?(s[e]=n,!0):ot(t.props,e)||e[0]==="$"&&e.slice(1)in t?!1:(l[e]=n,!0)},has({_:{data:t,setupState:e,accessCache:n,ctx:s,appContext:i,props:l,type:r}},c){let u;return!!(n[c]||t!==ht&&c[0]!=="$"&&ot(t,c)||ta(e,c)||ot(l,c)||ot(s,c)||ot(xo,c)||ot(i.config.globalProperties,c)||(u=r.__cssModules)&&u[c])},defineProperty(t,e,n){return n.get!=null?t._.accessCache[e]=0:ot(n,"value")&&this.set(t,e,n.value,null),Reflect.defineProperty(t,e,n)}};function jc(t){return Ie(t)?t.reduce((e,n)=>(e[n]=null,e),{}):t}let ya=!0;function c1(t){const e=Bd(t),n=t.proxy,s=t.ctx;ya=!1,e.beforeCreate&&qc(e.beforeCreate,t,"bc");const{data:i,computed:l,methods:r,watch:c,provide:u,inject:h,created:f,beforeMount:g,mounted:C,beforeUpdate:_,updated:y,activated:P,deactivated:I,beforeDestroy:H,beforeUnmount:W,destroyed:G,unmounted:F,render:ne,renderTracked:he,renderTriggered:ce,errorCaptured:Ee,serverPrefetch:Se,expose:_e,inheritAttrs:ye,components:Me,directives:ve,filters:te}=e;if(h&&u1(h,s,null),r)for(const oe in r){const Q=r[oe];ze(Q)&&(s[oe]=Q.bind(n))}if(i){const oe=i.call(n,n);pt(oe)&&(t.data=Xt(oe))}if(ya=!0,l)for(const oe in l){const Q=l[oe],Re=ze(Q)?Q.bind(n,n):ze(Q.get)?Q.get.bind(n,n):zn,He=!ze(Q)&&ze(Q.set)?Q.set.bind(n):zn,z=Ye({get:Re,set:He});Object.defineProperty(s,oe,{enumerable:!0,configurable:!0,get:()=>z.value,set:Qe=>z.value=Qe})}if(c)for(const oe in c)xd(c[oe],s,n,oe);if(u){const oe=ze(u)?u.call(n):u;Reflect.ownKeys(oe).forEach(Q=>{Ii(Q,oe[Q])})}f&&qc(f,t,"c");function Y(oe,Q){Ie(Q)?Q.forEach(Re=>oe(Re.bind(n))):Q&&oe(Q.bind(n))}if(Y(Jg,g),Y(cn,C),Y(Xg,_),Y(Yg,y),Y(Kg,P),Y(Gg,I),Y(s1,Ee),Y(n1,he),Y(t1,ce),Y(Zg,W),Y(bo,F),Y(e1,Se),Ie(_e))if(_e.length){const oe=t.exposed||(t.exposed={});_e.forEach(Q=>{Object.defineProperty(oe,Q,{get:()=>n[Q],set:Re=>n[Q]=Re,enumerable:!0})})}else t.exposed||(t.exposed={});ne&&t.render===zn&&(t.render=ne),ye!=null&&(t.inheritAttrs=ye),Me&&(t.components=Me),ve&&(t.directives=ve),Se&&Dd(t)}function u1(t,e,n=zn){Ie(t)&&(t=wa(t));for(const s in t){const i=t[s];let l;pt(i)?"default"in i?l=$n(i.from||s,i.default,!0):l=$n(i.from||s):l=$n(i),Bt(l)?Object.defineProperty(e,s,{enumerable:!0,configurable:!0,get:()=>l.value,set:r=>l.value=r}):e[s]=l}}function qc(t,e,n){Hn(Ie(t)?t.map(s=>s.bind(e.proxy)):t.bind(e.proxy),e,n)}function xd(t,e,n,s){let i=s.includes(".")?Md(n,s):()=>n[s];if(At(t)){const l=e[t];ze(l)&&hs(i,l)}else if(ze(t))hs(i,t.bind(n));else if(pt(t))if(Ie(t))t.forEach(l=>xd(l,e,n,s));else{const l=ze(t.handler)?t.handler.bind(n):e[t.handler];ze(l)&&hs(i,l,t)}}function Bd(t){const e=t.type,{mixins:n,extends:s}=e,{mixins:i,optionsCache:l,config:{optionMergeStrategies:r}}=t.appContext,c=l.get(e);let u;return c?u=c:!i.length&&!n&&!s?u=e:(u={},i.length&&i.forEach(h=>Vi(u,h,r,!0)),Vi(u,e,r)),pt(e)&&l.set(e,u),u}function Vi(t,e,n,s=!1){const{mixins:i,extends:l}=e;l&&Vi(t,l,n,!0),i&&i.forEach(r=>Vi(t,r,n,!0));for(const r in e)if(!(s&&r==="expose")){const c=d1[r]||n&&n[r];t[r]=c?c(t[r],e[r]):e[r]}return t}const d1={data:Wc,props:Kc,emits:Kc,methods:Mo,computed:Mo,beforeCreate:Kt,created:Kt,beforeMount:Kt,mounted:Kt,beforeUpdate:Kt,updated:Kt,beforeDestroy:Kt,beforeUnmount:Kt,destroyed:Kt,unmounted:Kt,activated:Kt,deactivated:Kt,errorCaptured:Kt,serverPrefetch:Kt,components:Mo,directives:Mo,watch:h1,provide:Wc,inject:f1};function Wc(t,e){return e?t?function(){return Ht(ze(t)?t.call(this,this):t,ze(e)?e.call(this,this):e)}:e:t}function f1(t,e){return Mo(wa(t),wa(e))}function wa(t){if(Ie(t)){const e={};for(let n=0;ne==="modelValue"||e==="model-value"?t.modelModifiers:t[`${e}Modifiers`]||t[`${vn(e)}Modifiers`]||t[`${gs(e)}Modifiers`];function v1(t,e,...n){if(t.isUnmounted)return;const s=t.vnode.props||ht;let i=n;const l=e.startsWith("update:"),r=l&&m1(s,e.slice(7));r&&(r.trim&&(i=n.map(f=>At(f)?f.trim():f)),r.number&&(i=n.map(er)));let c,u=s[c=Jr(e)]||s[c=Jr(vn(e))];!u&&l&&(u=s[c=Jr(gs(e))]),u&&Hn(u,t,6,i);const h=s[c+"Once"];if(h){if(!t.emitted)t.emitted={};else if(t.emitted[c])return;t.emitted[c]=!0,Hn(h,t,6,i)}}const b1=new WeakMap;function Hd(t,e,n=!1){const s=n?b1:e.emitsCache,i=s.get(t);if(i!==void 0)return i;const l=t.emits;let r={},c=!1;if(!ze(t)){const u=h=>{const f=Hd(h,e,!0);f&&(c=!0,Ht(r,f))};!n&&e.mixins.length&&e.mixins.forEach(u),t.extends&&u(t.extends),t.mixins&&t.mixins.forEach(u)}return!l&&!c?(pt(t)&&s.set(t,null),null):(Ie(l)?l.forEach(u=>r[u]=null):Ht(r,l),pt(t)&&s.set(t,r),r)}function ir(t,e){return!t||!Xi(e)?!1:(e=e.slice(2).replace(/Once$/,""),ot(t,e[0].toLowerCase()+e.slice(1))||ot(t,gs(e))||ot(t,e))}function Gc(t){const{type:e,vnode:n,proxy:s,withProxy:i,propsOptions:[l],slots:r,attrs:c,emit:u,render:h,renderCache:f,props:g,data:C,setupState:_,ctx:y,inheritAttrs:P}=t,I=Hi(t);let H,W;try{if(n.shapeFlag&4){const F=i||s,ne=F;H=Bn(h.call(ne,F,f,g,_,C,y)),W=c}else{const F=e;H=Bn(F.length>1?F(g,{attrs:c,slots:r,emit:u}):F(g,null)),W=e.props?c:y1(c)}}catch(F){Bo.length=0,sr(F,t,1),H=ke(es)}let G=H;if(W&&P!==!1){const F=Object.keys(W),{shapeFlag:ne}=G;F.length&&ne&7&&(l&&F.some(La)&&(W=w1(W,l)),G=uo(G,W,!1,!0))}return n.dirs&&(G=uo(G,null,!1,!0),G.dirs=G.dirs?G.dirs.concat(n.dirs):n.dirs),n.transition&&Ga(G,n.transition),H=G,Hi(I),H}const y1=t=>{let e;for(const n in t)(n==="class"||n==="style"||Xi(n))&&((e||(e={}))[n]=t[n]);return e},w1=(t,e)=>{const n={};for(const s in t)(!La(s)||!(s.slice(9)in e))&&(n[s]=t[s]);return n};function _1(t,e,n){const{props:s,children:i,component:l}=t,{props:r,children:c,patchFlag:u}=e,h=l.emitsOptions;if(e.dirs||e.transition)return!0;if(n&&u>=0){if(u&1024)return!0;if(u&16)return s?Qc(s,r,h):!!r;if(u&8){const f=e.dynamicProps;for(let g=0;gObject.create(Ud),jd=t=>Object.getPrototypeOf(t)===Ud;function k1(t,e,n,s=!1){const i={},l=Vd();t.propsDefaults=Object.create(null),qd(t,e,i,l);for(const r in t.propsOptions[0])r in i||(i[r]=void 0);n?t.props=s?i:Sd(i):t.type.props?t.props=i:t.props=l,t.attrs=l}function S1(t,e,n,s){const{props:i,attrs:l,vnode:{patchFlag:r}}=t,c=st(i),[u]=t.propsOptions;let h=!1;if((s||r>0)&&!(r&16)){if(r&8){const f=t.vnode.dynamicProps;for(let g=0;g{u=!0;const[C,_]=Wd(g,e,!0);Ht(r,C),_&&c.push(..._)};!n&&e.mixins.length&&e.mixins.forEach(f),t.extends&&f(t.extends),t.mixins&&t.mixins.forEach(f)}if(!l&&!u)return pt(t)&&s.set(t,so),so;if(Ie(l))for(let f=0;ft==="_"||t==="_ctx"||t==="$stable",Ja=t=>Ie(t)?t.map(Bn):[Bn(t)],$1=(t,e,n)=>{if(e._n)return e;const s=Ze((...i)=>Ja(e(...i)),n);return s._c=!1,s},Kd=(t,e,n)=>{const s=t._ctx;for(const i in t){if(Qa(i))continue;const l=t[i];if(ze(l))e[i]=$1(i,l,s);else if(l!=null){const r=Ja(l);e[i]=()=>r}}},Gd=(t,e)=>{const n=Ja(e);t.slots.default=()=>n},Qd=(t,e,n)=>{for(const s in e)(n||!Qa(s))&&(t[s]=e[s])},T1=(t,e,n)=>{const s=t.slots=Vd();if(t.vnode.shapeFlag&32){const i=e._;i?(Qd(s,e,n),n&&rd(s,"_",i,!0)):Kd(e,s)}else e&&Gd(t,e)},A1=(t,e,n)=>{const{vnode:s,slots:i}=t;let l=!0,r=ht;if(s.shapeFlag&32){const c=e._;c?n&&c===1?l=!1:Qd(i,e,n):(l=!e.$stable,Kd(e,i)),r=e}else e&&(Gd(t,e),r={default:1});if(l)for(const c in i)!Qa(c)&&r[c]==null&&delete i[c]},rn=M1;function R1(t){return P1(t)}function P1(t,e){const n=tr();n.__VUE__=!0;const{insert:s,remove:i,patchProp:l,createElement:r,createText:c,createComment:u,setText:h,setElementText:f,parentNode:g,nextSibling:C,setScopeId:_=zn,insertStaticContent:y}=t,P=(v,E,R,j=null,K=null,V=null,le=void 0,ie=null,se=!!E.dynamicChildren)=>{if(v===E)return;v&&!Ro(v,E)&&(j=M(v),Qe(v,K,V,!0),v=null),E.patchFlag===-2&&(se=!1,E.dynamicChildren=null);const{type:X,ref:$e,shapeFlag:de}=E;switch(X){case rr:I(v,E,R,j);break;case es:H(v,E,R,j);break;case Oi:v==null&&W(E,R,j,le);break;case Xe:Me(v,E,R,j,K,V,le,ie,se);break;default:de&1?ne(v,E,R,j,K,V,le,ie,se):de&6?ve(v,E,R,j,K,V,le,ie,se):(de&64||de&128)&&X.process(v,E,R,j,K,V,le,ie,se,x)}$e!=null&&K?Fo($e,v&&v.ref,V,E||v,!E):$e==null&&v&&v.ref!=null&&Fo(v.ref,null,V,v,!0)},I=(v,E,R,j)=>{if(v==null)s(E.el=c(E.children),R,j);else{const K=E.el=v.el;E.children!==v.children&&h(K,E.children)}},H=(v,E,R,j)=>{v==null?s(E.el=u(E.children||""),R,j):E.el=v.el},W=(v,E,R,j)=>{[v.el,v.anchor]=y(v.children,E,R,j,v.el,v.anchor)},G=({el:v,anchor:E},R,j)=>{let K;for(;v&&v!==E;)K=C(v),s(v,R,j),v=K;s(E,R,j)},F=({el:v,anchor:E})=>{let R;for(;v&&v!==E;)R=C(v),i(v),v=R;i(E)},ne=(v,E,R,j,K,V,le,ie,se)=>{if(E.type==="svg"?le="svg":E.type==="math"&&(le="mathml"),v==null)he(E,R,j,K,V,le,ie,se);else{const X=v.el&&v.el._isVueCE?v.el:null;try{X&&X._beginPatch(),Se(v,E,K,V,le,ie,se)}finally{X&&X._endPatch()}}},he=(v,E,R,j,K,V,le,ie)=>{let se,X;const{props:$e,shapeFlag:de,transition:Ce,dirs:Te}=v;if(se=v.el=r(v.type,V,$e&&$e.is,$e),de&8?f(se,v.children):de&16&&Ee(v.children,se,null,j,K,na(v,V),le,ie),Te&&As(v,null,j,"created"),ce(se,v,v.scopeId,le,j),$e){for(const Je in $e)Je!=="value"&&!Do(Je)&&l(se,Je,null,$e[Je],V,j);"value"in $e&&l(se,"value",null,$e.value,V),(X=$e.onVnodeBeforeMount)&&Nn(X,j,v)}Te&&As(v,null,j,"beforeMount");const Oe=I1(K,Ce);Oe&&Ce.beforeEnter(se),s(se,E,R),((X=$e&&$e.onVnodeMounted)||Oe||Te)&&rn(()=>{X&&Nn(X,j,v),Oe&&Ce.enter(se),Te&&As(v,null,j,"mounted")},K)},ce=(v,E,R,j,K)=>{if(R&&_(v,R),j)for(let V=0;V{for(let X=se;X{const ie=E.el=v.el;let{patchFlag:se,dynamicChildren:X,dirs:$e}=E;se|=v.patchFlag&16;const de=v.props||ht,Ce=E.props||ht;let Te;if(R&&Rs(R,!1),(Te=Ce.onVnodeBeforeUpdate)&&Nn(Te,R,E,v),$e&&As(E,v,R,"beforeUpdate"),R&&Rs(R,!0),(de.innerHTML&&Ce.innerHTML==null||de.textContent&&Ce.textContent==null)&&f(ie,""),X?_e(v.dynamicChildren,X,ie,R,j,na(E,K),V):le||Q(v,E,ie,null,R,j,na(E,K),V,!1),se>0){if(se&16)ye(ie,de,Ce,R,K);else if(se&2&&de.class!==Ce.class&&l(ie,"class",null,Ce.class,K),se&4&&l(ie,"style",de.style,Ce.style,K),se&8){const Oe=E.dynamicProps;for(let Je=0;Je{Te&&Nn(Te,R,E,v),$e&&As(E,v,R,"updated")},j)},_e=(v,E,R,j,K,V,le)=>{for(let ie=0;ie{if(E!==R){if(E!==ht)for(const V in E)!Do(V)&&!(V in R)&&l(v,V,E[V],null,K,j);for(const V in R){if(Do(V))continue;const le=R[V],ie=E[V];le!==ie&&V!=="value"&&l(v,V,ie,le,K,j)}"value"in R&&l(v,"value",E.value,R.value,K)}},Me=(v,E,R,j,K,V,le,ie,se)=>{const X=E.el=v?v.el:c(""),$e=E.anchor=v?v.anchor:c("");let{patchFlag:de,dynamicChildren:Ce,slotScopeIds:Te}=E;Te&&(ie=ie?ie.concat(Te):Te),v==null?(s(X,R,j),s($e,R,j),Ee(E.children||[],R,$e,K,V,le,ie,se)):de>0&&de&64&&Ce&&v.dynamicChildren&&v.dynamicChildren.length===Ce.length?(_e(v.dynamicChildren,Ce,R,K,V,le,ie),(E.key!=null||K&&E===K.subTree)&&Jd(v,E,!0)):Q(v,E,R,$e,K,V,le,ie,se)},ve=(v,E,R,j,K,V,le,ie,se)=>{E.slotScopeIds=ie,v==null?E.shapeFlag&512?K.ctx.activate(E,R,j,le,se):te(E,R,j,K,V,le,se):Le(v,E,se)},te=(v,E,R,j,K,V,le)=>{const ie=v.component=z1(v,j,K);if(Ld(v)&&(ie.ctx.renderer=x),U1(ie,!1,le),ie.asyncDep){if(K&&K.registerDep(ie,Y,le),!v.el){const se=ie.subTree=ke(es);H(null,se,E,R),v.placeholder=se.el}}else Y(ie,v,E,R,K,V,le)},Le=(v,E,R)=>{const j=E.component=v.component;if(_1(v,E,R))if(j.asyncDep&&!j.asyncResolved){oe(j,E,R);return}else j.next=E,j.update();else E.el=v.el,j.vnode=E},Y=(v,E,R,j,K,V,le)=>{const ie=()=>{if(v.isMounted){let{next:de,bu:Ce,u:Te,parent:Oe,vnode:Je}=v;{const qe=Xd(v);if(qe){de&&(de.el=Je.el,oe(v,de,le)),qe.asyncDep.then(()=>{v.isUnmounted||ie()});return}}let k=de,N;Rs(v,!1),de?(de.el=Je.el,oe(v,de,le)):de=Je,Ce&&Pi(Ce),(N=de.props&&de.props.onVnodeBeforeUpdate)&&Nn(N,Oe,de,Je),Rs(v,!0);const ue=Gc(v),me=v.subTree;v.subTree=ue,P(me,ue,g(me.el),M(me),v,K,V),de.el=ue.el,k===null&&C1(v,ue.el),Te&&rn(Te,K),(N=de.props&&de.props.onVnodeUpdated)&&rn(()=>Nn(N,Oe,de,Je),K)}else{let de;const{el:Ce,props:Te}=E,{bm:Oe,m:Je,parent:k,root:N,type:ue}=v,me=ao(E);Rs(v,!1),Oe&&Pi(Oe),!me&&(de=Te&&Te.onVnodeBeforeMount)&&Nn(de,k,E),Rs(v,!0);{N.ce&&N.ce._def.shadowRoot!==!1&&N.ce._injectChildStyle(ue);const qe=v.subTree=Gc(v);P(null,qe,R,j,v,K,V),E.el=qe.el}if(Je&&rn(Je,K),!me&&(de=Te&&Te.onVnodeMounted)){const qe=E;rn(()=>Nn(de,k,qe),K)}(E.shapeFlag&256||k&&ao(k.vnode)&&k.vnode.shapeFlag&256)&&v.a&&rn(v.a,K),v.isMounted=!0,E=R=j=null}};v.scope.on();const se=v.effect=new ud(ie);v.scope.off();const X=v.update=se.run.bind(se),$e=v.job=se.runIfDirty.bind(se);$e.i=v,$e.id=v.uid,se.scheduler=()=>Ka($e),Rs(v,!0),X()},oe=(v,E,R)=>{E.component=v;const j=v.vnode.props;v.vnode=E,v.next=null,S1(v,E.props,j,R),A1(v,E.children,R),Xn(),Hc(v),Yn()},Q=(v,E,R,j,K,V,le,ie,se=!1)=>{const X=v&&v.children,$e=v?v.shapeFlag:0,de=E.children,{patchFlag:Ce,shapeFlag:Te}=E;if(Ce>0){if(Ce&128){He(X,de,R,j,K,V,le,ie,se);return}else if(Ce&256){Re(X,de,R,j,K,V,le,ie,se);return}}Te&8?($e&16&&Ae(X,K,V),de!==X&&f(R,de)):$e&16?Te&16?He(X,de,R,j,K,V,le,ie,se):Ae(X,K,V,!0):($e&8&&f(R,""),Te&16&&Ee(de,R,j,K,V,le,ie,se))},Re=(v,E,R,j,K,V,le,ie,se)=>{v=v||so,E=E||so;const X=v.length,$e=E.length,de=Math.min(X,$e);let Ce;for(Ce=0;Ce$e?Ae(v,K,V,!0,!1,de):Ee(E,R,j,K,V,le,ie,se,de)},He=(v,E,R,j,K,V,le,ie,se)=>{let X=0;const $e=E.length;let de=v.length-1,Ce=$e-1;for(;X<=de&&X<=Ce;){const Te=v[X],Oe=E[X]=se?us(E[X]):Bn(E[X]);if(Ro(Te,Oe))P(Te,Oe,R,null,K,V,le,ie,se);else break;X++}for(;X<=de&&X<=Ce;){const Te=v[de],Oe=E[Ce]=se?us(E[Ce]):Bn(E[Ce]);if(Ro(Te,Oe))P(Te,Oe,R,null,K,V,le,ie,se);else break;de--,Ce--}if(X>de){if(X<=Ce){const Te=Ce+1,Oe=Te<$e?E[Te].el:j;for(;X<=Ce;)P(null,E[X]=se?us(E[X]):Bn(E[X]),R,Oe,K,V,le,ie,se),X++}}else if(X>Ce)for(;X<=de;)Qe(v[X],K,V,!0),X++;else{const Te=X,Oe=X,Je=new Map;for(X=Oe;X<=Ce;X++){const mt=E[X]=se?us(E[X]):Bn(E[X]);mt.key!=null&&Je.set(mt.key,X)}let k,N=0;const ue=Ce-Oe+1;let me=!1,qe=0;const Ot=new Array(ue);for(X=0;X=ue){Qe(mt,K,V,!0);continue}let et;if(mt.key!=null)et=Je.get(mt.key);else for(k=Oe;k<=Ce;k++)if(Ot[k-Oe]===0&&Ro(mt,E[k])){et=k;break}et===void 0?Qe(mt,K,V,!0):(Ot[et-Oe]=X+1,et>=qe?qe=et:me=!0,P(mt,E[et],R,null,K,V,le,ie,se),N++)}const Ut=me?O1(Ot):so;for(k=Ut.length-1,X=ue-1;X>=0;X--){const mt=Oe+X,et=E[mt],In=E[mt+1],bn=mt+1<$e?In.el||Yd(In):j;Ot[X]===0?P(null,et,R,bn,K,V,le,ie,se):me&&(k<0||X!==Ut[k]?z(et,R,bn,2):k--)}}},z=(v,E,R,j,K=null)=>{const{el:V,type:le,transition:ie,children:se,shapeFlag:X}=v;if(X&6){z(v.component.subTree,E,R,j);return}if(X&128){v.suspense.move(E,R,j);return}if(X&64){le.move(v,E,R,x);return}if(le===Xe){s(V,E,R);for(let de=0;deie.enter(V),K);else{const{leave:de,delayLeave:Ce,afterLeave:Te}=ie,Oe=()=>{v.ctx.isUnmounted?i(V):s(V,E,R)},Je=()=>{V._isLeaving&&V[Wg](!0),de(V,()=>{Oe(),Te&&Te()})};Ce?Ce(V,Oe,Je):Je()}else s(V,E,R)},Qe=(v,E,R,j=!1,K=!1)=>{const{type:V,props:le,ref:ie,children:se,dynamicChildren:X,shapeFlag:$e,patchFlag:de,dirs:Ce,cacheIndex:Te}=v;if(de===-2&&(K=!1),ie!=null&&(Xn(),Fo(ie,null,R,v,!0),Yn()),Te!=null&&(E.renderCache[Te]=void 0),$e&256){E.ctx.deactivate(v);return}const Oe=$e&1&&Ce,Je=!ao(v);let k;if(Je&&(k=le&&le.onVnodeBeforeUnmount)&&Nn(k,E,v),$e&6)gt(v.component,R,j);else{if($e&128){v.suspense.unmount(R,j);return}Oe&&As(v,null,E,"beforeUnmount"),$e&64?v.type.remove(v,E,R,x,j):X&&!X.hasOnce&&(V!==Xe||de>0&&de&64)?Ae(X,E,R,!1,!0):(V===Xe&&de&384||!K&&$e&16)&&Ae(se,E,R),j&&Ke(v)}(Je&&(k=le&&le.onVnodeUnmounted)||Oe)&&rn(()=>{k&&Nn(k,E,v),Oe&&As(v,null,E,"unmounted")},R)},Ke=v=>{const{type:E,el:R,anchor:j,transition:K}=v;if(E===Xe){yt(R,j);return}if(E===Oi){F(v);return}const V=()=>{i(R),K&&!K.persisted&&K.afterLeave&&K.afterLeave()};if(v.shapeFlag&1&&K&&!K.persisted){const{leave:le,delayLeave:ie}=K,se=()=>le(R,V);ie?ie(v.el,V,se):se()}else V()},yt=(v,E)=>{let R;for(;v!==E;)R=C(v),i(v),v=R;i(E)},gt=(v,E,R)=>{const{bum:j,scope:K,job:V,subTree:le,um:ie,m:se,a:X}=v;Xc(se),Xc(X),j&&Pi(j),K.stop(),V&&(V.flags|=8,Qe(le,v,E,R)),ie&&rn(ie,E),rn(()=>{v.isUnmounted=!0},E)},Ae=(v,E,R,j=!1,K=!1,V=0)=>{for(let le=V;le{if(v.shapeFlag&6)return M(v.component.subTree);if(v.shapeFlag&128)return v.suspense.next();const E=C(v.anchor||v.el),R=E&&E[jg];return R?C(R):E};let ee=!1;const S=(v,E,R)=>{let j;v==null?E._vnode&&(Qe(E._vnode,null,null,!0),j=E._vnode.component):P(E._vnode||null,v,E,null,null,null,R),E._vnode=v,ee||(ee=!0,Hc(j),Rd(),ee=!1)},x={p:P,um:Qe,m:z,r:Ke,mt:te,mc:Ee,pc:Q,pbc:_e,n:M,o:t};return{render:S,hydrate:void 0,createApp:g1(S)}}function na({type:t,props:e},n){return n==="svg"&&t==="foreignObject"||n==="mathml"&&t==="annotation-xml"&&e&&e.encoding&&e.encoding.includes("html")?void 0:n}function Rs({effect:t,job:e},n){n?(t.flags|=32,e.flags|=4):(t.flags&=-33,e.flags&=-5)}function I1(t,e){return(!t||t&&!t.pendingBranch)&&e&&!e.persisted}function Jd(t,e,n=!1){const s=t.children,i=e.children;if(Ie(s)&&Ie(i))for(let l=0;l>1,t[n[c]]0&&(e[s]=n[l-1]),n[l]=s)}}for(l=n.length,r=n[l-1];l-- >0;)n[l]=r,r=e[r];return n}function Xd(t){const e=t.subTree.component;if(e)return e.asyncDep&&!e.asyncResolved?e:Xd(e)}function Xc(t){if(t)for(let e=0;et.__isSuspense;function M1(t,e){e&&e.pendingBranch?Ie(t)?e.effects.push(...t):e.effects.push(t):zg(t)}const Xe=Symbol.for("v-fgt"),rr=Symbol.for("v-txt"),es=Symbol.for("v-cmt"),Oi=Symbol.for("v-stc"),Bo=[];let an=null;function b(t=!1){Bo.push(an=t?null:[])}function D1(){Bo.pop(),an=Bo[Bo.length-1]||null}let qo=1;function ji(t,e=!1){qo+=t,t<0&&an&&e&&(an.hasOnce=!0)}function ef(t){return t.dynamicChildren=qo>0?an||so:null,D1(),qo>0&&an&&an.push(t),t}function w(t,e,n,s,i,l){return ef(o(t,e,n,s,i,l,!0))}function Wo(t,e,n,s,i){return ef(ke(t,e,n,s,i,!0))}function Ko(t){return t?t.__v_isVNode===!0:!1}function Ro(t,e){return t.type===e.type&&t.key===e.key}const tf=({key:t})=>t??null,Mi=({ref:t,ref_key:e,ref_for:n})=>(typeof t=="number"&&(t=""+t),t!=null?At(t)||Bt(t)||ze(t)?{i:Dt,r:t,k:e,f:!!n}:t:null);function o(t,e=null,n=null,s=0,i=null,l=t===Xe?0:1,r=!1,c=!1){const u={__v_isVNode:!0,__v_skip:!0,type:t,props:e,key:e&&tf(e),ref:e&&Mi(e),scopeId:Id,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:l,patchFlag:s,dynamicProps:i,dynamicChildren:null,appContext:null,ctx:Dt};return c?(Xa(u,n),l&128&&t.normalize(u)):n&&(u.shapeFlag|=At(n)?8:16),qo>0&&!r&&an&&(u.patchFlag>0||l&6)&&u.patchFlag!==32&&an.push(u),u}const ke=L1;function L1(t,e=null,n=null,s=0,i=null,l=!1){if((!t||t===i1)&&(t=es),Ko(t)){const c=uo(t,e,!0);return n&&Xa(c,n),qo>0&&!l&&an&&(c.shapeFlag&6?an[an.indexOf(t)]=c:an.push(c)),c.patchFlag=-2,c}if(K1(t)&&(t=t.__vccOpts),e){e=N1(e);let{class:c,style:u}=e;c&&!At(c)&&(e.class=ae(c)),pt(u)&&(qa(u)&&!Ie(u)&&(u=Ht({},u)),e.style=Sn(u))}const r=At(t)?1:Zd(t)?128:qg(t)?64:pt(t)?4:ze(t)?2:0;return o(t,e,n,s,i,r,l,!0)}function N1(t){return t?qa(t)||jd(t)?Ht({},t):t:null}function uo(t,e,n=!1,s=!1){const{props:i,ref:l,patchFlag:r,children:c,transition:u}=t,h=e?F1(i||{},e):i,f={__v_isVNode:!0,__v_skip:!0,type:t.type,props:h,key:h&&tf(h),ref:e&&e.ref?n&&l?Ie(l)?l.concat(Mi(e)):[l,Mi(e)]:Mi(e):l,scopeId:t.scopeId,slotScopeIds:t.slotScopeIds,children:c,target:t.target,targetStart:t.targetStart,targetAnchor:t.targetAnchor,staticCount:t.staticCount,shapeFlag:t.shapeFlag,patchFlag:e&&t.type!==Xe?r===-1?16:r|16:r,dynamicProps:t.dynamicProps,dynamicChildren:t.dynamicChildren,appContext:t.appContext,dirs:t.dirs,transition:u,component:t.component,suspense:t.suspense,ssContent:t.ssContent&&uo(t.ssContent),ssFallback:t.ssFallback&&uo(t.ssFallback),placeholder:t.placeholder,el:t.el,anchor:t.anchor,ctx:t.ctx,ce:t.ce};return u&&s&&Ga(f,u.clone(f)),f}function L(t=" ",e=0){return ke(rr,null,t,e)}function Cn(t,e){const n=ke(Oi,null,t);return n.staticCount=e,n}function U(t="",e=!1){return e?(b(),Wo(es,null,t)):ke(es,null,t)}function Bn(t){return t==null||typeof t=="boolean"?ke(es):Ie(t)?ke(Xe,null,t.slice()):Ko(t)?us(t):ke(rr,null,String(t))}function us(t){return t.el===null&&t.patchFlag!==-1||t.memo?t:uo(t)}function Xa(t,e){let n=0;const{shapeFlag:s}=t;if(e==null)e=null;else if(Ie(e))n=16;else if(typeof e=="object")if(s&65){const i=e.default;i&&(i._c&&(i._d=!1),Xa(t,i()),i._c&&(i._d=!0));return}else{n=32;const i=e._;!i&&!jd(e)?e._ctx=Dt:i===3&&Dt&&(Dt.slots._===1?e._=1:(e._=2,t.patchFlag|=1024))}else ze(e)?(e={default:e,_ctx:Dt},n=32):(e=String(e),s&64?(n=16,e=[L(e)]):n=8);t.children=e,t.shapeFlag|=n}function F1(...t){const e={};for(let n=0;nFt||Dt;let qi,Ca;{const t=tr(),e=(n,s)=>{let i;return(i=t[n])||(i=t[n]=[]),i.push(s),l=>{i.length>1?i.forEach(r=>r(l)):i[0](l)}};qi=e("__VUE_INSTANCE_SETTERS__",n=>Ft=n),Ca=e("__VUE_SSR_SETTERS__",n=>Go=n)}const ei=t=>{const e=Ft;return qi(t),t.scope.on(),()=>{t.scope.off(),qi(e)}},Yc=()=>{Ft&&Ft.scope.off(),qi(null)};function nf(t){return t.vnode.shapeFlag&4}let Go=!1;function U1(t,e=!1,n=!1){e&&Ca(e);const{props:s,children:i}=t.vnode,l=nf(t);k1(t,s,l,e),T1(t,i,n||e);const r=l?V1(t,e):void 0;return e&&Ca(!1),r}function V1(t,e){const n=t.type;t.accessCache=Object.create(null),t.proxy=new Proxy(t.ctx,l1);const{setup:s}=n;if(s){Xn();const i=t.setupContext=s.length>1?q1(t):null,l=ei(t),r=Zo(s,t,0,[t.props,i]),c=sd(r);if(Yn(),l(),(c||t.sp)&&!ao(t)&&Dd(t),c){if(r.then(Yc,Yc),e)return r.then(u=>{Zc(t,u)}).catch(u=>{sr(u,t,0)});t.asyncDep=r}else Zc(t,r)}else sf(t)}function Zc(t,e,n){ze(e)?t.type.__ssrInlineRender?t.ssrRender=e:t.render=e:pt(e)&&(t.setupState=$d(e)),sf(t)}function sf(t,e,n){const s=t.type;t.render||(t.render=s.render||zn);{const i=ei(t);Xn();try{c1(t)}finally{Yn(),i()}}}const j1={get(t,e){return Lt(t,"get",""),t[e]}};function q1(t){const e=n=>{t.exposed=n||{}};return{attrs:new Proxy(t.attrs,j1),slots:t.slots,emit:t.emit,expose:e}}function ar(t){return t.exposed?t.exposeProxy||(t.exposeProxy=new Proxy($d(Pg(t.exposed)),{get(e,n){if(n in e)return e[n];if(n in xo)return xo[n](t)},has(e,n){return n in e||n in xo}})):t.proxy}function W1(t,e=!0){return ze(t)?t.displayName||t.name:t.name||e&&t.__name}function K1(t){return ze(t)&&"__vccOpts"in t}const Ye=(t,e)=>Lg(t,e,Go);function of(t,e,n){try{ji(-1);const s=arguments.length;return s===2?pt(e)&&!Ie(e)?Ko(e)?ke(t,null,[e]):ke(t,e):ke(t,null,e):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&Ko(n)&&(n=[n]),ke(t,e,n))}finally{ji(1)}}const G1="3.5.26";/** +* @vue/runtime-dom v3.5.26 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let ka;const eu=typeof window<"u"&&window.trustedTypes;if(eu)try{ka=eu.createPolicy("vue",{createHTML:t=>t})}catch{}const rf=ka?t=>ka.createHTML(t):t=>t,Q1="http://www.w3.org/2000/svg",J1="http://www.w3.org/1998/Math/MathML",Kn=typeof document<"u"?document:null,tu=Kn&&Kn.createElement("template"),X1={insert:(t,e,n)=>{e.insertBefore(t,n||null)},remove:t=>{const e=t.parentNode;e&&e.removeChild(t)},createElement:(t,e,n,s)=>{const i=e==="svg"?Kn.createElementNS(Q1,t):e==="mathml"?Kn.createElementNS(J1,t):n?Kn.createElement(t,{is:n}):Kn.createElement(t);return t==="select"&&s&&s.multiple!=null&&i.setAttribute("multiple",s.multiple),i},createText:t=>Kn.createTextNode(t),createComment:t=>Kn.createComment(t),setText:(t,e)=>{t.nodeValue=e},setElementText:(t,e)=>{t.textContent=e},parentNode:t=>t.parentNode,nextSibling:t=>t.nextSibling,querySelector:t=>Kn.querySelector(t),setScopeId(t,e){t.setAttribute(e,"")},insertStaticContent(t,e,n,s,i,l){const r=n?n.previousSibling:e.lastChild;if(i&&(i===l||i.nextSibling))for(;e.insertBefore(i.cloneNode(!0),n),!(i===l||!(i=i.nextSibling)););else{tu.innerHTML=rf(s==="svg"?`${t}`:s==="mathml"?`${t}`:t);const c=tu.content;if(s==="svg"||s==="mathml"){const u=c.firstChild;for(;u.firstChild;)c.appendChild(u.firstChild);c.removeChild(u)}e.insertBefore(c,n)}return[r?r.nextSibling:e.firstChild,n?n.previousSibling:e.lastChild]}},Y1=Symbol("_vtc");function Z1(t,e,n){const s=t[Y1];s&&(e=(e?[e,...s]:[...s]).join(" ")),e==null?t.removeAttribute("class"):n?t.setAttribute("class",e):t.className=e}const nu=Symbol("_vod"),em=Symbol("_vsh"),tm=Symbol(""),nm=/(?:^|;)\s*display\s*:/;function sm(t,e,n){const s=t.style,i=At(n);let l=!1;if(n&&!i){if(e)if(At(e))for(const r of e.split(";")){const c=r.slice(0,r.indexOf(":")).trim();n[c]==null&&Di(s,c,"")}else for(const r in e)n[r]==null&&Di(s,r,"");for(const r in n)r==="display"&&(l=!0),Di(s,r,n[r])}else if(i){if(e!==n){const r=s[tm];r&&(n+=";"+r),s.cssText=n,l=nm.test(n)}}else e&&t.removeAttribute("style");nu in t&&(t[nu]=l?s.display:"",t[em]&&(s.display="none"))}const su=/\s*!important$/;function Di(t,e,n){if(Ie(n))n.forEach(s=>Di(t,e,s));else if(n==null&&(n=""),e.startsWith("--"))t.setProperty(e,n);else{const s=om(t,e);su.test(n)?t.setProperty(gs(s),n.replace(su,""),"important"):t[s]=n}}const ou=["Webkit","Moz","ms"],sa={};function om(t,e){const n=sa[e];if(n)return n;let s=vn(e);if(s!=="filter"&&s in t)return sa[e]=s;s=Zi(s);for(let i=0;ioa||(lm.then(()=>oa=0),oa=Date.now());function um(t,e){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;Hn(dm(s,n.value),e,5,[s])};return n.value=t,n.attached=cm(),n}function dm(t,e){if(Ie(e)){const n=t.stopImmediatePropagation;return t.stopImmediatePropagation=()=>{n.call(t),t._stopped=!0},e.map(s=>i=>!i._stopped&&s&&s(i))}else return e}const uu=t=>t.charCodeAt(0)===111&&t.charCodeAt(1)===110&&t.charCodeAt(2)>96&&t.charCodeAt(2)<123,fm=(t,e,n,s,i,l)=>{const r=i==="svg";e==="class"?Z1(t,s,r):e==="style"?sm(t,n,s):Xi(e)?La(e)||rm(t,e,n,s,l):(e[0]==="."?(e=e.slice(1),!0):e[0]==="^"?(e=e.slice(1),!1):hm(t,e,s,r))?(au(t,e,s),!t.tagName.includes("-")&&(e==="value"||e==="checked"||e==="selected")&&ru(t,e,s,r,l,e!=="value")):t._isVueCE&&(/[A-Z]/.test(e)||!At(s))?au(t,vn(e),s,l,e):(e==="true-value"?t._trueValue=s:e==="false-value"&&(t._falseValue=s),ru(t,e,s,r))};function hm(t,e,n,s){if(s)return!!(e==="innerHTML"||e==="textContent"||e in t&&uu(e)&&ze(n));if(e==="spellcheck"||e==="draggable"||e==="translate"||e==="autocorrect"||e==="sandbox"&&t.tagName==="IFRAME"||e==="form"||e==="list"&&t.tagName==="INPUT"||e==="type"&&t.tagName==="TEXTAREA")return!1;if(e==="width"||e==="height"){const i=t.tagName;if(i==="IMG"||i==="VIDEO"||i==="CANVAS"||i==="SOURCE")return!1}return uu(e)&&At(n)?!1:e in t}const ps=t=>{const e=t.props["onUpdate:modelValue"]||!1;return Ie(e)?n=>Pi(e,n):e};function pm(t){t.target.composing=!0}function du(t){const e=t.target;e.composing&&(e.composing=!1,e.dispatchEvent(new Event("input")))}const mn=Symbol("_assign");function fu(t,e,n){return e&&(t=t.trim()),n&&(t=er(t)),t}const at={created(t,{modifiers:{lazy:e,trim:n,number:s}},i){t[mn]=ps(i);const l=s||i.props&&i.props.type==="number";Jn(t,e?"change":"input",r=>{r.target.composing||t[mn](fu(t.value,n,l))}),(n||l)&&Jn(t,"change",()=>{t.value=fu(t.value,n,l)}),e||(Jn(t,"compositionstart",pm),Jn(t,"compositionend",du),Jn(t,"change",du))},mounted(t,{value:e}){t.value=e??""},beforeUpdate(t,{value:e,oldValue:n,modifiers:{lazy:s,trim:i,number:l}},r){if(t[mn]=ps(r),t.composing)return;const c=(l||t.type==="number")&&!/^0\d/.test(t.value)?er(t.value):t.value,u=e??"";c!==u&&(document.activeElement===t&&t.type!=="range"&&(s&&e===n||i&&t.value.trim()===u)||(t.value=u))}},_n={deep:!0,created(t,e,n){t[mn]=ps(n),Jn(t,"change",()=>{const s=t._modelValue,i=fo(t),l=t.checked,r=t[mn];if(Ie(s)){const c=xa(s,i),u=c!==-1;if(l&&!u)r(s.concat(i));else if(!l&&u){const h=[...s];h.splice(c,1),r(h)}}else if(vo(s)){const c=new Set(s);l?c.add(i):c.delete(i),r(c)}else r(af(t,l))})},mounted:hu,beforeUpdate(t,e,n){t[mn]=ps(n),hu(t,e,n)}};function hu(t,{value:e,oldValue:n},s){t._modelValue=e;let i;if(Ie(e))i=xa(e,s.props.value)>-1;else if(vo(e))i=e.has(s.props.value);else{if(e===n)return;i=xs(e,af(t,!0))}t.checked!==i&&(t.checked=i)}const gm={created(t,{value:e},n){t.checked=xs(e,n.props.value),t[mn]=ps(n),Jn(t,"change",()=>{t[mn](fo(t))})},beforeUpdate(t,{value:e,oldValue:n},s){t[mn]=ps(s),e!==n&&(t.checked=xs(e,s.props.value))}},zo={deep:!0,created(t,{value:e,modifiers:{number:n}},s){const i=vo(e);Jn(t,"change",()=>{const l=Array.prototype.filter.call(t.options,r=>r.selected).map(r=>n?er(fo(r)):fo(r));t[mn](t.multiple?i?new Set(l):l:l[0]),t._assigning=!0,Wa(()=>{t._assigning=!1})}),t[mn]=ps(s)},mounted(t,{value:e}){pu(t,e)},beforeUpdate(t,e,n){t[mn]=ps(n)},updated(t,{value:e}){t._assigning||pu(t,e)}};function pu(t,e){const n=t.multiple,s=Ie(e);if(!(n&&!s&&!vo(e))){for(let i=0,l=t.options.length;iString(h)===String(c)):r.selected=xa(e,c)>-1}else r.selected=e.has(c);else if(xs(fo(r),e)){t.selectedIndex!==i&&(t.selectedIndex=i);return}}!n&&t.selectedIndex!==-1&&(t.selectedIndex=-1)}}function fo(t){return"_value"in t?t._value:t.value}function af(t,e){const n=e?"_trueValue":"_falseValue";return n in t?t[n]:e}const lf={created(t,e,n){Ti(t,e,n,null,"created")},mounted(t,e,n){Ti(t,e,n,null,"mounted")},beforeUpdate(t,e,n,s){Ti(t,e,n,s,"beforeUpdate")},updated(t,e,n,s){Ti(t,e,n,s,"updated")}};function mm(t,e){switch(t){case"SELECT":return zo;case"TEXTAREA":return at;default:switch(e){case"checkbox":return _n;case"radio":return gm;default:return at}}}function Ti(t,e,n,s,i){const r=mm(t.tagName,n.props&&n.props.type)[i];r&&r(t,e,n,s)}const vm=["ctrl","shift","alt","meta"],bm={stop:t=>t.stopPropagation(),prevent:t=>t.preventDefault(),self:t=>t.target!==t.currentTarget,ctrl:t=>!t.ctrlKey,shift:t=>!t.shiftKey,alt:t=>!t.altKey,meta:t=>!t.metaKey,left:t=>"button"in t&&t.button!==0,middle:t=>"button"in t&&t.button!==1,right:t=>"button"in t&&t.button!==2,exact:(t,e)=>vm.some(n=>t[`${n}Key`]&&!e.includes(n))},kt=(t,e)=>{const n=t._withMods||(t._withMods={}),s=e.join(".");return n[s]||(n[s]=(i,...l)=>{for(let r=0;r{const n=t._withKeys||(t._withKeys={}),s=e.join(".");return n[s]||(n[s]=i=>{if(!("key"in i))return;const l=gs(i.key);if(e.some(r=>r===l||ym[r]===l))return t(i)})},wm=Ht({patchProp:fm},X1);let gu;function _m(){return gu||(gu=R1(wm))}const Cm=(...t)=>{const e=_m().createApp(...t),{mount:n}=e;return e.mount=s=>{const i=Sm(s);if(!i)return;const l=e._component;!ze(l)&&!l.render&&!l.template&&(l.template=i.innerHTML),i.nodeType===1&&(i.textContent="");const r=n(i,!1,km(i));return i instanceof Element&&(i.removeAttribute("v-cloak"),i.setAttribute("data-v-app","")),r},e};function km(t){if(t instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&t instanceof MathMLElement)return"mathml"}function Sm(t){return At(t)?document.querySelector(t):t}/*! + * vue-router v4.6.4 + * (c) 2025 Eduardo San Martin Morote + * @license MIT + */const no=typeof document<"u";function cf(t){return typeof t=="object"||"displayName"in t||"props"in t||"__vccOpts"in t}function Em(t){return t.__esModule||t[Symbol.toStringTag]==="Module"||t.default&&cf(t.default)}const nt=Object.assign;function ia(t,e){const n={};for(const s in e){const i=e[s];n[s]=Rn(i)?i.map(t):t(i)}return n}const Ho=()=>{},Rn=Array.isArray;function mu(t,e){const n={};for(const s in t)n[s]=s in e?e[s]:t[s];return n}const uf=/#/g,$m=/&/g,Tm=/\//g,Am=/=/g,Rm=/\?/g,df=/\+/g,Pm=/%5B/g,Im=/%5D/g,ff=/%5E/g,Om=/%60/g,hf=/%7B/g,Mm=/%7C/g,pf=/%7D/g,Dm=/%20/g;function Ya(t){return t==null?"":encodeURI(""+t).replace(Mm,"|").replace(Pm,"[").replace(Im,"]")}function Lm(t){return Ya(t).replace(hf,"{").replace(pf,"}").replace(ff,"^")}function Sa(t){return Ya(t).replace(df,"%2B").replace(Dm,"+").replace(uf,"%23").replace($m,"%26").replace(Om,"`").replace(hf,"{").replace(pf,"}").replace(ff,"^")}function Nm(t){return Sa(t).replace(Am,"%3D")}function Fm(t){return Ya(t).replace(uf,"%23").replace(Rm,"%3F")}function xm(t){return Fm(t).replace(Tm,"%2F")}function Qo(t){if(t==null)return null;try{return decodeURIComponent(""+t)}catch{}return""+t}const Bm=/\/$/,zm=t=>t.replace(Bm,"");function ra(t,e,n="/"){let s,i={},l="",r="";const c=e.indexOf("#");let u=e.indexOf("?");return u=c>=0&&u>c?-1:u,u>=0&&(s=e.slice(0,u),l=e.slice(u,c>0?c:e.length),i=t(l.slice(1))),c>=0&&(s=s||e.slice(0,c),r=e.slice(c,e.length)),s=jm(s??e,n),{fullPath:s+l+r,path:s,query:i,hash:Qo(r)}}function Hm(t,e){const n=e.query?t(e.query):"";return e.path+(n&&"?")+n+(e.hash||"")}function vu(t,e){return!e||!t.toLowerCase().startsWith(e.toLowerCase())?t:t.slice(e.length)||"/"}function Um(t,e,n){const s=e.matched.length-1,i=n.matched.length-1;return s>-1&&s===i&&ho(e.matched[s],n.matched[i])&&gf(e.params,n.params)&&t(e.query)===t(n.query)&&e.hash===n.hash}function ho(t,e){return(t.aliasOf||t)===(e.aliasOf||e)}function gf(t,e){if(Object.keys(t).length!==Object.keys(e).length)return!1;for(var n in t)if(!Vm(t[n],e[n]))return!1;return!0}function Vm(t,e){return Rn(t)?bu(t,e):Rn(e)?bu(e,t):(t==null?void 0:t.valueOf())===(e==null?void 0:e.valueOf())}function bu(t,e){return Rn(e)?t.length===e.length&&t.every((n,s)=>n===e[s]):t.length===1&&t[0]===e}function jm(t,e){if(t.startsWith("/"))return t;if(!t)return e;const n=e.split("/"),s=t.split("/"),i=s[s.length-1];(i===".."||i===".")&&s.push("");let l=n.length-1,r,c;for(r=0;r1&&l--;else break;return n.slice(0,l).join("/")+"/"+s.slice(r).join("/")}const as={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};let Ea=function(t){return t.pop="pop",t.push="push",t}({}),aa=function(t){return t.back="back",t.forward="forward",t.unknown="",t}({});function qm(t){if(!t)if(no){const e=document.querySelector("base");t=e&&e.getAttribute("href")||"/",t=t.replace(/^\w+:\/\/[^\/]+/,"")}else t="/";return t[0]!=="/"&&t[0]!=="#"&&(t="/"+t),zm(t)}const Wm=/^[^#]+#/;function Km(t,e){return t.replace(Wm,"#")+e}function Gm(t,e){const n=document.documentElement.getBoundingClientRect(),s=t.getBoundingClientRect();return{behavior:e.behavior,left:s.left-n.left-(e.left||0),top:s.top-n.top-(e.top||0)}}const lr=()=>({left:window.scrollX,top:window.scrollY});function Qm(t){let e;if("el"in t){const n=t.el,s=typeof n=="string"&&n.startsWith("#"),i=typeof n=="string"?s?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!i)return;e=Gm(i,t)}else e=t;"scrollBehavior"in document.documentElement.style?window.scrollTo(e):window.scrollTo(e.left!=null?e.left:window.scrollX,e.top!=null?e.top:window.scrollY)}function yu(t,e){return(history.state?history.state.position-e:-1)+t}const $a=new Map;function Jm(t,e){$a.set(t,e)}function Xm(t){const e=$a.get(t);return $a.delete(t),e}function Ym(t){return typeof t=="string"||t&&typeof t=="object"}function mf(t){return typeof t=="string"||typeof t=="symbol"}let Ct=function(t){return t[t.MATCHER_NOT_FOUND=1]="MATCHER_NOT_FOUND",t[t.NAVIGATION_GUARD_REDIRECT=2]="NAVIGATION_GUARD_REDIRECT",t[t.NAVIGATION_ABORTED=4]="NAVIGATION_ABORTED",t[t.NAVIGATION_CANCELLED=8]="NAVIGATION_CANCELLED",t[t.NAVIGATION_DUPLICATED=16]="NAVIGATION_DUPLICATED",t}({});const vf=Symbol("");Ct.MATCHER_NOT_FOUND+"",Ct.NAVIGATION_GUARD_REDIRECT+"",Ct.NAVIGATION_ABORTED+"",Ct.NAVIGATION_CANCELLED+"",Ct.NAVIGATION_DUPLICATED+"";function po(t,e){return nt(new Error,{type:t,[vf]:!0},e)}function Wn(t,e){return t instanceof Error&&vf in t&&(e==null||!!(t.type&e))}const Zm=["params","query","hash"];function ev(t){if(typeof t=="string")return t;if(t.path!=null)return t.path;const e={};for(const n of Zm)n in t&&(e[n]=t[n]);return JSON.stringify(e,null,2)}function tv(t){const e={};if(t===""||t==="?")return e;const n=(t[0]==="?"?t.slice(1):t).split("&");for(let s=0;si&&Sa(i)):[s&&Sa(s)]).forEach(i=>{i!==void 0&&(e+=(e.length?"&":"")+n,i!=null&&(e+="="+i))})}return e}function nv(t){const e={};for(const n in t){const s=t[n];s!==void 0&&(e[n]=Rn(s)?s.map(i=>i==null?null:""+i):s==null?s:""+s)}return e}const sv=Symbol(""),_u=Symbol(""),cr=Symbol(""),Za=Symbol(""),Ta=Symbol("");function Po(){let t=[];function e(s){return t.push(s),()=>{const i=t.indexOf(s);i>-1&&t.splice(i,1)}}function n(){t=[]}return{add:e,list:()=>t.slice(),reset:n}}function ds(t,e,n,s,i,l=r=>r()){const r=s&&(s.enterCallbacks[i]=s.enterCallbacks[i]||[]);return()=>new Promise((c,u)=>{const h=C=>{C===!1?u(po(Ct.NAVIGATION_ABORTED,{from:n,to:e})):C instanceof Error?u(C):Ym(C)?u(po(Ct.NAVIGATION_GUARD_REDIRECT,{from:e,to:C})):(r&&s.enterCallbacks[i]===r&&typeof C=="function"&&r.push(C),c())},f=l(()=>t.call(s&&s.instances[i],e,n,h));let g=Promise.resolve(f);t.length<3&&(g=g.then(h)),g.catch(C=>u(C))})}function la(t,e,n,s,i=l=>l()){const l=[];for(const r of t)for(const c in r.components){let u=r.components[c];if(!(e!=="beforeRouteEnter"&&!r.instances[c]))if(cf(u)){const h=(u.__vccOpts||u)[e];h&&l.push(ds(h,n,s,r,c,i))}else{let h=u();l.push(()=>h.then(f=>{if(!f)throw new Error(`Couldn't resolve component "${c}" at "${r.path}"`);const g=Em(f)?f.default:f;r.mods[c]=f,r.components[c]=g;const C=(g.__vccOpts||g)[e];return C&&ds(C,n,s,r,c,i)()}))}}return l}function ov(t,e){const n=[],s=[],i=[],l=Math.max(e.matched.length,t.matched.length);for(let r=0;rho(h,c))?s.push(c):n.push(c));const u=t.matched[r];u&&(e.matched.find(h=>ho(h,u))||i.push(u))}return[n,s,i]}/*! + * vue-router v4.6.4 + * (c) 2025 Eduardo San Martin Morote + * @license MIT + */let iv=()=>location.protocol+"//"+location.host;function bf(t,e){const{pathname:n,search:s,hash:i}=e,l=t.indexOf("#");if(l>-1){let r=i.includes(t.slice(l))?t.slice(l).length:1,c=i.slice(r);return c[0]!=="/"&&(c="/"+c),vu(c,"")}return vu(n,t)+s+i}function rv(t,e,n,s){let i=[],l=[],r=null;const c=({state:C})=>{const _=bf(t,location),y=n.value,P=e.value;let I=0;if(C){if(n.value=_,e.value=C,r&&r===y){r=null;return}I=P?C.position-P.position:0}else s(_);i.forEach(H=>{H(n.value,y,{delta:I,type:Ea.pop,direction:I?I>0?aa.forward:aa.back:aa.unknown})})};function u(){r=n.value}function h(C){i.push(C);const _=()=>{const y=i.indexOf(C);y>-1&&i.splice(y,1)};return l.push(_),_}function f(){if(document.visibilityState==="hidden"){const{history:C}=window;if(!C.state)return;C.replaceState(nt({},C.state,{scroll:lr()}),"")}}function g(){for(const C of l)C();l=[],window.removeEventListener("popstate",c),window.removeEventListener("pagehide",f),document.removeEventListener("visibilitychange",f)}return window.addEventListener("popstate",c),window.addEventListener("pagehide",f),document.addEventListener("visibilitychange",f),{pauseListeners:u,listen:h,destroy:g}}function Cu(t,e,n,s=!1,i=!1){return{back:t,current:e,forward:n,replaced:s,position:window.history.length,scroll:i?lr():null}}function av(t){const{history:e,location:n}=window,s={value:bf(t,n)},i={value:e.state};i.value||l(s.value,{back:null,current:s.value,forward:null,position:e.length-1,replaced:!0,scroll:null},!0);function l(u,h,f){const g=t.indexOf("#"),C=g>-1?(n.host&&document.querySelector("base")?t:t.slice(g))+u:iv()+t+u;try{e[f?"replaceState":"pushState"](h,"",C),i.value=h}catch(_){console.error(_),n[f?"replace":"assign"](C)}}function r(u,h){l(u,nt({},e.state,Cu(i.value.back,u,i.value.forward,!0),h,{position:i.value.position}),!0),s.value=u}function c(u,h){const f=nt({},i.value,e.state,{forward:u,scroll:lr()});l(f.current,f,!0),l(u,nt({},Cu(s.value,u,null),{position:f.position+1},h),!1),s.value=u}return{location:s,state:i,push:c,replace:r}}function lv(t){t=qm(t);const e=av(t),n=rv(t,e.state,e.location,e.replace);function s(l,r=!0){r||n.pauseListeners(),history.go(l)}const i=nt({location:"",base:t,go:s,createHref:Km.bind(null,t)},e,n);return Object.defineProperty(i,"location",{enumerable:!0,get:()=>e.location.value}),Object.defineProperty(i,"state",{enumerable:!0,get:()=>e.state.value}),i}let Is=function(t){return t[t.Static=0]="Static",t[t.Param=1]="Param",t[t.Group=2]="Group",t}({});var Rt=function(t){return t[t.Static=0]="Static",t[t.Param=1]="Param",t[t.ParamRegExp=2]="ParamRegExp",t[t.ParamRegExpEnd=3]="ParamRegExpEnd",t[t.EscapeNext=4]="EscapeNext",t}(Rt||{});const cv={type:Is.Static,value:""},uv=/[a-zA-Z0-9_]/;function dv(t){if(!t)return[[]];if(t==="/")return[[cv]];if(!t.startsWith("/"))throw new Error(`Invalid path "${t}"`);function e(_){throw new Error(`ERR (${n})/"${h}": ${_}`)}let n=Rt.Static,s=n;const i=[];let l;function r(){l&&i.push(l),l=[]}let c=0,u,h="",f="";function g(){h&&(n===Rt.Static?l.push({type:Is.Static,value:h}):n===Rt.Param||n===Rt.ParamRegExp||n===Rt.ParamRegExpEnd?(l.length>1&&(u==="*"||u==="+")&&e(`A repeatable param (${h}) must be alone in its segment. eg: '/:ids+.`),l.push({type:Is.Param,value:h,regexp:f,repeatable:u==="*"||u==="+",optional:u==="*"||u==="?"})):e("Invalid state to consume buffer"),h="")}function C(){h+=u}for(;ce.length?e.length===1&&e[0]===Gt.Static+Gt.Segment?1:-1:0}function yf(t,e){let n=0;const s=t.score,i=e.score;for(;n0&&e[e.length-1]<0}const mv={strict:!1,end:!0,sensitive:!1};function vv(t,e,n){const s=pv(dv(t.path),n),i=nt(s,{record:t,parent:e,children:[],alias:[]});return e&&!i.record.aliasOf==!e.record.aliasOf&&e.children.push(i),i}function bv(t,e){const n=[],s=new Map;e=mu(mv,e);function i(g){return s.get(g)}function l(g,C,_){const y=!_,P=$u(g);P.aliasOf=_&&_.record;const I=mu(e,g),H=[P];if("alias"in g){const F=typeof g.alias=="string"?[g.alias]:g.alias;for(const ne of F)H.push($u(nt({},P,{components:_?_.record.components:P.components,path:ne,aliasOf:_?_.record:P})))}let W,G;for(const F of H){const{path:ne}=F;if(C&&ne[0]!=="/"){const he=C.record.path,ce=he[he.length-1]==="/"?"":"/";F.path=C.record.path+(ne&&ce+ne)}if(W=vv(F,C,I),_?_.alias.push(W):(G=G||W,G!==W&&G.alias.push(W),y&&g.name&&!Tu(W)&&r(g.name)),wf(W)&&u(W),P.children){const he=P.children;for(let ce=0;ce{r(G)}:Ho}function r(g){if(mf(g)){const C=s.get(g);C&&(s.delete(g),n.splice(n.indexOf(C),1),C.children.forEach(r),C.alias.forEach(r))}else{const C=n.indexOf(g);C>-1&&(n.splice(C,1),g.record.name&&s.delete(g.record.name),g.children.forEach(r),g.alias.forEach(r))}}function c(){return n}function u(g){const C=_v(g,n);n.splice(C,0,g),g.record.name&&!Tu(g)&&s.set(g.record.name,g)}function h(g,C){let _,y={},P,I;if("name"in g&&g.name){if(_=s.get(g.name),!_)throw po(Ct.MATCHER_NOT_FOUND,{location:g});I=_.record.name,y=nt(Eu(C.params,_.keys.filter(G=>!G.optional).concat(_.parent?_.parent.keys.filter(G=>G.optional):[]).map(G=>G.name)),g.params&&Eu(g.params,_.keys.map(G=>G.name))),P=_.stringify(y)}else if(g.path!=null)P=g.path,_=n.find(G=>G.re.test(P)),_&&(y=_.parse(P),I=_.record.name);else{if(_=C.name?s.get(C.name):n.find(G=>G.re.test(C.path)),!_)throw po(Ct.MATCHER_NOT_FOUND,{location:g,currentLocation:C});I=_.record.name,y=nt({},C.params,g.params),P=_.stringify(y)}const H=[];let W=_;for(;W;)H.unshift(W.record),W=W.parent;return{name:I,path:P,params:y,matched:H,meta:wv(H)}}t.forEach(g=>l(g));function f(){n.length=0,s.clear()}return{addRoute:l,resolve:h,removeRoute:r,clearRoutes:f,getRoutes:c,getRecordMatcher:i}}function Eu(t,e){const n={};for(const s of e)s in t&&(n[s]=t[s]);return n}function $u(t){const e={path:t.path,redirect:t.redirect,name:t.name,meta:t.meta||{},aliasOf:t.aliasOf,beforeEnter:t.beforeEnter,props:yv(t),children:t.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in t?t.components||null:t.component&&{default:t.component}};return Object.defineProperty(e,"mods",{value:{}}),e}function yv(t){const e={},n=t.props||!1;if("component"in t)e.default=n;else for(const s in t.components)e[s]=typeof n=="object"?n[s]:n;return e}function Tu(t){for(;t;){if(t.record.aliasOf)return!0;t=t.parent}return!1}function wv(t){return t.reduce((e,n)=>nt(e,n.meta),{})}function _v(t,e){let n=0,s=e.length;for(;n!==s;){const l=n+s>>1;yf(t,e[l])<0?s=l:n=l+1}const i=Cv(t);return i&&(s=e.lastIndexOf(i,s-1)),s}function Cv(t){let e=t;for(;e=e.parent;)if(wf(e)&&yf(t,e)===0)return e}function wf({record:t}){return!!(t.name||t.components&&Object.keys(t.components).length||t.redirect)}function Au(t){const e=$n(cr),n=$n(Za),s=Ye(()=>{const u=io(t.to);return e.resolve(u)}),i=Ye(()=>{const{matched:u}=s.value,{length:h}=u,f=u[h-1],g=n.matched;if(!f||!g.length)return-1;const C=g.findIndex(ho.bind(null,f));if(C>-1)return C;const _=Ru(u[h-2]);return h>1&&Ru(f)===_&&g[g.length-1].path!==_?g.findIndex(ho.bind(null,u[h-2])):C}),l=Ye(()=>i.value>-1&&$v(n.params,s.value.params)),r=Ye(()=>i.value>-1&&i.value===n.matched.length-1&&gf(n.params,s.value.params));function c(u={}){if(Ev(u)){const h=e[io(t.replace)?"replace":"push"](io(t.to)).catch(Ho);return t.viewTransition&&typeof document<"u"&&"startViewTransition"in document&&document.startViewTransition(()=>h),h}return Promise.resolve()}return{route:s,href:Ye(()=>s.value.href),isActive:l,isExactActive:r,navigate:c}}function kv(t){return t.length===1?t[0]:t}const Sv=$t({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"},viewTransition:Boolean},useLink:Au,setup(t,{slots:e}){const n=Xt(Au(t)),{options:s}=$n(cr),i=Ye(()=>({[Pu(t.activeClass,s.linkActiveClass,"router-link-active")]:n.isActive,[Pu(t.exactActiveClass,s.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const l=e.default&&kv(e.default(n));return t.custom?l:of("a",{"aria-current":n.isExactActive?t.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:i.value},l)}}}),el=Sv;function Ev(t){if(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)&&!t.defaultPrevented&&!(t.button!==void 0&&t.button!==0)){if(t.currentTarget&&t.currentTarget.getAttribute){const e=t.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(e))return}return t.preventDefault&&t.preventDefault(),!0}}function $v(t,e){for(const n in e){const s=e[n],i=t[n];if(typeof s=="string"){if(s!==i)return!1}else if(!Rn(i)||i.length!==s.length||s.some((l,r)=>l.valueOf()!==i[r].valueOf()))return!1}return!0}function Ru(t){return t?t.aliasOf?t.aliasOf.path:t.path:""}const Pu=(t,e,n)=>t??e??n,Tv=$t({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(t,{attrs:e,slots:n}){const s=$n(Ta),i=Ye(()=>t.route||s.value),l=$n(_u,0),r=Ye(()=>{let h=io(l);const{matched:f}=i.value;let g;for(;(g=f[h])&&!g.components;)h++;return h}),c=Ye(()=>i.value.matched[r.value]);Ii(_u,Ye(()=>r.value+1)),Ii(sv,c),Ii(Ta,i);const u=O();return hs(()=>[u.value,c.value,t.name],([h,f,g],[C,_,y])=>{f&&(f.instances[g]=h,_&&_!==f&&h&&h===C&&(f.leaveGuards.size||(f.leaveGuards=_.leaveGuards),f.updateGuards.size||(f.updateGuards=_.updateGuards))),h&&f&&(!_||!ho(f,_)||!C)&&(f.enterCallbacks[g]||[]).forEach(P=>P(h))},{flush:"post"}),()=>{const h=i.value,f=t.name,g=c.value,C=g&&g.components[f];if(!C)return Iu(n.default,{Component:C,route:h});const _=g.props[f],y=_?_===!0?h.params:typeof _=="function"?_(h):_:null,I=of(C,nt({},y,e,{onVnodeUnmounted:H=>{H.component.isUnmounted&&(g.instances[f]=null)},ref:u}));return Iu(n.default,{Component:I,route:h})||I}}});function Iu(t,e){if(!t)return null;const n=t(e);return n.length===1?n[0]:n}const _f=Tv;function Av(t){const e=bv(t.routes,t),n=t.parseQuery||tv,s=t.stringifyQuery||wu,i=t.history,l=Po(),r=Po(),c=Po(),u=Ig(as);let h=as;no&&t.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const f=ia.bind(null,M=>""+M),g=ia.bind(null,xm),C=ia.bind(null,Qo);function _(M,ee){let S,x;return mf(M)?(S=e.getRecordMatcher(M),x=ee):x=M,e.addRoute(x,S)}function y(M){const ee=e.getRecordMatcher(M);ee&&e.removeRoute(ee)}function P(){return e.getRoutes().map(M=>M.record)}function I(M){return!!e.getRecordMatcher(M)}function H(M,ee){if(ee=nt({},ee||u.value),typeof M=="string"){const R=ra(n,M,ee.path),j=e.resolve({path:R.path},ee),K=i.createHref(R.fullPath);return nt(R,j,{params:C(j.params),hash:Qo(R.hash),redirectedFrom:void 0,href:K})}let S;if(M.path!=null)S=nt({},M,{path:ra(n,M.path,ee.path).path});else{const R=nt({},M.params);for(const j in R)R[j]==null&&delete R[j];S=nt({},M,{params:g(R)}),ee.params=g(ee.params)}const x=e.resolve(S,ee),Z=M.hash||"";x.params=f(C(x.params));const v=Hm(s,nt({},M,{hash:Lm(Z),path:x.path})),E=i.createHref(v);return nt({fullPath:v,hash:Z,query:s===wu?nv(M.query):M.query||{}},x,{redirectedFrom:void 0,href:E})}function W(M){return typeof M=="string"?ra(n,M,u.value.path):nt({},M)}function G(M,ee){if(h!==M)return po(Ct.NAVIGATION_CANCELLED,{from:ee,to:M})}function F(M){return ce(M)}function ne(M){return F(nt(W(M),{replace:!0}))}function he(M,ee){const S=M.matched[M.matched.length-1];if(S&&S.redirect){const{redirect:x}=S;let Z=typeof x=="function"?x(M,ee):x;return typeof Z=="string"&&(Z=Z.includes("?")||Z.includes("#")?Z=W(Z):{path:Z},Z.params={}),nt({query:M.query,hash:M.hash,params:Z.path!=null?{}:M.params},Z)}}function ce(M,ee){const S=h=H(M),x=u.value,Z=M.state,v=M.force,E=M.replace===!0,R=he(S,x);if(R)return ce(nt(W(R),{state:typeof R=="object"?nt({},Z,R.state):Z,force:v,replace:E}),ee||S);const j=S;j.redirectedFrom=ee;let K;return!v&&Um(s,x,S)&&(K=po(Ct.NAVIGATION_DUPLICATED,{to:j,from:x}),z(x,x,!0,!1)),(K?Promise.resolve(K):_e(j,x)).catch(V=>Wn(V)?Wn(V,Ct.NAVIGATION_GUARD_REDIRECT)?V:He(V):Q(V,j,x)).then(V=>{if(V){if(Wn(V,Ct.NAVIGATION_GUARD_REDIRECT))return ce(nt({replace:E},W(V.to),{state:typeof V.to=="object"?nt({},Z,V.to.state):Z,force:v}),ee||j)}else V=Me(j,x,!0,E,Z);return ye(j,x,V),V})}function Ee(M,ee){const S=G(M,ee);return S?Promise.reject(S):Promise.resolve()}function Se(M){const ee=yt.values().next().value;return ee&&typeof ee.runWithContext=="function"?ee.runWithContext(M):M()}function _e(M,ee){let S;const[x,Z,v]=ov(M,ee);S=la(x.reverse(),"beforeRouteLeave",M,ee);for(const R of x)R.leaveGuards.forEach(j=>{S.push(ds(j,M,ee))});const E=Ee.bind(null,M,ee);return S.push(E),Ae(S).then(()=>{S=[];for(const R of l.list())S.push(ds(R,M,ee));return S.push(E),Ae(S)}).then(()=>{S=la(Z,"beforeRouteUpdate",M,ee);for(const R of Z)R.updateGuards.forEach(j=>{S.push(ds(j,M,ee))});return S.push(E),Ae(S)}).then(()=>{S=[];for(const R of v)if(R.beforeEnter)if(Rn(R.beforeEnter))for(const j of R.beforeEnter)S.push(ds(j,M,ee));else S.push(ds(R.beforeEnter,M,ee));return S.push(E),Ae(S)}).then(()=>(M.matched.forEach(R=>R.enterCallbacks={}),S=la(v,"beforeRouteEnter",M,ee,Se),S.push(E),Ae(S))).then(()=>{S=[];for(const R of r.list())S.push(ds(R,M,ee));return S.push(E),Ae(S)}).catch(R=>Wn(R,Ct.NAVIGATION_CANCELLED)?R:Promise.reject(R))}function ye(M,ee,S){c.list().forEach(x=>Se(()=>x(M,ee,S)))}function Me(M,ee,S,x,Z){const v=G(M,ee);if(v)return v;const E=ee===as,R=no?history.state:{};S&&(x||E?i.replace(M.fullPath,nt({scroll:E&&R&&R.scroll},Z)):i.push(M.fullPath,Z)),u.value=M,z(M,ee,S,E),He()}let ve;function te(){ve||(ve=i.listen((M,ee,S)=>{if(!gt.listening)return;const x=H(M),Z=he(x,gt.currentRoute.value);if(Z){ce(nt(Z,{replace:!0,force:!0}),x).catch(Ho);return}h=x;const v=u.value;no&&Jm(yu(v.fullPath,S.delta),lr()),_e(x,v).catch(E=>Wn(E,Ct.NAVIGATION_ABORTED|Ct.NAVIGATION_CANCELLED)?E:Wn(E,Ct.NAVIGATION_GUARD_REDIRECT)?(ce(nt(W(E.to),{force:!0}),x).then(R=>{Wn(R,Ct.NAVIGATION_ABORTED|Ct.NAVIGATION_DUPLICATED)&&!S.delta&&S.type===Ea.pop&&i.go(-1,!1)}).catch(Ho),Promise.reject()):(S.delta&&i.go(-S.delta,!1),Q(E,x,v))).then(E=>{E=E||Me(x,v,!1),E&&(S.delta&&!Wn(E,Ct.NAVIGATION_CANCELLED)?i.go(-S.delta,!1):S.type===Ea.pop&&Wn(E,Ct.NAVIGATION_ABORTED|Ct.NAVIGATION_DUPLICATED)&&i.go(-1,!1)),ye(x,v,E)}).catch(Ho)}))}let Le=Po(),Y=Po(),oe;function Q(M,ee,S){He(M);const x=Y.list();return x.length?x.forEach(Z=>Z(M,ee,S)):console.error(M),Promise.reject(M)}function Re(){return oe&&u.value!==as?Promise.resolve():new Promise((M,ee)=>{Le.add([M,ee])})}function He(M){return oe||(oe=!M,te(),Le.list().forEach(([ee,S])=>M?S(M):ee()),Le.reset()),M}function z(M,ee,S,x){const{scrollBehavior:Z}=t;if(!no||!Z)return Promise.resolve();const v=!S&&Xm(yu(M.fullPath,0))||(x||!S)&&history.state&&history.state.scroll||null;return Wa().then(()=>Z(M,ee,v)).then(E=>E&&Qm(E)).catch(E=>Q(E,M,ee))}const Qe=M=>i.go(M);let Ke;const yt=new Set,gt={currentRoute:u,listening:!0,addRoute:_,removeRoute:y,clearRoutes:e.clearRoutes,hasRoute:I,getRoutes:P,resolve:H,options:t,push:F,replace:ne,go:Qe,back:()=>Qe(-1),forward:()=>Qe(1),beforeEach:l.add,beforeResolve:r.add,afterEach:c.add,onError:Y.add,isReady:Re,install(M){M.component("RouterLink",el),M.component("RouterView",_f),M.config.globalProperties.$router=gt,Object.defineProperty(M.config.globalProperties,"$route",{enumerable:!0,get:()=>io(u)}),no&&!Ke&&u.value===as&&(Ke=!0,F(i.location).catch(x=>{}));const ee={};for(const x in as)Object.defineProperty(ee,x,{get:()=>u.value[x],enumerable:!0});M.provide(cr,gt),M.provide(Za,Sd(ee)),M.provide(Ta,u);const S=M.unmount;yt.add(M),M.unmount=function(){yt.delete(M),yt.size<1&&(h=as,ve&&ve(),ve=null,u.value=as,Ke=!1,oe=!1),S()}}};function Ae(M){return M.reduce((ee,S)=>ee.then(()=>Se(S)),Promise.resolve())}return gt}function ti(){return $n(cr)}function ns(t){return $n(Za)}function Cf(t,e){return function(){return t.apply(e,arguments)}}const{toString:Rv}=Object.prototype,{getPrototypeOf:tl}=Object,{iterator:ur,toStringTag:kf}=Symbol,dr=(t=>e=>{const n=Rv.call(e);return t[n]||(t[n]=n.slice(8,-1).toLowerCase())})(Object.create(null)),Pn=t=>(t=t.toLowerCase(),e=>dr(e)===t),fr=t=>e=>typeof e===t,{isArray:yo}=Array,go=fr("undefined");function ni(t){return t!==null&&!go(t)&&t.constructor!==null&&!go(t.constructor)&&Zt(t.constructor.isBuffer)&&t.constructor.isBuffer(t)}const Sf=Pn("ArrayBuffer");function Pv(t){let e;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?e=ArrayBuffer.isView(t):e=t&&t.buffer&&Sf(t.buffer),e}const Iv=fr("string"),Zt=fr("function"),Ef=fr("number"),si=t=>t!==null&&typeof t=="object",Ov=t=>t===!0||t===!1,Li=t=>{if(dr(t)!=="object")return!1;const e=tl(t);return(e===null||e===Object.prototype||Object.getPrototypeOf(e)===null)&&!(kf in t)&&!(ur in t)},Mv=t=>{if(!si(t)||ni(t))return!1;try{return Object.keys(t).length===0&&Object.getPrototypeOf(t)===Object.prototype}catch{return!1}},Dv=Pn("Date"),Lv=Pn("File"),Nv=Pn("Blob"),Fv=Pn("FileList"),xv=t=>si(t)&&Zt(t.pipe),Bv=t=>{let e;return t&&(typeof FormData=="function"&&t instanceof FormData||Zt(t.append)&&((e=dr(t))==="formdata"||e==="object"&&Zt(t.toString)&&t.toString()==="[object FormData]"))},zv=Pn("URLSearchParams"),[Hv,Uv,Vv,jv]=["ReadableStream","Request","Response","Headers"].map(Pn),qv=t=>t.trim?t.trim():t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function oi(t,e,{allOwnKeys:n=!1}={}){if(t===null||typeof t>"u")return;let s,i;if(typeof t!="object"&&(t=[t]),yo(t))for(s=0,i=t.length;s0;)if(i=n[s],e===i.toLowerCase())return i;return null}const Os=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,Tf=t=>!go(t)&&t!==Os;function Aa(){const{caseless:t,skipUndefined:e}=Tf(this)&&this||{},n={},s=(i,l)=>{const r=t&&$f(n,l)||l;Li(n[r])&&Li(i)?n[r]=Aa(n[r],i):Li(i)?n[r]=Aa({},i):yo(i)?n[r]=i.slice():(!e||!go(i))&&(n[r]=i)};for(let i=0,l=arguments.length;i(oi(e,(i,l)=>{n&&Zt(i)?t[l]=Cf(i,n):t[l]=i},{allOwnKeys:s}),t),Kv=t=>(t.charCodeAt(0)===65279&&(t=t.slice(1)),t),Gv=(t,e,n,s)=>{t.prototype=Object.create(e.prototype,s),t.prototype.constructor=t,Object.defineProperty(t,"super",{value:e.prototype}),n&&Object.assign(t.prototype,n)},Qv=(t,e,n,s)=>{let i,l,r;const c={};if(e=e||{},t==null)return e;do{for(i=Object.getOwnPropertyNames(t),l=i.length;l-- >0;)r=i[l],(!s||s(r,t,e))&&!c[r]&&(e[r]=t[r],c[r]=!0);t=n!==!1&&tl(t)}while(t&&(!n||n(t,e))&&t!==Object.prototype);return e},Jv=(t,e,n)=>{t=String(t),(n===void 0||n>t.length)&&(n=t.length),n-=e.length;const s=t.indexOf(e,n);return s!==-1&&s===n},Xv=t=>{if(!t)return null;if(yo(t))return t;let e=t.length;if(!Ef(e))return null;const n=new Array(e);for(;e-- >0;)n[e]=t[e];return n},Yv=(t=>e=>t&&e instanceof t)(typeof Uint8Array<"u"&&tl(Uint8Array)),Zv=(t,e)=>{const s=(t&&t[ur]).call(t);let i;for(;(i=s.next())&&!i.done;){const l=i.value;e.call(t,l[0],l[1])}},e2=(t,e)=>{let n;const s=[];for(;(n=t.exec(e))!==null;)s.push(n);return s},t2=Pn("HTMLFormElement"),n2=t=>t.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(n,s,i){return s.toUpperCase()+i}),Ou=(({hasOwnProperty:t})=>(e,n)=>t.call(e,n))(Object.prototype),s2=Pn("RegExp"),Af=(t,e)=>{const n=Object.getOwnPropertyDescriptors(t),s={};oi(n,(i,l)=>{let r;(r=e(i,l,t))!==!1&&(s[l]=r||i)}),Object.defineProperties(t,s)},o2=t=>{Af(t,(e,n)=>{if(Zt(t)&&["arguments","caller","callee"].indexOf(n)!==-1)return!1;const s=t[n];if(Zt(s)){if(e.enumerable=!1,"writable"in e){e.writable=!1;return}e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")})}})},i2=(t,e)=>{const n={},s=i=>{i.forEach(l=>{n[l]=!0})};return yo(t)?s(t):s(String(t).split(e)),n},r2=()=>{},a2=(t,e)=>t!=null&&Number.isFinite(t=+t)?t:e;function l2(t){return!!(t&&Zt(t.append)&&t[kf]==="FormData"&&t[ur])}const c2=t=>{const e=new Array(10),n=(s,i)=>{if(si(s)){if(e.indexOf(s)>=0)return;if(ni(s))return s;if(!("toJSON"in s)){e[i]=s;const l=yo(s)?[]:{};return oi(s,(r,c)=>{const u=n(r,i+1);!go(u)&&(l[c]=u)}),e[i]=void 0,l}}return s};return n(t,0)},u2=Pn("AsyncFunction"),d2=t=>t&&(si(t)||Zt(t))&&Zt(t.then)&&Zt(t.catch),Rf=((t,e)=>t?setImmediate:e?((n,s)=>(Os.addEventListener("message",({source:i,data:l})=>{i===Os&&l===n&&s.length&&s.shift()()},!1),i=>{s.push(i),Os.postMessage(n,"*")}))(`axios@${Math.random()}`,[]):n=>setTimeout(n))(typeof setImmediate=="function",Zt(Os.postMessage)),f2=typeof queueMicrotask<"u"?queueMicrotask.bind(Os):typeof process<"u"&&process.nextTick||Rf,h2=t=>t!=null&&Zt(t[ur]),D={isArray:yo,isArrayBuffer:Sf,isBuffer:ni,isFormData:Bv,isArrayBufferView:Pv,isString:Iv,isNumber:Ef,isBoolean:Ov,isObject:si,isPlainObject:Li,isEmptyObject:Mv,isReadableStream:Hv,isRequest:Uv,isResponse:Vv,isHeaders:jv,isUndefined:go,isDate:Dv,isFile:Lv,isBlob:Nv,isRegExp:s2,isFunction:Zt,isStream:xv,isURLSearchParams:zv,isTypedArray:Yv,isFileList:Fv,forEach:oi,merge:Aa,extend:Wv,trim:qv,stripBOM:Kv,inherits:Gv,toFlatObject:Qv,kindOf:dr,kindOfTest:Pn,endsWith:Jv,toArray:Xv,forEachEntry:Zv,matchAll:e2,isHTMLForm:t2,hasOwnProperty:Ou,hasOwnProp:Ou,reduceDescriptors:Af,freezeMethods:o2,toObjectSet:i2,toCamelCase:n2,noop:r2,toFiniteNumber:a2,findKey:$f,global:Os,isContextDefined:Tf,isSpecCompliantForm:l2,toJSONObject:c2,isAsyncFn:u2,isThenable:d2,setImmediate:Rf,asap:f2,isIterable:h2};function Ue(t,e,n,s,i){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack,this.message=t,this.name="AxiosError",e&&(this.code=e),n&&(this.config=n),s&&(this.request=s),i&&(this.response=i,this.status=i.status?i.status:null)}D.inherits(Ue,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:D.toJSONObject(this.config),code:this.code,status:this.status}}});const Pf=Ue.prototype,If={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach(t=>{If[t]={value:t}});Object.defineProperties(Ue,If);Object.defineProperty(Pf,"isAxiosError",{value:!0});Ue.from=(t,e,n,s,i,l)=>{const r=Object.create(Pf);D.toFlatObject(t,r,function(f){return f!==Error.prototype},h=>h!=="isAxiosError");const c=t&&t.message?t.message:"Error",u=e==null&&t?t.code:e;return Ue.call(r,c,u,n,s,i),t&&r.cause==null&&Object.defineProperty(r,"cause",{value:t,configurable:!0}),r.name=t&&t.name||"Error",l&&Object.assign(r,l),r};const p2=null;function Ra(t){return D.isPlainObject(t)||D.isArray(t)}function Of(t){return D.endsWith(t,"[]")?t.slice(0,-2):t}function Mu(t,e,n){return t?t.concat(e).map(function(i,l){return i=Of(i),!n&&l?"["+i+"]":i}).join(n?".":""):e}function g2(t){return D.isArray(t)&&!t.some(Ra)}const m2=D.toFlatObject(D,{},null,function(e){return/^is[A-Z]/.test(e)});function hr(t,e,n){if(!D.isObject(t))throw new TypeError("target must be an object");e=e||new FormData,n=D.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,function(P,I){return!D.isUndefined(I[P])});const s=n.metaTokens,i=n.visitor||f,l=n.dots,r=n.indexes,u=(n.Blob||typeof Blob<"u"&&Blob)&&D.isSpecCompliantForm(e);if(!D.isFunction(i))throw new TypeError("visitor must be a function");function h(y){if(y===null)return"";if(D.isDate(y))return y.toISOString();if(D.isBoolean(y))return y.toString();if(!u&&D.isBlob(y))throw new Ue("Blob is not supported. Use a Buffer instead.");return D.isArrayBuffer(y)||D.isTypedArray(y)?u&&typeof Blob=="function"?new Blob([y]):Buffer.from(y):y}function f(y,P,I){let H=y;if(y&&!I&&typeof y=="object"){if(D.endsWith(P,"{}"))P=s?P:P.slice(0,-2),y=JSON.stringify(y);else if(D.isArray(y)&&g2(y)||(D.isFileList(y)||D.endsWith(P,"[]"))&&(H=D.toArray(y)))return P=Of(P),H.forEach(function(G,F){!(D.isUndefined(G)||G===null)&&e.append(r===!0?Mu([P],F,l):r===null?P:P+"[]",h(G))}),!1}return Ra(y)?!0:(e.append(Mu(I,P,l),h(y)),!1)}const g=[],C=Object.assign(m2,{defaultVisitor:f,convertValue:h,isVisitable:Ra});function _(y,P){if(!D.isUndefined(y)){if(g.indexOf(y)!==-1)throw Error("Circular reference detected in "+P.join("."));g.push(y),D.forEach(y,function(H,W){(!(D.isUndefined(H)||H===null)&&i.call(e,H,D.isString(W)?W.trim():W,P,C))===!0&&_(H,P?P.concat(W):[W])}),g.pop()}}if(!D.isObject(t))throw new TypeError("data must be an object");return _(t),e}function Du(t){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(t).replace(/[!'()~]|%20|%00/g,function(s){return e[s]})}function nl(t,e){this._pairs=[],t&&hr(t,this,e)}const Mf=nl.prototype;Mf.append=function(e,n){this._pairs.push([e,n])};Mf.toString=function(e){const n=e?function(s){return e.call(this,s,Du)}:Du;return this._pairs.map(function(i){return n(i[0])+"="+n(i[1])},"").join("&")};function v2(t){return encodeURIComponent(t).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}function Df(t,e,n){if(!e)return t;const s=n&&n.encode||v2;D.isFunction(n)&&(n={serialize:n});const i=n&&n.serialize;let l;if(i?l=i(e,n):l=D.isURLSearchParams(e)?e.toString():new nl(e,n).toString(s),l){const r=t.indexOf("#");r!==-1&&(t=t.slice(0,r)),t+=(t.indexOf("?")===-1?"?":"&")+l}return t}class Lu{constructor(){this.handlers=[]}use(e,n,s){return this.handlers.push({fulfilled:e,rejected:n,synchronous:s?s.synchronous:!1,runWhen:s?s.runWhen:null}),this.handlers.length-1}eject(e){this.handlers[e]&&(this.handlers[e]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(e){D.forEach(this.handlers,function(s){s!==null&&e(s)})}}const Lf={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},b2=typeof URLSearchParams<"u"?URLSearchParams:nl,y2=typeof FormData<"u"?FormData:null,w2=typeof Blob<"u"?Blob:null,_2={isBrowser:!0,classes:{URLSearchParams:b2,FormData:y2,Blob:w2},protocols:["http","https","file","blob","url","data"]},sl=typeof window<"u"&&typeof document<"u",Pa=typeof navigator=="object"&&navigator||void 0,C2=sl&&(!Pa||["ReactNative","NativeScript","NS"].indexOf(Pa.product)<0),k2=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope&&typeof self.importScripts=="function",S2=sl&&window.location.href||"http://localhost",E2=Object.freeze(Object.defineProperty({__proto__:null,hasBrowserEnv:sl,hasStandardBrowserEnv:C2,hasStandardBrowserWebWorkerEnv:k2,navigator:Pa,origin:S2},Symbol.toStringTag,{value:"Module"})),xt={...E2,..._2};function $2(t,e){return hr(t,new xt.classes.URLSearchParams,{visitor:function(n,s,i,l){return xt.isNode&&D.isBuffer(n)?(this.append(s,n.toString("base64")),!1):l.defaultVisitor.apply(this,arguments)},...e})}function T2(t){return D.matchAll(/\w+|\[(\w*)]/g,t).map(e=>e[0]==="[]"?"":e[1]||e[0])}function A2(t){const e={},n=Object.keys(t);let s;const i=n.length;let l;for(s=0;s=n.length;return r=!r&&D.isArray(i)?i.length:r,u?(D.hasOwnProp(i,r)?i[r]=[i[r],s]:i[r]=s,!c):((!i[r]||!D.isObject(i[r]))&&(i[r]=[]),e(n,s,i[r],l)&&D.isArray(i[r])&&(i[r]=A2(i[r])),!c)}if(D.isFormData(t)&&D.isFunction(t.entries)){const n={};return D.forEachEntry(t,(s,i)=>{e(T2(s),i,n,0)}),n}return null}function R2(t,e,n){if(D.isString(t))try{return(e||JSON.parse)(t),D.trim(t)}catch(s){if(s.name!=="SyntaxError")throw s}return(n||JSON.stringify)(t)}const ii={transitional:Lf,adapter:["xhr","http","fetch"],transformRequest:[function(e,n){const s=n.getContentType()||"",i=s.indexOf("application/json")>-1,l=D.isObject(e);if(l&&D.isHTMLForm(e)&&(e=new FormData(e)),D.isFormData(e))return i?JSON.stringify(Nf(e)):e;if(D.isArrayBuffer(e)||D.isBuffer(e)||D.isStream(e)||D.isFile(e)||D.isBlob(e)||D.isReadableStream(e))return e;if(D.isArrayBufferView(e))return e.buffer;if(D.isURLSearchParams(e))return n.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();let c;if(l){if(s.indexOf("application/x-www-form-urlencoded")>-1)return $2(e,this.formSerializer).toString();if((c=D.isFileList(e))||s.indexOf("multipart/form-data")>-1){const u=this.env&&this.env.FormData;return hr(c?{"files[]":e}:e,u&&new u,this.formSerializer)}}return l||i?(n.setContentType("application/json",!1),R2(e)):e}],transformResponse:[function(e){const n=this.transitional||ii.transitional,s=n&&n.forcedJSONParsing,i=this.responseType==="json";if(D.isResponse(e)||D.isReadableStream(e))return e;if(e&&D.isString(e)&&(s&&!this.responseType||i)){const r=!(n&&n.silentJSONParsing)&&i;try{return JSON.parse(e,this.parseReviver)}catch(c){if(r)throw c.name==="SyntaxError"?Ue.from(c,Ue.ERR_BAD_RESPONSE,this,null,this.response):c}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:xt.classes.FormData,Blob:xt.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};D.forEach(["delete","get","head","post","put","patch"],t=>{ii.headers[t]={}});const P2=D.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),I2=t=>{const e={};let n,s,i;return t&&t.split(` +`).forEach(function(r){i=r.indexOf(":"),n=r.substring(0,i).trim().toLowerCase(),s=r.substring(i+1).trim(),!(!n||e[n]&&P2[n])&&(n==="set-cookie"?e[n]?e[n].push(s):e[n]=[s]:e[n]=e[n]?e[n]+", "+s:s)}),e},Nu=Symbol("internals");function Io(t){return t&&String(t).trim().toLowerCase()}function Ni(t){return t===!1||t==null?t:D.isArray(t)?t.map(Ni):String(t)}function O2(t){const e=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let s;for(;s=n.exec(t);)e[s[1]]=s[2];return e}const M2=t=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(t.trim());function ca(t,e,n,s,i){if(D.isFunction(s))return s.call(this,e,n);if(i&&(e=n),!!D.isString(e)){if(D.isString(s))return e.indexOf(s)!==-1;if(D.isRegExp(s))return s.test(e)}}function D2(t){return t.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(e,n,s)=>n.toUpperCase()+s)}function L2(t,e){const n=D.toCamelCase(" "+e);["get","set","has"].forEach(s=>{Object.defineProperty(t,s+n,{value:function(i,l,r){return this[s].call(this,e,i,l,r)},configurable:!0})})}let en=class{constructor(e){e&&this.set(e)}set(e,n,s){const i=this;function l(c,u,h){const f=Io(u);if(!f)throw new Error("header name must be a non-empty string");const g=D.findKey(i,f);(!g||i[g]===void 0||h===!0||h===void 0&&i[g]!==!1)&&(i[g||u]=Ni(c))}const r=(c,u)=>D.forEach(c,(h,f)=>l(h,f,u));if(D.isPlainObject(e)||e instanceof this.constructor)r(e,n);else if(D.isString(e)&&(e=e.trim())&&!M2(e))r(I2(e),n);else if(D.isObject(e)&&D.isIterable(e)){let c={},u,h;for(const f of e){if(!D.isArray(f))throw TypeError("Object iterator must return a key-value pair");c[h=f[0]]=(u=c[h])?D.isArray(u)?[...u,f[1]]:[u,f[1]]:f[1]}r(c,n)}else e!=null&&l(n,e,s);return this}get(e,n){if(e=Io(e),e){const s=D.findKey(this,e);if(s){const i=this[s];if(!n)return i;if(n===!0)return O2(i);if(D.isFunction(n))return n.call(this,i,s);if(D.isRegExp(n))return n.exec(i);throw new TypeError("parser must be boolean|regexp|function")}}}has(e,n){if(e=Io(e),e){const s=D.findKey(this,e);return!!(s&&this[s]!==void 0&&(!n||ca(this,this[s],s,n)))}return!1}delete(e,n){const s=this;let i=!1;function l(r){if(r=Io(r),r){const c=D.findKey(s,r);c&&(!n||ca(s,s[c],c,n))&&(delete s[c],i=!0)}}return D.isArray(e)?e.forEach(l):l(e),i}clear(e){const n=Object.keys(this);let s=n.length,i=!1;for(;s--;){const l=n[s];(!e||ca(this,this[l],l,e,!0))&&(delete this[l],i=!0)}return i}normalize(e){const n=this,s={};return D.forEach(this,(i,l)=>{const r=D.findKey(s,l);if(r){n[r]=Ni(i),delete n[l];return}const c=e?D2(l):String(l).trim();c!==l&&delete n[l],n[c]=Ni(i),s[c]=!0}),this}concat(...e){return this.constructor.concat(this,...e)}toJSON(e){const n=Object.create(null);return D.forEach(this,(s,i)=>{s!=null&&s!==!1&&(n[i]=e&&D.isArray(s)?s.join(", "):s)}),n}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([e,n])=>e+": "+n).join(` +`)}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(e){return e instanceof this?e:new this(e)}static concat(e,...n){const s=new this(e);return n.forEach(i=>s.set(i)),s}static accessor(e){const s=(this[Nu]=this[Nu]={accessors:{}}).accessors,i=this.prototype;function l(r){const c=Io(r);s[c]||(L2(i,r),s[c]=!0)}return D.isArray(e)?e.forEach(l):l(e),this}};en.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]);D.reduceDescriptors(en.prototype,({value:t},e)=>{let n=e[0].toUpperCase()+e.slice(1);return{get:()=>t,set(s){this[n]=s}}});D.freezeMethods(en);function ua(t,e){const n=this||ii,s=e||n,i=en.from(s.headers);let l=s.data;return D.forEach(t,function(c){l=c.call(n,l,i.normalize(),e?e.status:void 0)}),i.normalize(),l}function Ff(t){return!!(t&&t.__CANCEL__)}function wo(t,e,n){Ue.call(this,t??"canceled",Ue.ERR_CANCELED,e,n),this.name="CanceledError"}D.inherits(wo,Ue,{__CANCEL__:!0});function xf(t,e,n){const s=n.config.validateStatus;!n.status||!s||s(n.status)?t(n):e(new Ue("Request failed with status code "+n.status,[Ue.ERR_BAD_REQUEST,Ue.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n))}function N2(t){const e=/^([-+\w]{1,25})(:?\/\/|:)/.exec(t);return e&&e[1]||""}function F2(t,e){t=t||10;const n=new Array(t),s=new Array(t);let i=0,l=0,r;return e=e!==void 0?e:1e3,function(u){const h=Date.now(),f=s[l];r||(r=h),n[i]=u,s[i]=h;let g=l,C=0;for(;g!==i;)C+=n[g++],g=g%t;if(i=(i+1)%t,i===l&&(l=(l+1)%t),h-r{n=f,i=null,l&&(clearTimeout(l),l=null),t(...h)};return[(...h)=>{const f=Date.now(),g=f-n;g>=s?r(h,f):(i=h,l||(l=setTimeout(()=>{l=null,r(i)},s-g)))},()=>i&&r(i)]}const Ki=(t,e,n=3)=>{let s=0;const i=F2(50,250);return x2(l=>{const r=l.loaded,c=l.lengthComputable?l.total:void 0,u=r-s,h=i(u),f=r<=c;s=r;const g={loaded:r,total:c,progress:c?r/c:void 0,bytes:u,rate:h||void 0,estimated:h&&c&&f?(c-r)/h:void 0,event:l,lengthComputable:c!=null,[e?"download":"upload"]:!0};t(g)},n)},Fu=(t,e)=>{const n=t!=null;return[s=>e[0]({lengthComputable:n,total:t,loaded:s}),e[1]]},xu=t=>(...e)=>D.asap(()=>t(...e)),B2=xt.hasStandardBrowserEnv?((t,e)=>n=>(n=new URL(n,xt.origin),t.protocol===n.protocol&&t.host===n.host&&(e||t.port===n.port)))(new URL(xt.origin),xt.navigator&&/(msie|trident)/i.test(xt.navigator.userAgent)):()=>!0,z2=xt.hasStandardBrowserEnv?{write(t,e,n,s,i,l,r){if(typeof document>"u")return;const c=[`${t}=${encodeURIComponent(e)}`];D.isNumber(n)&&c.push(`expires=${new Date(n).toUTCString()}`),D.isString(s)&&c.push(`path=${s}`),D.isString(i)&&c.push(`domain=${i}`),l===!0&&c.push("secure"),D.isString(r)&&c.push(`SameSite=${r}`),document.cookie=c.join("; ")},read(t){if(typeof document>"u")return null;const e=document.cookie.match(new RegExp("(?:^|; )"+t+"=([^;]*)"));return e?decodeURIComponent(e[1]):null},remove(t){this.write(t,"",Date.now()-864e5,"/")}}:{write(){},read(){return null},remove(){}};function H2(t){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(t)}function U2(t,e){return e?t.replace(/\/?\/$/,"")+"/"+e.replace(/^\/+/,""):t}function Bf(t,e,n){let s=!H2(e);return t&&(s||n==!1)?U2(t,e):e}const Bu=t=>t instanceof en?{...t}:t;function Bs(t,e){e=e||{};const n={};function s(h,f,g,C){return D.isPlainObject(h)&&D.isPlainObject(f)?D.merge.call({caseless:C},h,f):D.isPlainObject(f)?D.merge({},f):D.isArray(f)?f.slice():f}function i(h,f,g,C){if(D.isUndefined(f)){if(!D.isUndefined(h))return s(void 0,h,g,C)}else return s(h,f,g,C)}function l(h,f){if(!D.isUndefined(f))return s(void 0,f)}function r(h,f){if(D.isUndefined(f)){if(!D.isUndefined(h))return s(void 0,h)}else return s(void 0,f)}function c(h,f,g){if(g in e)return s(h,f);if(g in t)return s(void 0,h)}const u={url:l,method:l,data:l,baseURL:r,transformRequest:r,transformResponse:r,paramsSerializer:r,timeout:r,timeoutMessage:r,withCredentials:r,withXSRFToken:r,adapter:r,responseType:r,xsrfCookieName:r,xsrfHeaderName:r,onUploadProgress:r,onDownloadProgress:r,decompress:r,maxContentLength:r,maxBodyLength:r,beforeRedirect:r,transport:r,httpAgent:r,httpsAgent:r,cancelToken:r,socketPath:r,responseEncoding:r,validateStatus:c,headers:(h,f,g)=>i(Bu(h),Bu(f),g,!0)};return D.forEach(Object.keys({...t,...e}),function(f){const g=u[f]||i,C=g(t[f],e[f],f);D.isUndefined(C)&&g!==c||(n[f]=C)}),n}const zf=t=>{const e=Bs({},t);let{data:n,withXSRFToken:s,xsrfHeaderName:i,xsrfCookieName:l,headers:r,auth:c}=e;if(e.headers=r=en.from(r),e.url=Df(Bf(e.baseURL,e.url,e.allowAbsoluteUrls),t.params,t.paramsSerializer),c&&r.set("Authorization","Basic "+btoa((c.username||"")+":"+(c.password?unescape(encodeURIComponent(c.password)):""))),D.isFormData(n)){if(xt.hasStandardBrowserEnv||xt.hasStandardBrowserWebWorkerEnv)r.setContentType(void 0);else if(D.isFunction(n.getHeaders)){const u=n.getHeaders(),h=["content-type","content-length"];Object.entries(u).forEach(([f,g])=>{h.includes(f.toLowerCase())&&r.set(f,g)})}}if(xt.hasStandardBrowserEnv&&(s&&D.isFunction(s)&&(s=s(e)),s||s!==!1&&B2(e.url))){const u=i&&l&&z2.read(l);u&&r.set(i,u)}return e},V2=typeof XMLHttpRequest<"u",j2=V2&&function(t){return new Promise(function(n,s){const i=zf(t);let l=i.data;const r=en.from(i.headers).normalize();let{responseType:c,onUploadProgress:u,onDownloadProgress:h}=i,f,g,C,_,y;function P(){_&&_(),y&&y(),i.cancelToken&&i.cancelToken.unsubscribe(f),i.signal&&i.signal.removeEventListener("abort",f)}let I=new XMLHttpRequest;I.open(i.method.toUpperCase(),i.url,!0),I.timeout=i.timeout;function H(){if(!I)return;const G=en.from("getAllResponseHeaders"in I&&I.getAllResponseHeaders()),ne={data:!c||c==="text"||c==="json"?I.responseText:I.response,status:I.status,statusText:I.statusText,headers:G,config:t,request:I};xf(function(ce){n(ce),P()},function(ce){s(ce),P()},ne),I=null}"onloadend"in I?I.onloadend=H:I.onreadystatechange=function(){!I||I.readyState!==4||I.status===0&&!(I.responseURL&&I.responseURL.indexOf("file:")===0)||setTimeout(H)},I.onabort=function(){I&&(s(new Ue("Request aborted",Ue.ECONNABORTED,t,I)),I=null)},I.onerror=function(F){const ne=F&&F.message?F.message:"Network Error",he=new Ue(ne,Ue.ERR_NETWORK,t,I);he.event=F||null,s(he),I=null},I.ontimeout=function(){let F=i.timeout?"timeout of "+i.timeout+"ms exceeded":"timeout exceeded";const ne=i.transitional||Lf;i.timeoutErrorMessage&&(F=i.timeoutErrorMessage),s(new Ue(F,ne.clarifyTimeoutError?Ue.ETIMEDOUT:Ue.ECONNABORTED,t,I)),I=null},l===void 0&&r.setContentType(null),"setRequestHeader"in I&&D.forEach(r.toJSON(),function(F,ne){I.setRequestHeader(ne,F)}),D.isUndefined(i.withCredentials)||(I.withCredentials=!!i.withCredentials),c&&c!=="json"&&(I.responseType=i.responseType),h&&([C,y]=Ki(h,!0),I.addEventListener("progress",C)),u&&I.upload&&([g,_]=Ki(u),I.upload.addEventListener("progress",g),I.upload.addEventListener("loadend",_)),(i.cancelToken||i.signal)&&(f=G=>{I&&(s(!G||G.type?new wo(null,t,I):G),I.abort(),I=null)},i.cancelToken&&i.cancelToken.subscribe(f),i.signal&&(i.signal.aborted?f():i.signal.addEventListener("abort",f)));const W=N2(i.url);if(W&&xt.protocols.indexOf(W)===-1){s(new Ue("Unsupported protocol "+W+":",Ue.ERR_BAD_REQUEST,t));return}I.send(l||null)})},q2=(t,e)=>{const{length:n}=t=t?t.filter(Boolean):[];if(e||n){let s=new AbortController,i;const l=function(h){if(!i){i=!0,c();const f=h instanceof Error?h:this.reason;s.abort(f instanceof Ue?f:new wo(f instanceof Error?f.message:f))}};let r=e&&setTimeout(()=>{r=null,l(new Ue(`timeout ${e} of ms exceeded`,Ue.ETIMEDOUT))},e);const c=()=>{t&&(r&&clearTimeout(r),r=null,t.forEach(h=>{h.unsubscribe?h.unsubscribe(l):h.removeEventListener("abort",l)}),t=null)};t.forEach(h=>h.addEventListener("abort",l));const{signal:u}=s;return u.unsubscribe=()=>D.asap(c),u}},W2=function*(t,e){let n=t.byteLength;if(n{const i=K2(t,e);let l=0,r,c=u=>{r||(r=!0,s&&s(u))};return new ReadableStream({async pull(u){try{const{done:h,value:f}=await i.next();if(h){c(),u.close();return}let g=f.byteLength;if(n){let C=l+=g;n(C)}u.enqueue(new Uint8Array(f))}catch(h){throw c(h),h}},cancel(u){return c(u),i.return()}},{highWaterMark:2})},Hu=64*1024,{isFunction:Ai}=D,Q2=(({Request:t,Response:e})=>({Request:t,Response:e}))(D.global),{ReadableStream:Uu,TextEncoder:Vu}=D.global,ju=(t,...e)=>{try{return!!t(...e)}catch{return!1}},J2=t=>{t=D.merge.call({skipUndefined:!0},Q2,t);const{fetch:e,Request:n,Response:s}=t,i=e?Ai(e):typeof fetch=="function",l=Ai(n),r=Ai(s);if(!i)return!1;const c=i&&Ai(Uu),u=i&&(typeof Vu=="function"?(y=>P=>y.encode(P))(new Vu):async y=>new Uint8Array(await new n(y).arrayBuffer())),h=l&&c&&ju(()=>{let y=!1;const P=new n(xt.origin,{body:new Uu,method:"POST",get duplex(){return y=!0,"half"}}).headers.has("Content-Type");return y&&!P}),f=r&&c&&ju(()=>D.isReadableStream(new s("").body)),g={stream:f&&(y=>y.body)};i&&["text","arrayBuffer","blob","formData","stream"].forEach(y=>{!g[y]&&(g[y]=(P,I)=>{let H=P&&P[y];if(H)return H.call(P);throw new Ue(`Response type '${y}' is not supported`,Ue.ERR_NOT_SUPPORT,I)})});const C=async y=>{if(y==null)return 0;if(D.isBlob(y))return y.size;if(D.isSpecCompliantForm(y))return(await new n(xt.origin,{method:"POST",body:y}).arrayBuffer()).byteLength;if(D.isArrayBufferView(y)||D.isArrayBuffer(y))return y.byteLength;if(D.isURLSearchParams(y)&&(y=y+""),D.isString(y))return(await u(y)).byteLength},_=async(y,P)=>{const I=D.toFiniteNumber(y.getContentLength());return I??C(P)};return async y=>{let{url:P,method:I,data:H,signal:W,cancelToken:G,timeout:F,onDownloadProgress:ne,onUploadProgress:he,responseType:ce,headers:Ee,withCredentials:Se="same-origin",fetchOptions:_e}=zf(y),ye=e||fetch;ce=ce?(ce+"").toLowerCase():"text";let Me=q2([W,G&&G.toAbortSignal()],F),ve=null;const te=Me&&Me.unsubscribe&&(()=>{Me.unsubscribe()});let Le;try{if(he&&h&&I!=="get"&&I!=="head"&&(Le=await _(Ee,H))!==0){let z=new n(P,{method:"POST",body:H,duplex:"half"}),Qe;if(D.isFormData(H)&&(Qe=z.headers.get("content-type"))&&Ee.setContentType(Qe),z.body){const[Ke,yt]=Fu(Le,Ki(xu(he)));H=zu(z.body,Hu,Ke,yt)}}D.isString(Se)||(Se=Se?"include":"omit");const Y=l&&"credentials"in n.prototype,oe={..._e,signal:Me,method:I.toUpperCase(),headers:Ee.normalize().toJSON(),body:H,duplex:"half",credentials:Y?Se:void 0};ve=l&&new n(P,oe);let Q=await(l?ye(ve,_e):ye(P,oe));const Re=f&&(ce==="stream"||ce==="response");if(f&&(ne||Re&&te)){const z={};["status","statusText","headers"].forEach(gt=>{z[gt]=Q[gt]});const Qe=D.toFiniteNumber(Q.headers.get("content-length")),[Ke,yt]=ne&&Fu(Qe,Ki(xu(ne),!0))||[];Q=new s(zu(Q.body,Hu,Ke,()=>{yt&&yt(),te&&te()}),z)}ce=ce||"text";let He=await g[D.findKey(g,ce)||"text"](Q,y);return!Re&&te&&te(),await new Promise((z,Qe)=>{xf(z,Qe,{data:He,headers:en.from(Q.headers),status:Q.status,statusText:Q.statusText,config:y,request:ve})})}catch(Y){throw te&&te(),Y&&Y.name==="TypeError"&&/Load failed|fetch/i.test(Y.message)?Object.assign(new Ue("Network Error",Ue.ERR_NETWORK,y,ve),{cause:Y.cause||Y}):Ue.from(Y,Y&&Y.code,y,ve)}}},X2=new Map,Hf=t=>{let e=t&&t.env||{};const{fetch:n,Request:s,Response:i}=e,l=[s,i,n];let r=l.length,c=r,u,h,f=X2;for(;c--;)u=l[c],h=f.get(u),h===void 0&&f.set(u,h=c?new Map:J2(e)),f=h;return h};Hf();const ol={http:p2,xhr:j2,fetch:{get:Hf}};D.forEach(ol,(t,e)=>{if(t){try{Object.defineProperty(t,"name",{value:e})}catch{}Object.defineProperty(t,"adapterName",{value:e})}});const qu=t=>`- ${t}`,Y2=t=>D.isFunction(t)||t===null||t===!1;function Z2(t,e){t=D.isArray(t)?t:[t];const{length:n}=t;let s,i;const l={};for(let r=0;r`adapter ${u} `+(h===!1?"is not supported by the environment":"is not available in the build"));let c=n?r.length>1?`since : +`+r.map(qu).join(` +`):" "+qu(r[0]):"as no adapter specified";throw new Ue("There is no suitable adapter to dispatch the request "+c,"ERR_NOT_SUPPORT")}return i}const Uf={getAdapter:Z2,adapters:ol};function da(t){if(t.cancelToken&&t.cancelToken.throwIfRequested(),t.signal&&t.signal.aborted)throw new wo(null,t)}function Wu(t){return da(t),t.headers=en.from(t.headers),t.data=ua.call(t,t.transformRequest),["post","put","patch"].indexOf(t.method)!==-1&&t.headers.setContentType("application/x-www-form-urlencoded",!1),Uf.getAdapter(t.adapter||ii.adapter,t)(t).then(function(s){return da(t),s.data=ua.call(t,t.transformResponse,s),s.headers=en.from(s.headers),s},function(s){return Ff(s)||(da(t),s&&s.response&&(s.response.data=ua.call(t,t.transformResponse,s.response),s.response.headers=en.from(s.response.headers))),Promise.reject(s)})}const Vf="1.13.2",pr={};["object","boolean","number","function","string","symbol"].forEach((t,e)=>{pr[t]=function(s){return typeof s===t||"a"+(e<1?"n ":" ")+t}});const Ku={};pr.transitional=function(e,n,s){function i(l,r){return"[Axios v"+Vf+"] Transitional option '"+l+"'"+r+(s?". "+s:"")}return(l,r,c)=>{if(e===!1)throw new Ue(i(r," has been removed"+(n?" in "+n:"")),Ue.ERR_DEPRECATED);return n&&!Ku[r]&&(Ku[r]=!0,console.warn(i(r," has been deprecated since v"+n+" and will be removed in the near future"))),e?e(l,r,c):!0}};pr.spelling=function(e){return(n,s)=>(console.warn(`${s} is likely a misspelling of ${e}`),!0)};function eb(t,e,n){if(typeof t!="object")throw new Ue("options must be an object",Ue.ERR_BAD_OPTION_VALUE);const s=Object.keys(t);let i=s.length;for(;i-- >0;){const l=s[i],r=e[l];if(r){const c=t[l],u=c===void 0||r(c,l,t);if(u!==!0)throw new Ue("option "+l+" must be "+u,Ue.ERR_BAD_OPTION_VALUE);continue}if(n!==!0)throw new Ue("Unknown option "+l,Ue.ERR_BAD_OPTION)}}const Fi={assertOptions:eb,validators:pr},Fn=Fi.validators;let Ls=class{constructor(e){this.defaults=e||{},this.interceptors={request:new Lu,response:new Lu}}async request(e,n){try{return await this._request(e,n)}catch(s){if(s instanceof Error){let i={};Error.captureStackTrace?Error.captureStackTrace(i):i=new Error;const l=i.stack?i.stack.replace(/^.+\n/,""):"";try{s.stack?l&&!String(s.stack).endsWith(l.replace(/^.+\n.+\n/,""))&&(s.stack+=` +`+l):s.stack=l}catch{}}throw s}}_request(e,n){typeof e=="string"?(n=n||{},n.url=e):n=e||{},n=Bs(this.defaults,n);const{transitional:s,paramsSerializer:i,headers:l}=n;s!==void 0&&Fi.assertOptions(s,{silentJSONParsing:Fn.transitional(Fn.boolean),forcedJSONParsing:Fn.transitional(Fn.boolean),clarifyTimeoutError:Fn.transitional(Fn.boolean)},!1),i!=null&&(D.isFunction(i)?n.paramsSerializer={serialize:i}:Fi.assertOptions(i,{encode:Fn.function,serialize:Fn.function},!0)),n.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?n.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:n.allowAbsoluteUrls=!0),Fi.assertOptions(n,{baseUrl:Fn.spelling("baseURL"),withXsrfToken:Fn.spelling("withXSRFToken")},!0),n.method=(n.method||this.defaults.method||"get").toLowerCase();let r=l&&D.merge(l.common,l[n.method]);l&&D.forEach(["delete","get","head","post","put","patch","common"],y=>{delete l[y]}),n.headers=en.concat(r,l);const c=[];let u=!0;this.interceptors.request.forEach(function(P){typeof P.runWhen=="function"&&P.runWhen(n)===!1||(u=u&&P.synchronous,c.unshift(P.fulfilled,P.rejected))});const h=[];this.interceptors.response.forEach(function(P){h.push(P.fulfilled,P.rejected)});let f,g=0,C;if(!u){const y=[Wu.bind(this),void 0];for(y.unshift(...c),y.push(...h),C=y.length,f=Promise.resolve(n);g{if(!s._listeners)return;let l=s._listeners.length;for(;l-- >0;)s._listeners[l](i);s._listeners=null}),this.promise.then=i=>{let l;const r=new Promise(c=>{s.subscribe(c),l=c}).then(i);return r.cancel=function(){s.unsubscribe(l)},r},e(function(l,r,c){s.reason||(s.reason=new wo(l,r,c),n(s.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(e){if(this.reason){e(this.reason);return}this._listeners?this._listeners.push(e):this._listeners=[e]}unsubscribe(e){if(!this._listeners)return;const n=this._listeners.indexOf(e);n!==-1&&this._listeners.splice(n,1)}toAbortSignal(){const e=new AbortController,n=s=>{e.abort(s)};return this.subscribe(n),e.signal.unsubscribe=()=>this.unsubscribe(n),e.signal}static source(){let e;return{token:new jf(function(i){e=i}),cancel:e}}};function nb(t){return function(n){return t.apply(null,n)}}function sb(t){return D.isObject(t)&&t.isAxiosError===!0}const Ia={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(Ia).forEach(([t,e])=>{Ia[e]=t});function qf(t){const e=new Ls(t),n=Cf(Ls.prototype.request,e);return D.extend(n,Ls.prototype,e,{allOwnKeys:!0}),D.extend(n,e,null,{allOwnKeys:!0}),n.create=function(i){return qf(Bs(t,i))},n}const Et=qf(ii);Et.Axios=Ls;Et.CanceledError=wo;Et.CancelToken=tb;Et.isCancel=Ff;Et.VERSION=Vf;Et.toFormData=hr;Et.AxiosError=Ue;Et.Cancel=Et.CanceledError;Et.all=function(e){return Promise.all(e)};Et.spread=nb;Et.isAxiosError=sb;Et.mergeConfig=Bs;Et.AxiosHeaders=en;Et.formToJSON=t=>Nf(D.isHTMLForm(t)?new FormData(t):t);Et.getAdapter=Uf.getAdapter;Et.HttpStatusCode=Ia;Et.default=Et;const{Axios:p9,AxiosError:g9,CanceledError:m9,isCancel:v9,CancelToken:b9,VERSION:y9,all:w9,Cancel:_9,isAxiosError:C9,spread:k9,toFormData:S9,AxiosHeaders:E9,HttpStatusCode:$9,formToJSON:T9,getAdapter:A9,mergeConfig:R9}=Et,be=Et.create({baseURL:"/",withCredentials:!0,headers:{Accept:"application/json"}}),Gi=O(null),Qi=O(""),Oa=O(!0),Ma=O("");async function ob(){var t,e;try{Oa.value=!0,Ma.value="";const n=await be.get("/api/session");Gi.value=n.data.user,Qi.value=n.data.version}catch(n){Gi.value=null,Qi.value="",Ma.value=((e=(t=n==null?void 0:n.response)==null?void 0:t.data)==null?void 0:e.result)||n.message||"Session error"}finally{Oa.value=!1}}function ib(){Gi.value=null,Qi.value=""}function il(){return{user:Gi,version:Qi,loading:Oa,error:Ma,loadSession:ob,clearSession:ib}}const xi=Xt([]);let rb=1;function we(t,e="success",n=4e3){const s=rb++;xi.push({id:s,type:e,message:t}),setTimeout(()=>{const i=xi.findIndex(l=>l.id===s);i!==-1&&xi.splice(i,1)},n)}function ab(){return xi}const lb=$t({setup(){const t=ab();function e(s){const i=t.findIndex(l=>l.id===s);i!==-1&&t.splice(i,1)}function n(s){return s==="success"?"bg-success":s==="error"?"bg-danger":"bg-info"}return{toasts:t,dismiss:e,headerClass:n}}}),It=(t,e)=>{const n=t.__vccOpts||t;for(const[s,i]of e)n[s]=i;return n},cb={class:"position-fixed top-0 end-0 p-3",style:{"z-index":"1080"}},ub={class:"me-auto text-white"},db=["onClick"],fb={class:"toast-body"};function hb(t,e,n,s,i,l){return b(),w("div",cb,[(b(!0),w(Xe,null,Yt(t.toasts,r=>(b(),w("div",{key:r.id,class:"toast show mb-2",role:"alert","aria-live":"assertive","aria-atomic":"true"},[o("div",{class:ae(["toast-header",t.headerClass(r.type)])},[o("strong",ub,A(r.type),1),e[0]||(e[0]=o("small",{class:"text-white-50"},"agora",-1)),o("button",{type:"button",class:"btn-close btn-close-white ms-2 mb-1",onClick:c=>t.dismiss(r.id)},null,8,db)],2),o("div",fb,A(r.message),1)]))),128))])}const pb=It(lb,[["render",hb],["__scopeId","data-v-e78c0add"]]),gb=$t({components:{RouterLink:el,RouterView:_f,Toaster:pb},setup(){const t=new Date().getFullYear(),e=il(),n=ti(),s=ns(),i=O("0.0.0"),l=O({title:"QuePasa",logo:"",favicon:"",primaryColor:"#7C3AED",secondaryColor:"#5B21B6",accentColor:"#8B5CF6",companyName:"",companyUrl:""}),r=Ye(()=>s.path==="/login"),c=Ye(()=>r.value?"":"container py-4"),u=Ye(()=>({background:`linear-gradient(135deg, ${l.value.primaryColor}, ${l.value.secondaryColor})`})),h=async()=>{var y,P;try{const I=await be.get("/api/login/config");if((y=I.data)!=null&&y.branding){l.value={...l.value,...I.data.branding};const H=document.documentElement;if(H.style.setProperty("--branding-primary",l.value.primaryColor),H.style.setProperty("--branding-secondary",l.value.secondaryColor),H.style.setProperty("--branding-accent",l.value.accentColor),document.title=l.value.title,l.value.favicon){let W=document.querySelector('link[rel="icon"]');W||(W=document.createElement("link"),W.rel="icon",document.head.appendChild(W)),W.href=l.value.favicon}}(P=I.data)!=null&&P.version&&(i.value=I.data.version)}catch{}},f=async()=>{await e.loadSession()},g=async()=>{C();try{await be.get("/logout")}catch{}e.clearSession(),n.push("/login")},C=()=>{var P,I;const y=document.getElementById("navbarOffcanvas");if(y){const H=(I=(P=window.bootstrap)==null?void 0:P.Offcanvas)==null?void 0:I.getInstance(y);H&&H.hide()}},_=y=>{C(),n.push(y)};return cn(()=>{h(),f()}),{year:t,session:e,logout:g,isLoginPage:r,branding:l,navbarStyle:u,containerClass:c,appVersion:i,navigateTo:_}}}),mb={key:0,class:"mb-4"},vb={class:"container-fluid"},bb=["src"],yb={class:"collapse navbar-collapse d-none d-lg-flex",id:"navbarNav"},wb={class:"navbar-nav me-auto"},_b={class:"nav-item"},Cb={class:"nav-item"},kb={class:"nav-item dropdown"},Sb={class:"dropdown-menu","aria-labelledby":"manageMenu"},Eb={key:0,class:"d-flex align-items-center text-white"},$b={class:"me-3"},Tb={class:"offcanvas offcanvas-end d-lg-none",tabindex:"-1",id:"navbarOffcanvas","aria-labelledby":"navbarOffcanvasLabel"},Ab={class:"offcanvas-title text-white",id:"navbarOffcanvasLabel"},Rb=["src"],Pb={class:"offcanvas-body"},Ib={class:"navbar-nav"},Ob={class:"nav-item"},Mb={class:"nav-item"},Db={class:"nav-item"},Lb={class:"nav-item"},Nb={class:"nav-item"},Fb={class:"nav-item"},xb={key:0,class:"nav-item"},Bb={class:"nav-link text-muted small"},zb={class:"nav-item"},Hb={key:0,class:"text-center py-5"},Ub={key:1,class:"app-footer"},Vb={class:"footer-content"},jb={class:"footer-left"},qb=["href"],Wb={key:1},Kb={class:"footer-right"},Gb={class:"version-badge"};function Qb(t,e,n,s,i,l){const r=zt("RouterLink"),c=zt("RouterView"),u=zt("Toaster");return b(),w("div",{class:ae(t.containerClass)},[t.isLoginPage?U("",!0):(b(),w("header",mb,[o("nav",{class:"navbar navbar-expand-lg navbar-dark rounded",style:Sn(t.navbarStyle)},[o("div",vb,[ke(r,{class:"navbar-brand d-flex align-items-center",to:"/"},{default:Ze(()=>[t.branding.logo?(b(),w("img",{key:0,src:t.branding.logo,alt:"Logo",class:"navbar-logo me-2"},null,8,bb)):U("",!0),L(" "+A(t.branding.title||"QuePasa"),1)]),_:1}),e[30]||(e[30]=o("button",{class:"navbar-toggler",type:"button","data-bs-toggle":"offcanvas","data-bs-target":"#navbarOffcanvas","aria-controls":"navbarOffcanvas","aria-label":"Toggle navigation"},[o("span",{class:"navbar-toggler-icon"})],-1)),o("div",yb,[o("ul",wb,[o("li",_b,[ke(r,{class:"nav-link",to:"/"},{default:Ze(()=>[...e[8]||(e[8]=[L("Home",-1)])]),_:1})]),o("li",Cb,[ke(r,{class:"nav-link",to:"/account"},{default:Ze(()=>[...e[9]||(e[9]=[L("Account",-1)])]),_:1})]),o("li",kb,[e[16]||(e[16]=o("a",{class:"nav-link dropdown-toggle",href:"#",id:"manageMenu",role:"button","data-bs-toggle":"dropdown","aria-expanded":"false"},"Manage",-1)),o("ul",Sb,[o("li",null,[ke(r,{class:"dropdown-item",to:"/users"},{default:Ze(()=>[...e[10]||(e[10]=[L("Users",-1)])]),_:1})]),o("li",null,[ke(r,{class:"dropdown-item",to:"/users/create"},{default:Ze(()=>[...e[11]||(e[11]=[L("Create User",-1)])]),_:1})]),e[13]||(e[13]=o("li",null,[o("hr",{class:"dropdown-divider"})],-1)),o("li",null,[ke(r,{class:"dropdown-item",to:"/environment"},{default:Ze(()=>[...e[12]||(e[12]=[L("Environment",-1)])]),_:1})]),e[14]||(e[14]=o("li",null,[o("hr",{class:"dropdown-divider"})],-1)),e[15]||(e[15]=o("li",null,[o("a",{class:"dropdown-item",href:"/swagger/",target:"_blank"},"API Docs (Swagger)")],-1))])])]),t.session.user.value?(b(),w("div",Eb,[o("small",$b,A(t.session.user.value.username),1),o("button",{class:"btn btn-outline-light btn-sm",onClick:e[0]||(e[0]=(...h)=>t.logout&&t.logout(...h))},"Logout")])):U("",!0)]),o("div",Tb,[o("div",{class:"offcanvas-header",style:Sn(t.navbarStyle)},[o("h5",Ab,[t.branding.logo?(b(),w("img",{key:0,src:t.branding.logo,alt:"Logo",class:"navbar-logo me-2"},null,8,Rb)):U("",!0),L(" "+A(t.branding.title||"QuePasa"),1)]),e[17]||(e[17]=o("button",{type:"button",class:"btn-close btn-close-white","data-bs-dismiss":"offcanvas","aria-label":"Close"},null,-1))],4),o("div",Pb,[o("ul",Ib,[o("li",Ob,[o("a",{class:"nav-link",href:"#",onClick:e[1]||(e[1]=kt(h=>t.navigateTo("/"),["prevent"]))},[...e[18]||(e[18]=[o("i",{class:"fa fa-home me-2"},null,-1),L(" Home ",-1)])])]),o("li",Mb,[o("a",{class:"nav-link",href:"#",onClick:e[2]||(e[2]=kt(h=>t.navigateTo("/account"),["prevent"]))},[...e[19]||(e[19]=[o("i",{class:"fa fa-user me-2"},null,-1),L(" Account ",-1)])])]),e[26]||(e[26]=o("li",null,[o("hr",{class:"my-2"})],-1)),o("li",Db,[o("a",{class:"nav-link",href:"#",onClick:e[3]||(e[3]=kt(h=>t.navigateTo("/setup"),["prevent"]))},[...e[20]||(e[20]=[o("i",{class:"fa fa-cog me-2"},null,-1),L(" Setup ",-1)])])]),o("li",Lb,[o("a",{class:"nav-link",href:"#",onClick:e[4]||(e[4]=kt(h=>t.navigateTo("/users"),["prevent"]))},[...e[21]||(e[21]=[o("i",{class:"fa fa-users me-2"},null,-1),L(" Users ",-1)])])]),o("li",Nb,[o("a",{class:"nav-link",href:"#",onClick:e[5]||(e[5]=kt(h=>t.navigateTo("/users/create"),["prevent"]))},[...e[22]||(e[22]=[o("i",{class:"fa fa-user-plus me-2"},null,-1),L(" Create User ",-1)])])]),e[27]||(e[27]=o("li",null,[o("hr",{class:"my-2"})],-1)),o("li",Fb,[o("a",{class:"nav-link",href:"#",onClick:e[6]||(e[6]=kt(h=>t.navigateTo("/environment"),["prevent"]))},[...e[23]||(e[23]=[o("i",{class:"fa fa-cog me-2"},null,-1),L(" Environment ",-1)])])]),e[28]||(e[28]=o("li",{class:"nav-item"},[o("a",{class:"nav-link",href:"/swagger/",target:"_blank"},[o("i",{class:"fa fa-book me-2"}),L(" API Docs ")])],-1)),e[29]||(e[29]=o("li",null,[o("hr",{class:"my-2"})],-1)),t.session.user.value?(b(),w("li",xb,[o("div",Bb,[e[24]||(e[24]=o("i",{class:"fa fa-user-circle me-2"},null,-1)),L(" "+A(t.session.user.value.username),1)])])):U("",!0),o("li",zb,[o("a",{class:"nav-link text-danger",href:"#",onClick:e[7]||(e[7]=kt((...h)=>t.logout&&t.logout(...h),["prevent"]))},[...e[25]||(e[25]=[o("i",{class:"fa fa-sign-out-alt me-2"},null,-1),L(" Logout ",-1)])])])])])])])],4)])),o("main",null,[t.session.loading.value?(b(),w("div",Hb,"Carregando sessão...")):(b(),Wo(c,{key:1}))]),ke(u),t.isLoginPage?U("",!0):(b(),w("footer",Ub,[o("div",Vb,[o("div",jb,[o("span",null,"© "+A(t.year),1),t.branding.companyUrl?(b(),w("a",{key:0,href:t.branding.companyUrl,target:"_blank",class:"company-link"},A(t.branding.companyName||t.branding.title||"QuePasa"),9,qb)):(b(),w("span",Wb,A(t.branding.companyName||t.branding.title||"QuePasa"),1))]),o("div",Kb,[o("span",Gb,"v"+A(t.appVersion),1)])])]))],2)}const Jb=It(gb,[["render",Qb]]),Xb="modulepreload",Yb=function(t){return"/assets/frontend/"+t},Gu={},Qu=function(e,n,s){let i=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const r=document.querySelector("meta[property=csp-nonce]"),c=(r==null?void 0:r.nonce)||(r==null?void 0:r.getAttribute("nonce"));i=Promise.allSettled(n.map(u=>{if(u=Yb(u),u in Gu)return;Gu[u]=!0;const h=u.endsWith(".css"),f=h?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${u}"]${f}`))return;const g=document.createElement("link");if(g.rel=h?"stylesheet":Xb,h||(g.as="script"),g.crossOrigin="",g.href=u,c&&g.setAttribute("nonce",c),document.head.appendChild(g),h)return new Promise((C,_)=>{g.addEventListener("load",C),g.addEventListener("error",()=>_(new Error(`Unable to preload CSS for ${u}`)))})}))}function l(r){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=r,window.dispatchEvent(c),!c.defaultPrevented)throw r}return i.then(r=>{for(const c of r||[])c.status==="rejected"&&l(c.reason);return e().catch(l)})},Zb=$t({setup(){const t=ti(),e=O([]),n=O(!0),s=O(""),i=O("card"),l=O(""),r=O(""),c=O(!1),u=Ye(()=>e.value.filter(S=>{var x;return((x=S.state)==null?void 0:x.toLowerCase())==="ready"}).length),h=Ye(()=>e.value.filter(S=>{var x;return((x=S.state)==null?void 0:x.toLowerCase())!=="ready"}).length),f=O(0),g=Ye(()=>f.value>0),C=O(1),_=O(10),y=[10,25,50,100],P=O(""),I=O("");let H=null;const W=Ye(()=>{const S=I.value.trim().toLowerCase();return S?e.value.filter(x=>{const Z=(x.token||"").toLowerCase(),v=(x.wid||"").toLowerCase(),E=(x.state||"").toLowerCase();return Z.includes(S)||v.includes(S)||E.includes(S)}):e.value}),G=Ye(()=>Math.ceil(W.value.length/_.value)||1),F=Ye(()=>{const S=(C.value-1)*_.value,x=S+_.value;return W.value.slice(S,x)});hs([I,_],()=>{C.value=1});function ne(S){S>=1&&S<=G.value&&(C.value=S)}function he(){C.value1&&C.value--}function Ee(){I.value=P.value,H&&(clearTimeout(H),H=null)}function Se(){P.value="",I.value=""}hs(P,S=>{H&&clearTimeout(H),H=setTimeout(()=>{I.value=S},300)}),hs(I,async S=>{const x=(S||"").trim();if(x.length===0){await _e();return}await ye(x)});async function _e(){var S,x;try{n.value=!0,s.value="";const Z=await be.get("/api/servers");e.value=Z.data.servers||[],f.value=e.value.length,Z.data.serversViewMode&&(i.value=Z.data.serversViewMode)}catch(Z){s.value=((x=(S=Z==null?void 0:Z.response)==null?void 0:S.data)==null?void 0:x.result)||Z.message||"Erro ao carregar servidores"}finally{n.value=!1}}async function ye(S){var x,Z;try{n.value=!0,s.value="";const v={query:S,page:1,limit:50},E=await be.post("/api/servers/search",v);e.value=E.data.servers||[]}catch(v){s.value=((Z=(x=v==null?void 0:v.response)==null?void 0:x.data)==null?void 0:Z.result)||v.message||"Error searching servers"}finally{n.value=!1}}function Me(S){var Z;const x=((Z=S.state)==null?void 0:Z.toLowerCase())||"";return x==="ready"?"connected":x==="connecting"||x==="starting"?"connecting":"disconnected"}function ve(S){const x=(S.connection||S.state||"").toLowerCase();return x==="ready"?"ready":x==="connecting"?"connecting":x==="unverified"?"unverified":"disconnected"}function te(S){var x;return((x=S.state)==null?void 0:x.toLowerCase())==="ready"}function Le(S){return S===1||S===!0?"state-on":S===-1||S===!1?"state-off":"state-unset"}function Y(S,x){return x===1||x===!0?`${S}: ON (forçado)`:x===-1||x===!1?`${S}: OFF (forçado)`:`${S}: Padrão do sistema`}function oe(S){if(!S||S<0)return"-";const x=Math.floor(S/86400),Z=Math.floor(S%86400/3600),v=Math.floor(S%3600/60);return x>0?`${x}d ${Z}h ${v}m`:Z>0?`${Z}h ${v}m`:`${v}m`}function Q(S){if(!S)return"";let x=S.split("@")[0];return x=x.split(":")[0],x}async function Re(S){const x=()=>{l.value=S,we("Token copiado!","success"),setTimeout(()=>l.value="",2e3)};try{await navigator.clipboard.writeText(S),x()}catch{const Z=document.createElement("textarea");Z.value=S,document.body.appendChild(Z),Z.select(),document.execCommand("copy"),document.body.removeChild(Z),x()}}async function He(S){var x,Z;try{r.value=S.token;const v=te(S)?"stop":"start";await be.post("/api/command",{token:S.token,action:v}),await _e(),we("Servidor atualizado","success")}catch(v){we(((Z=(x=v==null?void 0:v.response)==null?void 0:x.data)==null?void 0:Z.result)||"Erro ao alterar servidor","error")}finally{r.value=""}}async function z(S){var x,Z;if(confirm("Deseja realmente desconectar este servidor?"))try{r.value=S.token,await be.post("/api/command",{token:S.token,action:"stop"}),await _e(),we("Servidor desconectado","success")}catch(v){we(((Z=(x=v==null?void 0:v.response)==null?void 0:x.data)==null?void 0:Z.result)||"Erro ao desconectar","error")}finally{r.value=""}}async function Qe(S){var x,Z;try{r.value=S.token,await be.post("/api/debug",{token:S.token}),await _e(),we("Debug atualizado","success")}catch(v){we(((Z=(x=v==null?void 0:v.response)==null?void 0:x.data)==null?void 0:Z.result)||"Erro ao alterar debug","error")}finally{r.value=""}}async function Ke(S){var x,Z;try{r.value=S.token,await be.post("/api/command",{token:S.token,action:"groups"}),await _e(),we("Grupos atualizado","success")}catch(v){we(((Z=(x=v==null?void 0:v.response)==null?void 0:x.data)==null?void 0:Z.result)||"Erro ao alterar grupos","error")}finally{r.value=""}}async function yt(S){var x,Z;try{r.value=S.token,await be.post("/api/command",{token:S.token,action:"broadcasts"}),await _e(),we("Broadcasts atualizado","success")}catch(v){we(((Z=(x=v==null?void 0:v.response)==null?void 0:x.data)==null?void 0:Z.result)||"Erro ao alterar broadcasts","error")}finally{r.value=""}}async function gt(S){var x,Z;try{r.value=S.token,await be.post("/api/command",{token:S.token,action:"readreceipts"}),await _e(),we("Confirmações de leitura atualizado","success")}catch(v){we(((Z=(x=v==null?void 0:v.response)==null?void 0:x.data)==null?void 0:Z.result)||"Erro ao alterar confirmações","error")}finally{r.value=""}}async function Ae(S){var x,Z;try{r.value=S.token,await be.post("/api/command",{token:S.token,action:"calls"}),await _e(),we("Ligações atualizado","success")}catch(v){we(((Z=(x=v==null?void 0:v.response)==null?void 0:x.data)==null?void 0:Z.result)||"Erro ao alterar ligações","error")}finally{r.value=""}}async function M(S){var x,Z;if(confirm("Deseja realmente REMOVER este servidor? Esta ação não pode ser desfeita."))try{r.value=S.token,await be.post("/api/delete",{token:S.token,key:"server"}),await _e(),we("Servidor removido","success")}catch(v){we(((Z=(x=v==null?void 0:v.response)==null?void 0:x.data)==null?void 0:Z.result)||"Erro ao remover servidor","error")}finally{r.value=""}}async function ee(){var S,x;if(!c.value){c.value=!0;try{const Z=await be.post("/api/server/create",{});if(Z.data&&Z.data.token){const v=Z.data.token;we("Servidor criado com sucesso!","success"),t.push(`/server/${v}`)}else throw new Error("Token não recebido do servidor")}catch(Z){console.error("Error creating server:",Z);const v=((x=(S=Z.response)==null?void 0:S.data)==null?void 0:x.message)||Z.message||"Erro ao criar servidor";we(v,"error")}finally{c.value=!1}}}return cn(()=>{_e()}),{servers:e,loading:n,error:s,connectedCount:u,disconnectedCount:h,viewMode:i,searchQuery:P,displayServers:F,copiedToken:l,toggling:r,hasServers:g,creating:c,filteredServers:W,currentPage:C,pageSize:_,pageSizeOptions:y,totalPages:G,load:_e,getStatusClass:Me,getConnectionClass:ve,isConnected:te,formatUptime:oe,formatWid:Q,copyToken:Re,toggleServer:He,toggleDebug:Qe,toggleGroups:Ke,toggleBroadcasts:yt,toggleReadReceipts:gt,toggleCalls:Ae,disconnectServer:z,deleteServer:M,applySearch:Ee,clearSearch:Se,goToPage:ne,nextPage:he,prevPage:ce,createNewServer:ee,getTriStateClass:Le,getTriStateTitle:Y}}}),ey={class:"home-page"},ty={class:"page-header"},ny={class:"header-actions"},sy={key:0,class:"desktop-controls"},oy={class:"search-box"},iy={class:"view-toggle"},ry=["disabled"],ay={key:0,class:"spinner-small"},ly={key:0,class:"mobile-controls"},cy={class:"search-box"},uy={class:"view-toggle"},dy=["disabled"],fy={key:0,class:"spinner-small"},hy={key:1,viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},py={key:1,class:"stats-bar"},gy={class:"stat-item"},my={class:"stat-value"},vy={class:"stat-item connected"},by={class:"stat-value"},yy={class:"stat-item disconnected"},wy={class:"stat-value"},_y={key:2,class:"loading-state"},Cy={key:3,class:"error-box"},ky={key:4,class:"empty-state"},Sy=["disabled"],Ey={key:5,class:"no-results"},$y={key:6,class:"servers-table-wrapper"},Ty={class:"servers-table"},Ay={class:"status-cell"},Ry=["title"],Py={class:"phone-cell"},Iy={class:"token-cell"},Oy=["onClick","title"],My={key:0,class:"fa fa-check text-success ms-1"},Dy={class:"status-cell"},Ly={class:"dispatch-cell",title:"Total dispatch configurations"},Ny={key:0,class:"dispatch-count"},Fy={key:1,class:"dispatch-count"},xy={class:"connection-cell"},By={class:"actions-cell"},zy={class:"dropdown"},Hy=["disabled"],Uy={class:"dropdown-menu dropdown-menu-end"},Vy=["onClick"],jy=["onClick"],qy=["onClick"],Wy=["onClick"],Ky=["onClick"],Gy=["onClick"],Qy={key:1},Jy=["onClick"],Xy=["onClick"],Yy={key:7,class:"servers-grid"},Zy={class:"server-header"},e0={class:"server-info"},t0={class:"server-details"},n0={class:"detail-row"},s0=["onClick","title"],o0={key:0,class:"fa fa-check text-success ms-1"},i0={key:0,class:"detail-row"},r0={class:"detail-value"},a0={class:"detail-row"},l0={class:"detail-value"},c0={key:0,class:"fa fa-bell text-success",title:"Dispatch count"},u0={class:"ms-1"},d0={key:1,class:"fa fa-link text-success ms-2",title:"Dispatching: {{ srv.webhook_count }}"},f0={key:2,class:"fa fa-database text-success ms-1",title:"RabbitMQ: {{ srv.rabbitmq_count }}"},h0={class:"detail-row"},p0={class:"flags-row"},g0=["title"],m0=["title"],v0=["title"],b0=["title"],y0={key:0,class:"quick-toggles"},w0=["onClick","disabled"],_0=["onClick","disabled"],C0=["onClick","disabled"],k0=["onClick","disabled"],S0={class:"server-actions"},E0=["onClick","disabled"],$0=["onClick","disabled"],T0=["onClick","disabled"],A0=["onClick","title","disabled"],R0={key:8,class:"pagination-bar"},P0={class:"pagination-info"},I0={class:"pagination-controls"},O0={class:"page-size-selector"},M0=["value"],D0={class:"page-nav"},L0=["disabled"],N0={class:"page-indicator"},F0=["disabled"];function x0(t,e,n,s,i,l){const r=zt("router-link");return b(),w("div",ey,[o("div",ty,[e[22]||(e[22]=o("div",{class:"header-content"},[o("h1",null,"Seus Servidores"),o("p",{class:"hide-mobile"},"Gerencie suas conexões WhatsApp")],-1)),o("div",ny,[t.hasServers?(b(),w("div",sy,[o("div",oy,[Be(o("input",{"onUpdate:modelValue":e[0]||(e[0]=c=>t.searchQuery=c),onKeyup:e[1]||(e[1]=Wi((...c)=>t.applySearch&&t.applySearch(...c),["enter"])),class:"search-input",type:"search",placeholder:"Search...","aria-label":"Search servers",title:"Search servers"},null,544),[[at,t.searchQuery]]),t.searchQuery?(b(),w("button",{key:0,class:"search-clear",onClick:e[2]||(e[2]=(...c)=>t.clearSearch&&t.clearSearch(...c)),title:"Clear search"},[...e[17]||(e[17]=[o("i",{class:"fa fa-times"},null,-1)])])):U("",!0)]),o("div",iy,[o("button",{class:ae(["view-btn",{active:t.viewMode==="card"}]),onClick:e[3]||(e[3]=c=>t.viewMode="card"),title:"Card view"},[...e[18]||(e[18]=[o("i",{class:"fa fa-th-large"},null,-1)])],2),o("button",{class:ae(["view-btn",{active:t.viewMode==="table"}]),onClick:e[4]||(e[4]=c=>t.viewMode="table"),title:"Table view"},[...e[19]||(e[19]=[o("i",{class:"fa fa-list"},null,-1)])],2)])])):U("",!0),o("button",{onClick:e[5]||(e[5]=(...c)=>t.createNewServer&&t.createNewServer(...c)),class:"btn-add",disabled:t.creating},[t.creating?(b(),w("div",ay)):(b(),w(Xe,{key:1},[e[20]||(e[20]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"})],-1)),e[21]||(e[21]=o("span",{class:"hide-mobile"},"New Server",-1))],64))],8,ry)])]),t.hasServers?(b(),w("div",ly,[o("div",cy,[Be(o("input",{"onUpdate:modelValue":e[6]||(e[6]=c=>t.searchQuery=c),onKeyup:e[7]||(e[7]=Wi((...c)=>t.applySearch&&t.applySearch(...c),["enter"])),class:"search-input",type:"search",placeholder:"Search...","aria-label":"Search servers",title:"Search servers"},null,544),[[at,t.searchQuery]]),t.searchQuery?(b(),w("button",{key:0,class:"search-clear",onClick:e[8]||(e[8]=(...c)=>t.clearSearch&&t.clearSearch(...c)),title:"Clear search"},[...e[23]||(e[23]=[o("i",{class:"fa fa-times"},null,-1)])])):U("",!0)]),o("div",uy,[o("button",{class:ae(["view-btn",{active:t.viewMode==="card"}]),onClick:e[9]||(e[9]=c=>t.viewMode="card"),title:"Card view"},[...e[24]||(e[24]=[o("i",{class:"fa fa-th-large"},null,-1)])],2),o("button",{class:ae(["view-btn",{active:t.viewMode==="table"}]),onClick:e[10]||(e[10]=c=>t.viewMode="table"),title:"Table view"},[...e[25]||(e[25]=[o("i",{class:"fa fa-list"},null,-1)])],2)]),o("button",{onClick:e[11]||(e[11]=(...c)=>t.createNewServer&&t.createNewServer(...c)),class:"btn-add-mobile",disabled:t.creating},[t.creating?(b(),w("div",fy)):(b(),w("svg",hy,[...e[26]||(e[26]=[o("path",{d:"M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"},null,-1)])]))],8,dy)])):U("",!0),!t.loading&&t.hasServers?(b(),w("div",py,[o("div",gy,[o("span",my,A(t.servers.length),1),e[27]||(e[27]=o("span",{class:"stat-label"},"Total",-1))]),o("div",vy,[o("span",by,A(t.connectedCount),1),e[28]||(e[28]=o("span",{class:"stat-label"},"Conectados",-1))]),o("div",yy,[o("span",wy,A(t.disconnectedCount),1),e[29]||(e[29]=o("span",{class:"stat-label"},"Desconectados",-1))])])):U("",!0),t.loading?(b(),w("div",_y,[...e[30]||(e[30]=[o("div",{class:"spinner-large"},null,-1),o("p",null,"Carregando servidores...",-1)])])):U("",!0),t.error?(b(),w("div",Cy,[e[31]||(e[31]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)),o("span",null,A(t.error),1),o("button",{onClick:e[12]||(e[12]=(...c)=>t.load&&t.load(...c)),class:"retry-btn"},"Tentar novamente")])):!t.loading&&t.servers.length===0?(b(),w("div",ky,[e[36]||(e[36]=o("div",{class:"empty-icon"},[o("svg",{viewBox:"0 0 24 24",width:"80",height:"80",fill:"currentColor"},[o("path",{d:"M12.04 2c-5.46 0-9.91 4.45-9.91 9.91 0 1.75.46 3.45 1.32 4.95L2.05 22l5.25-1.38c1.45.79 3.08 1.21 4.74 1.21 5.46 0 9.91-4.45 9.91-9.91 0-2.65-1.03-5.14-2.9-7.01A9.816 9.816 0 0012.04 2z"})])],-1)),e[37]||(e[37]=o("h2",null,"Nenhum servidor configurado",-1)),e[38]||(e[38]=o("p",null,"Adicione seu primeiro servidor WhatsApp para começar",-1)),o("button",{onClick:e[13]||(e[13]=(...c)=>t.createNewServer&&t.createNewServer(...c)),class:"btn-primary-large",disabled:t.creating},[t.creating?(b(),w(Xe,{key:0},[e[32]||(e[32]=o("div",{class:"spinner-small"},null,-1)),e[33]||(e[33]=o("span",null,"Criando...",-1))],64)):(b(),w(Xe,{key:1},[e[34]||(e[34]=o("svg",{viewBox:"0 0 24 24",width:"24",height:"24",fill:"currentColor"},[o("path",{d:"M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"})],-1)),e[35]||(e[35]=L(" Conectar WhatsApp ",-1))],64))],8,Sy)])):!t.loading&&t.servers.length>0&&t.displayServers.length===0?(b(),w("div",Ey,[...e[39]||(e[39]=[o("h3",null,"No servers match your search",-1),o("p",null,"Try a different query or clear the search.",-1)])])):t.viewMode==="table"?(b(),w("div",$y,[o("table",Ty,[e[58]||(e[58]=o("thead",null,[o("tr",null,[o("th",null,"Active"),o("th",null,"Phone"),o("th",null,"Token"),o("th",null,"Dispatch"),o("th",null,"Connection"),o("th",null,"Actions")])],-1)),o("tbody",null,[(b(!0),w(Xe,null,Yt(t.displayServers,c=>(b(),w("tr",{key:c.token},[o("td",Ay,[o("i",{class:ae(c.verified?"fa fa-check-square text-success":"fa fa-exclamation-triangle text-warning"),title:c.verified?"Server active":"Server not verified"},null,10,Ry)]),o("td",Py,A(t.formatWid(c.wid)||"—"),1),o("td",Iy,[o("code",{class:"token-code truncated",onClick:u=>t.copyToken(c.token),title:c.token},A(c.token),9,Oy),t.copiedToken===c.token?(b(),w("i",My)):U("",!0)]),o("td",Dy,[o("div",Ly,[c.dispatch_count>0?(b(),w("span",Ny,A(c.dispatch_count),1)):(b(),w("span",Fy,"0"))])]),o("td",xy,[o("span",{class:ae(["connection-badge",t.getConnectionClass(c)])},A(c.connection||c.state||"Unknown"),3)]),o("td",By,[o("div",zy,[o("button",{class:"action-dropdown-btn",type:"button","data-bs-toggle":"dropdown","aria-expanded":"false",disabled:t.toggling===c.token},[...e[40]||(e[40]=[o("i",{class:"fa fa-ellipsis-v"},null,-1)])],8,Hy),o("ul",Uy,[o("li",null,[ke(r,{to:`/server/${c.token}`,class:"dropdown-item"},{default:Ze(()=>[...e[41]||(e[41]=[o("i",{class:"fa fa-eye me-2"},null,-1),L(" Open ",-1)])]),_:1},8,["to"])]),t.isConnected(c)?(b(),w(Xe,{key:0},[o("li",null,[ke(r,{to:`/server/${c.token}/send`,class:"dropdown-item"},{default:Ze(()=>[...e[42]||(e[42]=[o("i",{class:"fa fa-paper-plane me-2"},null,-1),L(" Send Message ",-1)])]),_:1},8,["to"])]),o("li",null,[ke(r,{to:`/server/${c.token}/messages`,class:"dropdown-item"},{default:Ze(()=>[...e[43]||(e[43]=[o("i",{class:"fa fa-inbox me-2"},null,-1),L(" Messages ",-1)])]),_:1},8,["to"])]),e[46]||(e[46]=o("li",null,[o("hr",{class:"dropdown-divider"})],-1)),o("li",null,[o("button",{class:ae(["dropdown-item",{active:c.devel}]),onClick:u=>t.toggleDebug(c)},[e[44]||(e[44]=o("i",{class:"fa fa-bug me-2"},null,-1)),L(" Debug "+A(c.devel?"(ON)":"(OFF)"),1)],10,Vy)]),o("li",null,[o("button",{class:"dropdown-item text-warning",onClick:u=>t.disconnectServer(c)},[...e[45]||(e[45]=[o("i",{class:"fa fa-unlink me-2"},null,-1),L(" Disconnect ",-1)])],8,jy)])],64)):U("",!0),e[55]||(e[55]=o("li",null,[o("hr",{class:"dropdown-divider"})],-1)),o("li",null,[o("button",{class:ae(["dropdown-item",{active:c.groups}]),onClick:u=>t.toggleGroups(c)},[e[47]||(e[47]=o("i",{class:"fa fa-users me-2"},null,-1)),L(" Groups "+A(c.groups?"(ON)":"(OFF)"),1)],10,qy)]),o("li",null,[o("button",{class:ae(["dropdown-item",{active:c.broadcasts}]),onClick:u=>t.toggleBroadcasts(c)},[e[48]||(e[48]=o("i",{class:"fa fa-bullhorn me-2"},null,-1)),L(" Broadcasts "+A(c.broadcasts?"(ON)":"(OFF)"),1)],10,Wy)]),o("li",null,[o("button",{class:ae(["dropdown-item",{active:c.read_receipts}]),onClick:u=>t.toggleReadReceipts(c)},[e[49]||(e[49]=o("i",{class:"fa fa-check-double me-2"},null,-1)),L(" Read Receipts "+A(c.read_receipts?"(ON)":"(OFF)"),1)],10,Ky)]),o("li",null,[o("button",{class:ae(["dropdown-item",{active:c.calls}]),onClick:u=>t.toggleCalls(c)},[e[50]||(e[50]=o("i",{class:"fa fa-phone me-2"},null,-1)),L(" Calls "+A(c.calls?"(ON)":"(OFF)"),1)],10,Gy)]),e[56]||(e[56]=o("li",null,[o("hr",{class:"dropdown-divider"})],-1)),o("li",null,[ke(r,{to:`/dispatching?token=${c.token}`,class:"dropdown-item"},{default:Ze(()=>[...e[51]||(e[51]=[o("i",{class:"fa fa-link me-2"},null,-1),L(" Dispatching ",-1)])]),_:1},8,["to"])]),o("li",null,[ke(r,{to:`/rabbitmq?token=${c.token}`,class:"dropdown-item"},{default:Ze(()=>[...e[52]||(e[52]=[o("i",{class:"fa fa-database me-2"},null,-1),L(" RabbitMQ ",-1)])]),_:1},8,["to"])]),e[57]||(e[57]=o("li",null,[o("hr",{class:"dropdown-divider"})],-1)),t.isConnected(c)?U("",!0):(b(),w("li",Qy,[ke(r,{to:`/server/${c.token}/qrcode`,class:"dropdown-item text-success"},{default:Ze(()=>[...e[53]||(e[53]=[o("i",{class:"fa fa-qrcode me-2"},null,-1),L(" Connect ",-1)])]),_:1},8,["to"])])),o("li",null,[o("button",{class:"dropdown-item",onClick:u=>t.toggleServer(c)},[o("i",{class:ae(c.verified?"fa fa-power-off me-2":"fa fa-play me-2")},null,2),L(" "+A(c.verified?"Disable":"Enable"),1)],8,Jy)]),o("li",null,[o("button",{class:"dropdown-item text-danger",onClick:u=>t.deleteServer(c)},[...e[54]||(e[54]=[o("i",{class:"fa fa-trash me-2"},null,-1),L(" Remove ",-1)])],8,Xy)])])])])]))),128))])])])):(b(),w("div",Yy,[(b(!0),w(Xe,null,Yt(t.displayServers,c=>(b(),w("div",{key:c.token,class:ae(["server-card",t.getStatusClass(c)])},[o("div",Zy,[o("div",{class:ae(["server-avatar",t.getStatusClass(c)])},[...e[59]||(e[59]=[o("svg",{viewBox:"0 0 24 24",width:"28",height:"28",fill:"currentColor"},[o("path",{d:"M12.04 2c-5.46 0-9.91 4.45-9.91 9.91 0 1.75.46 3.45 1.32 4.95L2.05 22l5.25-1.38c1.45.79 3.08 1.21 4.74 1.21 5.46 0 9.91-4.45 9.91-9.91 0-2.65-1.03-5.14-2.9-7.01A9.816 9.816 0 0012.04 2z"})],-1)])],2),o("div",e0,[o("h3",null,A(t.formatWid(c.wid)||"Not connected"),1),o("span",{class:ae(["status-badge",t.getStatusClass(c)])},A(c.state||"Unknown"),3)])]),o("div",t0,[o("div",n0,[e[60]||(e[60]=o("span",{class:"detail-label"},"Token:",-1)),o("code",{class:"detail-value token-code truncated",onClick:u=>t.copyToken(c.token),title:c.token},[L(A(c.token)+" ",1),t.copiedToken===c.token?(b(),w("i",o0)):U("",!0)],8,s0)]),c.uptime_seconds>=0?(b(),w("div",i0,[e[61]||(e[61]=o("span",{class:"detail-label"},"Uptime:",-1)),o("span",r0,A(t.formatUptime(c.uptime_seconds)),1)])):U("",!0),o("div",a0,[e[62]||(e[62]=o("span",{class:"detail-label"},"Dispatch:",-1)),o("span",l0,[c.dispatch_count>0?(b(),w("i",c0)):U("",!0),o("span",u0,A(c.dispatch_count||0),1),c.webhook_count>0?(b(),w("i",d0)):U("",!0),c.rabbitmq_count>0?(b(),w("i",f0)):U("",!0)])]),o("div",h0,[e[67]||(e[67]=o("span",{class:"detail-label"},"Status:",-1)),o("div",p0,[o("span",{class:ae(["flag-badge",t.getTriStateClass(c.groups)]),title:t.getTriStateTitle("Groups",c.groups)},[...e[63]||(e[63]=[o("i",{class:"fa fa-users"},null,-1)])],10,g0),o("span",{class:ae(["flag-badge",t.getTriStateClass(c.broadcasts)]),title:t.getTriStateTitle("Broadcasts",c.broadcasts)},[...e[64]||(e[64]=[o("i",{class:"fa fa-bullhorn"},null,-1)])],10,m0),o("span",{class:ae(["flag-badge",t.getTriStateClass(c.readreceipts)]),title:t.getTriStateTitle("Read Receipts",c.readreceipts)},[...e[65]||(e[65]=[o("i",{class:"fa fa-check-double"},null,-1)])],10,v0),o("span",{class:ae(["flag-badge",t.getTriStateClass(c.calls)]),title:t.getTriStateTitle("Calls",c.calls)},[...e[66]||(e[66]=[o("i",{class:"fa fa-phone"},null,-1)])],10,b0)])])]),t.isConnected(c)?(b(),w("div",y0,[o("button",{class:ae(["toggle-btn",{active:c.groups}]),onClick:u=>t.toggleGroups(c),title:"Groups",disabled:t.toggling===c.token},[...e[68]||(e[68]=[o("i",{class:"fa fa-users"},null,-1)])],10,w0),o("button",{class:ae(["toggle-btn",{active:c.broadcasts}]),onClick:u=>t.toggleBroadcasts(c),title:"Broadcasts",disabled:t.toggling===c.token},[...e[69]||(e[69]=[o("i",{class:"fa fa-bullhorn"},null,-1)])],10,_0),o("button",{class:ae(["toggle-btn",{active:c.read_receipts}]),onClick:u=>t.toggleReadReceipts(c),title:"Read Receipts",disabled:t.toggling===c.token},[...e[70]||(e[70]=[o("i",{class:"fa fa-check-double"},null,-1)])],10,C0),o("button",{class:ae(["toggle-btn",{active:c.calls}]),onClick:u=>t.toggleCalls(c),title:"Calls",disabled:t.toggling===c.token},[...e[71]||(e[71]=[o("i",{class:"fa fa-phone"},null,-1)])],10,k0)])):U("",!0),o("div",S0,[ke(r,{to:`/server/${c.token}`,class:"btn-action"},{default:Ze(()=>[...e[72]||(e[72]=[o("i",{class:"fa fa-eye"},null,-1),L(" Open ",-1)])]),_:1},8,["to"]),t.isConnected(c)?U("",!0):(b(),Wo(r,{key:0,to:`/server/${c.token}/qrcode`,class:"btn-action success"},{default:Ze(()=>[...e[73]||(e[73]=[o("i",{class:"fa fa-qrcode"},null,-1),L(" Connect ",-1)])]),_:1},8,["to"])),o("button",{class:"btn-action danger",onClick:u=>t.deleteServer(c),title:"Remove Server",disabled:t.toggling===c.token},[...e[74]||(e[74]=[o("i",{class:"fa fa-trash"},null,-1),L(" Remove ",-1)])],8,E0),t.isConnected(c)?(b(),w(Xe,{key:1},[ke(r,{to:`/server/${c.token}/send`,class:"btn-action"},{default:Ze(()=>[...e[75]||(e[75]=[o("i",{class:"fa fa-paper-plane"},null,-1),L(" Send ",-1)])]),_:1},8,["to"]),ke(r,{to:`/server/${c.token}/messages`,class:"btn-action"},{default:Ze(()=>[...e[76]||(e[76]=[o("i",{class:"fa fa-inbox"},null,-1),L(" Messages ",-1)])]),_:1},8,["to"]),ke(r,{to:`/dispatching?token=${c.token}`,class:"btn-action"},{default:Ze(()=>[...e[77]||(e[77]=[o("i",{class:"fa fa-link"},null,-1),L(" Dispatching ",-1)])]),_:1},8,["to"]),o("button",{class:"btn-action warning",onClick:u=>t.disconnectServer(c),title:"Disconnect",disabled:t.toggling===c.token},[...e[78]||(e[78]=[o("i",{class:"fa fa-unlink"},null,-1),L(" Disconnect ",-1)])],8,$0),o("button",{class:ae(["btn-action",{active:c.devel}]),onClick:u=>t.toggleDebug(c),title:"Toggle Debug",disabled:t.toggling===c.token},[...e[79]||(e[79]=[o("i",{class:"fa fa-bug"},null,-1),L(" Debug ",-1)])],10,T0)],64)):U("",!0),o("button",{class:ae(["btn-action",{warning:c.verified}]),onClick:u=>t.toggleServer(c),title:c.verified?"Disable Server":"Enable Server",disabled:t.toggling===c.token},[o("i",{class:ae(c.verified?"fa fa-power-off":"fa fa-play")},null,2),L(" "+A(c.verified?"Disable":"Enable"),1)],10,A0)])],2))),128))])),!t.loading&&t.hasServers&&t.filteredServers.length>0?(b(),w("div",R0,[o("div",P0," Showing "+A((t.currentPage-1)*t.pageSize+1)+"-"+A(Math.min(t.currentPage*t.pageSize,t.filteredServers.length))+" of "+A(t.filteredServers.length)+" servers ",1),o("div",I0,[o("div",O0,[e[80]||(e[80]=o("label",{for:"pageSize"},"Per page:",-1)),Be(o("select",{id:"pageSize","onUpdate:modelValue":e[14]||(e[14]=c=>t.pageSize=c)},[(b(!0),w(Xe,null,Yt(t.pageSizeOptions,c=>(b(),w("option",{key:c,value:c},A(c),9,M0))),128))],512),[[zo,t.pageSize]])]),o("div",D0,[o("button",{class:"page-btn",onClick:e[15]||(e[15]=(...c)=>t.prevPage&&t.prevPage(...c)),disabled:t.currentPage<=1,title:"Previous page"},[...e[81]||(e[81]=[o("i",{class:"fa fa-chevron-left"},null,-1)])],8,L0),o("span",N0,"Page "+A(t.currentPage)+" of "+A(t.totalPages),1),o("button",{class:"page-btn",onClick:e[16]||(e[16]=(...c)=>t.nextPage&&t.nextPage(...c)),disabled:t.currentPage>=t.totalPages,title:"Next page"},[...e[82]||(e[82]=[o("i",{class:"fa fa-chevron-right"},null,-1)])],8,F0)])])])):U("",!0)])}const B0=It(Zb,[["render",x0],["__scopeId","data-v-cec6a771"]]);class z0{constructor(){this.socket=null,this.handlers={}}connect(e){this.socket&&this.disconnect();const n=(window.location.protocol==="https:"?"wss:":"ws:")+"//"+window.location.host+e;this.socket=new WebSocket(n),this.socket.onopen=()=>console.log("WS connected to",n),this.socket.onmessage=s=>{try{const i=JSON.parse(s.data);this.emit("message",i)}catch{this.emit("message",s.data)}},this.socket.onclose=()=>console.log("WS closed"),this.socket.onerror=s=>console.error("WS error",s)}disconnect(){this.socket&&(this.socket.close(),this.socket=null)}on(e,n){this.handlers[e]||(this.handlers[e]=[]),this.handlers[e].push(n)}emit(e,n){(this.handlers[e]||[]).forEach(i=>i(n))}}const H0=new z0,U0=$t({setup(){const t=O(null),e=O(""),n=O(""),s=O(!0),i=O(null),l=O(""),r=O(!1),c=O(""),u=O(!1);async function h(){var _,y,P;try{s.value=!0,n.value="";const I=await be.get("/api/session");t.value=I.data.user,e.value=I.data.version,i.value=I.data.branding,l.value=I.data.serversViewMode;const H=await be.get("/api/account");r.value=((_=H.data)==null?void 0:_.hasMasterKey)||!1,H0.connect("/api/verify/ws")}catch(I){n.value=((P=(y=I==null?void 0:I.response)==null?void 0:y.data)==null?void 0:P.result)||I.message||"Erro ao carregar conta"}finally{s.value=!1}}async function f(){var _,y,P;try{const I=await be.get("/api/account/masterkey");c.value=((_=I.data)==null?void 0:_.masterKey)||"",u.value=!0}catch(I){we(((P=(y=I==null?void 0:I.response)==null?void 0:y.data)==null?void 0:P.result)||"Erro ao carregar master key","error")}}async function g(){if(c.value)try{await navigator.clipboard.writeText(c.value),we("Master Key copiada!","success")}catch{we("Erro ao copiar","error")}}function C(){h()}return cn(()=>{h()}),{user:t,version:e,error:n,loading:s,branding:i,serversViewMode:l,hasMasterKey:r,masterKey:c,showMasterKey:u,reload:C,loadMasterKey:f,copyMasterKey:g}}}),V0={class:"account-page"},j0={key:0,class:"error-box"},q0={key:1,class:"loading-state"},W0={key:2,class:"account-content"},K0={class:"info-card"},G0={class:"card-body"},Q0={class:"info-row"},J0={class:"info-value"},X0={class:"info-row"},Y0={class:"info-value"},Z0={class:"info-card"},ew={class:"card-body"},tw={class:"info-row"},nw={class:"info-value"},sw={key:0,class:"info-row"},ow={class:"info-value"},iw={class:"info-row"},rw={class:"info-value"},aw={key:0,class:"info-card"},lw={class:"card-body"},cw={class:"branding-preview"},uw={key:0,class:"info-row"},dw={class:"info-value"},fw=["src"],hw={key:1,class:"info-card"},pw={class:"card-body"},gw={key:0,class:"info-row"},mw={class:"actions-section"};function vw(t,e,n,s,i,l){return b(),w("div",V0,[e[23]||(e[23]=o("div",{class:"page-header"},[o("div",{class:"header-content"},[o("h1",null,[o("i",{class:"fa fa-user-circle"}),L(" Minha Conta ")]),o("p",null,"Gerencie suas informações e configurações")])],-1)),t.error?(b(),w("div",j0,[e[4]||(e[4]=o("i",{class:"fa fa-exclamation-triangle"},null,-1)),o("span",null,A(t.error),1)])):U("",!0),t.loading?(b(),w("div",q0,[...e[5]||(e[5]=[o("div",{class:"spinner"},null,-1),o("p",null,"Carregando...",-1)])])):t.user?(b(),w("div",W0,[o("div",K0,[e[8]||(e[8]=o("div",{class:"card-header"},[o("i",{class:"fa fa-id-card"}),o("h2",null,"Informações do Usuário")],-1)),o("div",G0,[o("div",Q0,[e[6]||(e[6]=o("span",{class:"info-label"},"Email/Usuário:",-1)),o("span",J0,A(t.user.username),1)]),o("div",X0,[e[7]||(e[7]=o("span",{class:"info-label"},"Nível:",-1)),o("span",Y0,[o("span",{class:ae(["badge",t.user.level==="admin"?"badge-admin":"badge-user"])},A(t.user.level||"user"),3)])])])]),o("div",Z0,[e[12]||(e[12]=o("div",{class:"card-header"},[o("i",{class:"fa fa-cog"}),o("h2",null,"Informações do Sistema")],-1)),o("div",ew,[o("div",tw,[e[9]||(e[9]=o("span",{class:"info-label"},"Versão:",-1)),o("span",nw,[o("code",null,A(t.version),1)])]),t.branding?(b(),w("div",sw,[e[10]||(e[10]=o("span",{class:"info-label"},"Título da Aplicação:",-1)),o("span",ow,A(t.branding.title||"QuePasa"),1)])):U("",!0),o("div",iw,[e[11]||(e[11]=o("span",{class:"info-label"},"View Mode:",-1)),o("span",rw,A(t.serversViewMode||"card"),1)])])]),t.branding?(b(),w("div",aw,[e[17]||(e[17]=o("div",{class:"card-header"},[o("i",{class:"fa fa-palette"}),o("h2",null,"Branding")],-1)),o("div",lw,[o("div",cw,[o("div",{class:"color-swatch",style:Sn({background:t.branding.primaryColor}),title:"Primary"},[...e[13]||(e[13]=[o("span",null,"Primary",-1)])],4),o("div",{class:"color-swatch",style:Sn({background:t.branding.secondaryColor}),title:"Secondary"},[...e[14]||(e[14]=[o("span",null,"Secondary",-1)])],4),o("div",{class:"color-swatch",style:Sn({background:t.branding.accentColor}),title:"Accent"},[...e[15]||(e[15]=[o("span",null,"Accent",-1)])],4)]),t.branding.logo?(b(),w("div",uw,[e[16]||(e[16]=o("span",{class:"info-label"},"Logo:",-1)),o("span",dw,[o("img",{src:t.branding.logo,alt:"Logo",class:"logo-preview"},null,8,fw)])])):U("",!0)])])):U("",!0),t.hasMasterKey?(b(),w("div",hw,[e[21]||(e[21]=o("div",{class:"card-header"},[o("i",{class:"fa fa-key"}),o("h2",null,"API Master Key")],-1)),o("div",pw,[e[20]||(e[20]=o("div",{class:"info-row"},[o("span",{class:"info-label"},"Status:"),o("span",{class:"info-value"},[o("span",{class:"badge badge-success"},"Configurada")])],-1)),t.masterKey?(b(),w("div",gw,[e[18]||(e[18]=o("span",{class:"info-label"},"Chave:",-1)),o("code",{class:"master-key",onClick:e[1]||(e[1]=(...r)=>t.copyMasterKey&&t.copyMasterKey(...r))},[L(A(t.showMasterKey?t.masterKey:"••••••••••••••••")+" ",1),o("button",{class:"toggle-btn",onClick:e[0]||(e[0]=kt(r=>t.showMasterKey=!t.showMasterKey,["stop"]))},[o("i",{class:ae(t.showMasterKey?"fa fa-eye-slash":"fa fa-eye")},null,2)])])])):U("",!0),t.masterKey?U("",!0):(b(),w("button",{key:1,class:"btn-secondary",onClick:e[2]||(e[2]=(...r)=>t.loadMasterKey&&t.loadMasterKey(...r))},[...e[19]||(e[19]=[o("i",{class:"fa fa-download"},null,-1),L(" Carregar Master Key ",-1)])]))])])):U("",!0),o("div",mw,[o("button",{class:"btn-primary",onClick:e[3]||(e[3]=(...r)=>t.reload&&t.reload(...r))},[...e[22]||(e[22]=[o("i",{class:"fa fa-sync-alt"},null,-1),L(" Recarregar ",-1)])])])])):U("",!0)])}const bw=It(U0,[["render",vw],["__scopeId","data-v-4be79a22"]]),yw=$t({setup(){const t=O(""),e=O(""),n=O(""),s=O(!1),i=ti(),l=ns(),r=il(),c=O({});cn(async()=>{var h,f;try{const g=await be.get("/api/login/config");c.value=g.data||{};const C=((h=c.value.branding)==null?void 0:h.title)||c.value.appTitle||"QuePasa";if(document.title=C,c.value.branding){const _=document.documentElement;_.style.setProperty("--branding-primary",c.value.branding.primaryColor||"#7C3AED"),_.style.setProperty("--branding-secondary",c.value.branding.secondaryColor||"#5B21B6"),_.style.setProperty("--branding-accent",c.value.branding.accentColor||"#8B5CF6")}if((f=c.value.branding)!=null&&f.favicon){const _=document.querySelector('link[rel="icon"]');if(_)_.href=c.value.branding.favicon;else{const y=document.createElement("link");y.rel="icon",y.href=c.value.branding.favicon,document.head.appendChild(y)}}if(c.value.fontAwesome){const _=document.createElement("link");_.rel="stylesheet",_.href=c.value.fontAwesome,document.head.appendChild(_)}if(c.value.googleFonts){const _=document.createElement("link");_.rel="stylesheet",_.href=c.value.googleFonts,document.head.appendChild(_)}if(c.value.customCss){const _=document.createElement("link");_.rel="stylesheet",_.href=c.value.customCss,document.head.appendChild(_)}}catch{}});async function u(){var h,f;s.value=!0,n.value="";try{const g=new URLSearchParams;g.append("email",t.value),g.append("password",e.value),await be.post("/login",g),await r.loadSession();const C=l.query.redirect||"/";i.push(C)}catch(g){n.value=((f=(h=g==null?void 0:g.response)==null?void 0:h.data)==null?void 0:f.result)||g.message||"Falha no login"}finally{s.value=!1}}return{email:t,password:e,submit:u,error:n,loading:s,config:c}}}),ww={class:"login-wrapper"},_w={class:"login-container"},Cw={class:"login-card"},kw={class:"login-header"},Sw={key:0,class:"login-logo-wrapper"},Ew=["src"],$w={key:1,class:"login-logo-placeholder"},Tw={class:"login-title"},Aw={key:2,class:"login-subtitle"},Rw={key:3,class:"login-subtitle"},Pw={key:0,class:"login-warning"},Iw={key:0,class:"login-error"},Ow={class:"form-group"},Mw={class:"input-wrapper"},Dw={class:"form-group"},Lw={class:"input-wrapper"},Nw=["disabled"],Fw={key:0,class:"spinner"},xw={key:1},Bw={key:1,class:"setup-link"},zw={key:2,class:"login-footer"},Hw={key:3,class:"login-footer"},Uw={class:"login-info"},Vw={class:"info-content"};function jw(t,e,n,s,i,l){var c,u,h,f,g;const r=zt("router-link");return b(),w("div",ww,[e[12]||(e[12]=o("div",{class:"login-bg"},[o("div",{class:"login-bg-shape shape-1"}),o("div",{class:"login-bg-shape shape-2"}),o("div",{class:"login-bg-shape shape-3"})],-1)),o("div",_w,[o("div",Cw,[o("div",kw,[(c=t.config.branding)!=null&&c.logo||t.config.loginLogo?(b(),w("div",Sw,[o("img",{src:((u=t.config.branding)==null?void 0:u.logo)||t.config.loginLogo,alt:"Logo",class:"login-logo"},null,8,Ew)])):(b(),w("div",$w,[...e[3]||(e[3]=[o("svg",{viewBox:"0 0 24 24",width:"48",height:"48",fill:"currentColor"},[o("path",{d:"M12.04 2c-5.46 0-9.91 4.45-9.91 9.91 0 1.75.46 3.45 1.32 4.95L2.05 22l5.25-1.38c1.45.79 3.08 1.21 4.74 1.21 5.46 0 9.91-4.45 9.91-9.91 0-2.65-1.03-5.14-2.9-7.01A9.816 9.816 0 0012.04 2zm.01 1.67c2.2 0 4.26.86 5.82 2.42a8.225 8.225 0 012.41 5.83c0 4.54-3.7 8.23-8.24 8.23-1.48 0-2.93-.39-4.19-1.15l-.3-.17-3.12.82.83-3.04-.2-.32a8.188 8.188 0 01-1.26-4.38c.01-4.54 3.7-8.24 8.25-8.24zM8.53 7.33c-.16 0-.43.06-.66.31-.22.25-.87.86-.87 2.07 0 1.22.89 2.39 1 2.56.14.17 1.76 2.67 4.25 3.73.59.27 1.05.42 1.41.53.59.19 1.13.16 1.56.1.48-.07 1.46-.6 1.67-1.18.21-.58.21-1.07.15-1.18-.07-.1-.23-.16-.48-.27-.25-.14-1.47-.74-1.69-.82-.23-.08-.37-.12-.56.12-.16.25-.64.81-.78.97-.15.17-.29.19-.53.07-.26-.13-1.06-.39-2-1.23-.74-.66-1.23-1.47-1.38-1.72-.12-.24-.01-.39.11-.5.11-.11.27-.29.37-.44.13-.14.17-.25.25-.41.08-.17.04-.31-.02-.43-.06-.11-.56-1.35-.77-1.84-.2-.48-.4-.42-.56-.43-.14 0-.3-.01-.47-.01z"})],-1)])])),o("h1",Tw,A(((h=t.config.branding)==null?void 0:h.title)||t.config.appTitle||"QuePasa"),1),t.config.loginSubtitle?(b(),w("p",Aw,A(t.config.loginSubtitle),1)):(b(),w("p",Rw,"Sistema de Gerenciamento WhatsApp"))]),t.config.loginWarning?(b(),w("div",Pw,[e[4]||(e[4]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"})],-1)),o("span",null,A(t.config.loginWarning),1)])):U("",!0),o("form",{onSubmit:e[2]||(e[2]=kt((...C)=>t.submit&&t.submit(...C),["prevent"])),class:"login-form"},[t.error?(b(),w("div",Iw,[e[5]||(e[5]=o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)),o("span",null,A(t.error),1)])):U("",!0),o("div",Ow,[e[7]||(e[7]=o("label",{for:"email"},"Email",-1)),o("div",Mw,[e[6]||(e[6]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor",class:"input-icon"},[o("path",{d:"M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"})],-1)),Be(o("input",{id:"email","onUpdate:modelValue":e[0]||(e[0]=C=>t.email=C),type:"email",class:"form-input",placeholder:"seu@email.com",autocomplete:"email",required:""},null,512),[[at,t.email]])])]),o("div",Dw,[e[9]||(e[9]=o("label",{for:"password"},"Senha",-1)),o("div",Lw,[e[8]||(e[8]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor",class:"input-icon"},[o("path",{d:"M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"})],-1)),Be(o("input",{id:"password","onUpdate:modelValue":e[1]||(e[1]=C=>t.password=C),type:"password",class:"form-input",placeholder:"••••••••",autocomplete:"current-password",required:""},null,512),[[at,t.password]])])]),o("button",{type:"submit",class:"login-button",disabled:t.loading},[t.loading?(b(),w("span",Fw)):(b(),w("span",xw,"Entrar"))],8,Nw)],32),t.config.accountSetup?(b(),w("div",Bw,[ke(r,{to:"/setup",class:"setup-link-text"},{default:Ze(()=>[...e[10]||(e[10]=[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M19.14 12.94c.04-.31.06-.63.06-.94 0-.31-.02-.63-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"})],-1),L(" Criar conta ",-1)])]),_:1})])):U("",!0),t.config.loginFooter?(b(),w("div",zw,A(t.config.loginFooter),1)):(b(),w("div",Hw,[o("span",null,"Powered by "+A(((f=t.config.branding)==null?void 0:f.title)||"QuePasa"),1)]))]),o("div",Uw,[o("div",Vw,[o("h2",null,"Bem-vindo ao "+A(((g=t.config.branding)==null?void 0:g.title)||"QuePasa"),1),e[11]||(e[11]=Cn('

Plataforma completa para gerenciamento de bots WhatsApp com suporte a múltiplas conexões, webhooks e integrações.

Conexão Segura
Multi-Servidor
Webhooks
',2))])])])])}const qw=It(yw,[["render",jw],["__scopeId","data-v-d8fc6c09"]]),Ww=$t({props:{show:{type:Boolean,required:!0},title:{type:String,default:"Confirm"},message:{type:String,default:""},confirmLabel:{type:String,default:"Confirm"},cancelLabel:{type:String,default:"Cancel"}},emits:["confirm","cancel"]}),Kw={key:0},Gw={class:"modal d-block",tabindex:"-1",role:"dialog"},Qw={class:"modal-dialog",role:"document"},Jw={class:"modal-content"},Xw={class:"modal-header"},Yw={class:"modal-title"},Zw={class:"modal-body"},e_={class:"modal-footer"};function t_(t,e,n,s,i,l){return t.show?(b(),w("div",Kw,[e[3]||(e[3]=o("div",{class:"modal-backdrop fade show"},null,-1)),o("div",Gw,[o("div",Qw,[o("div",Jw,[o("div",Xw,[o("h5",Yw,A(t.title),1),o("button",{type:"button",class:"btn-close","aria-label":"Close",onClick:e[0]||(e[0]=r=>t.$emit("cancel"))})]),o("div",Zw,[a1(t.$slots,"default",{},()=>[L(A(t.message),1)])]),o("div",e_,[o("button",{type:"button",class:"btn btn-secondary",onClick:e[1]||(e[1]=r=>t.$emit("cancel"))},A(t.cancelLabel),1),o("button",{type:"button",class:"btn btn-danger",onClick:e[2]||(e[2]=r=>t.$emit("confirm"))},A(t.confirmLabel),1)])])])])])):U("",!0)}const Wf=It(Ww,[["render",t_]]),n_=$t({name:"TriStateToggle",props:{modelValue:{type:Number,required:!0,validator:t=>[-1,0,1].includes(t)},disabled:{type:Boolean,default:!1}},emits:["update:modelValue","change"],setup(t,{emit:e}){const n=Ye(()=>t.disabled?"disabled":t.modelValue===-1?"state-off":t.modelValue===1?"state-on":"state-unset");function s(i){t.disabled||(e("update:modelValue",i),e("change",i))}return{setValue:s,stateClass:n}}}),s_=["disabled"],o_=["disabled"],i_=["disabled"],r_=["disabled"];function a_(t,e,n,s,i,l){return b(),w("div",{class:ae(["tri-state-toggle",t.stateClass]),disabled:t.disabled},[o("button",{class:ae(["tri-btn off",{active:t.modelValue===-1}]),onClick:e[0]||(e[0]=r=>t.setValue(-1)),disabled:t.disabled,title:"OFF (forçado)"},[...e[3]||(e[3]=[o("i",{class:"fa fa-times"},null,-1)])],10,o_),o("button",{class:ae(["tri-btn default",{active:t.modelValue===0}]),onClick:e[1]||(e[1]=r=>t.setValue(0)),disabled:t.disabled,title:"Padrão do sistema"},[...e[4]||(e[4]=[o("i",{class:"fa fa-minus"},null,-1)])],10,i_),o("button",{class:ae(["tri-btn on",{active:t.modelValue===1}]),onClick:e[2]||(e[2]=r=>t.setValue(1)),disabled:t.disabled,title:"ON (forçado)"},[...e[5]||(e[5]=[o("i",{class:"fa fa-check"},null,-1)])],10,r_)],10,s_)}const Kf=It(n_,[["render",a_],["__scopeId","data-v-83eb2759"]]),l_=$t({components:{ConfirmModal:Wf,TriStateToggle:Kf},setup(){const t=O(null),e=O(""),n=O(!0),s=O(!1),i=ns(),l=O(!0);function r(te){return te?te.length<=16?te:te.substring(0,8)+"..."+te.substring(te.length-4):""}function c(te){return te===1||te===!0?"state-on":te===-1||te===!1?"state-off":"state-unset"}function u(te){if(!te)return"";if(typeof te=="string")return te;try{return JSON.stringify(te,null,2)}catch{return String(te)}}function h(te){return te===1||te===!0?1:te===-1||te===!1?-1:0}async function f(){var te,Le;try{n.value=!0,e.value="";const Y=i.query.token||"";if(!Y){l.value=!1,n.value=!1;return}l.value=!0;const oe=await be.get("/api/webhooks",{params:{token:Y}});t.value=oe.data}catch(Y){e.value=((Le=(te=Y==null?void 0:Y.response)==null?void 0:te.data)==null?void 0:Le.result)||Y.message||"Erro ao carregar webhooks"}finally{n.value=!1}}const g=O(""),C=O(""),_=O(!1),y=O(!0),P=O(!0),I=O(!1),H=O(!1),W=O("");async function G(){var te,Le,Y,oe;if(g.value){s.value=!0;try{const Q=i.query.token||((Le=(te=t.value)==null?void 0:te.server)==null?void 0:Le.token)||"";if(!Q)throw new Error("Token não encontrado");let Re=null;W.value&&(Re=JSON.parse(W.value)),await be.post("/api/webhooks",{token:Q,url:g.value,trackId:C.value,forwardInternal:_.value,broadcasts:y.value,groups:P.value,readReceipts:I.value,calls:H.value,extra:Re}),await f(),g.value="",C.value="",_.value=!1,y.value=!0,P.value=!0,I.value=!1,H.value=!1,W.value="",we("Webhook criado com sucesso","success")}catch(Q){const Re=((oe=(Y=Q==null?void 0:Q.response)==null?void 0:Y.data)==null?void 0:oe.result)||Q.message||"Erro ao criar webhook";e.value=Re,we(Re,"error")}finally{s.value=!1}}}const F=O(!1),ne=O("");function he(te){ne.value=te,F.value=!0}async function ce(){var te,Le,Y,oe;try{const Q=i.query.token||((Le=(te=t.value)==null?void 0:te.server)==null?void 0:Le.token)||"";if(!Q)throw new Error("Token não encontrado");await be.delete("/api/webhooks",{params:{token:Q},data:{url:ne.value}}),F.value=!1,ne.value="",await f(),we("Webhook removido","success")}catch(Q){const Re=((oe=(Y=Q==null?void 0:Q.response)==null?void 0:Y.data)==null?void 0:oe.result)||Q.message||"Erro ao remover";e.value=Re,we(Re,"error")}}async function Ee(te,Le){var Y,oe,Q,Re;try{const He=i.query.token||((oe=(Y=t.value)==null?void 0:Y.server)==null?void 0:oe.token)||"";if(!He)throw new Error("Token não encontrado");await be.post("/api/toggle",{token:He,key:Le,url:te}),await f()}catch(He){const z=((Re=(Q=He==null?void 0:He.response)==null?void 0:Q.data)==null?void 0:Re.result)||He.message||"Erro ao alternar";we(z,"error")}}const Se=O(!1),_e=O(!1),ye=Xt({originalUrl:"",url:"",trackId:"",extraStr:"",forwardInternal:!1,broadcasts:0,groups:0,readReceipts:0,calls:0});function Me(te){if(ye.originalUrl=te.url||"",ye.url=te.url||"",ye.trackId=te.trackid||"",ye.forwardInternal=te.forwardinternal||!1,ye.broadcasts=h(te.broadcasts),ye.groups=h(te.groups),ye.readReceipts=h(te.readreceipts),ye.calls=h(te.calls),te.extra)try{ye.extraStr=typeof te.extra=="string"?te.extra:JSON.stringify(te.extra,null,2)}catch{ye.extraStr=""}else ye.extraStr="";Se.value=!0}async function ve(){var te,Le,Y,oe;_e.value=!0;try{const Q=i.query.token||((Le=(te=t.value)==null?void 0:te.server)==null?void 0:Le.token)||"";if(!Q)throw new Error("Token não encontrado");let Re=null;if(ye.extraStr.trim())try{Re=JSON.parse(ye.extraStr)}catch{we("Extra deve ser um JSON válido","error"),_e.value=!1;return}await be.put("/api/webhooks",{token:Q,originalUrl:ye.originalUrl,url:ye.url,trackId:ye.trackId,forwardInternal:ye.forwardInternal,broadcasts:ye.broadcasts,groups:ye.groups,readReceipts:ye.readReceipts,calls:ye.calls,extra:Re}),Se.value=!1,await f(),we("Webhook atualizado com sucesso","success")}catch(Q){const Re=((oe=(Y=Q==null?void 0:Q.response)==null?void 0:Y.data)==null?void 0:oe.result)||Q.message||"Erro ao atualizar webhook";we(Re,"error")}finally{_e.value=!1}}return cn(()=>{f()}),{data:t,error:e,loading:n,creating:s,newUrl:g,newTrackId:C,newForwardInternal:_,newBroadcasts:y,newGroups:P,newReadReceipts:I,newCalls:H,newExtra:W,createWebhook:G,showConfirm:F,confirmDelete:he,doDeleteWebhook:ce,toggleWebhookFlag:Ee,truncateToken:r,hasToken:l,getTriStateClass:c,formatExtra:u,showEditModal:Se,saving:_e,editData:ye,startEdit:Me,saveEdit:ve}}}),c_={class:"webhooks-page"},u_={class:"page-header"},d_={class:"header-content"},f_={key:0},h_={key:1},p_={key:2},g_={key:0,class:"error-box"},m_={key:1,class:"no-token-warning"},v_={key:2,class:"loading-state"},b_={key:3,class:"webhooks-content"},y_={class:"add-card"},w_={class:"card-body"},__={class:"form-row"},C_={class:"form-group flex-grow"},k_={class:"form-group"},S_={class:"form-row options-row"},E_={class:"checkbox-label"},$_={class:"checkbox-label"},T_={class:"checkbox-label"},A_={class:"checkbox-label"},R_={class:"checkbox-label"},P_=["disabled"],I_={key:0,class:"fa fa-spinner fa-spin"},O_={key:1,class:"fa fa-plus"},M_={class:"list-card"},D_={class:"card-header"},L_={class:"count-badge"},N_={class:"card-body"},F_={key:0,class:"empty-state"},x_={key:1,class:"webhook-list"},B_={class:"item-header"},z_={class:"item-info"},H_={class:"item-main"},U_={class:"webhook-url"},V_={key:0,class:"track-id"},j_={class:"item-status"},q_={class:"item-actions"},W_=["onClick"],K_=["onClick"],G_={key:0,class:"item-extra"},Q_={class:"extra-value"},J_={class:"item-flags"},X_=["onClick"],Y_=["onClick"],Z_=["onClick"],e4=["onClick"],t4=["onClick"],n4={class:"modal-content edit-modal"},s4={class:"modal-header"},o4={class:"modal-body"},i4={class:"form-group"},r4={class:"form-group"},a4={class:"form-group"},l4={class:"form-group"},c4={class:"checkbox-label"},u4={class:"form-group options-grid"},d4={class:"option-item"},f4={class:"option-item"},h4={class:"option-item"},p4={class:"option-item"},g4={class:"modal-actions"},m4=["disabled"],v4={key:0,class:"fa fa-spinner fa-spin"},b4={key:1,class:"fa fa-save"};function y4(t,e,n,s,i,l){var h,f,g,C,_;const r=zt("router-link"),c=zt("ConfirmModal"),u=zt("TriStateToggle");return b(),w("div",c_,[o("div",u_,[o("button",{onClick:e[0]||(e[0]=y=>t.$router.back()),class:"back-link hide-mobile"},[...e[22]||(e[22]=[o("i",{class:"fa fa-arrow-left"},null,-1),L(" Voltar ",-1)])]),o("div",d_,[e[23]||(e[23]=o("h1",null,[o("i",{class:"fa fa-globe"}),L(" Webhooks ")],-1)),(f=(h=t.data)==null?void 0:h.server)!=null&&f.wid?(b(),w("p",f_,"Servidor: "+A(t.data.server.wid),1)):(C=(g=t.data)==null?void 0:g.server)!=null&&C.token?(b(),w("p",h_,"Token: "+A(t.truncateToken(t.data.server.token)),1)):(b(),w("p",p_,"Gerencie as integrações de webhook"))])]),t.error?(b(),w("div",g_,[e[24]||(e[24]=o("i",{class:"fa fa-exclamation-triangle"},null,-1)),o("span",null,A(t.error),1)])):!t.hasToken&&!t.loading?(b(),w("div",m_,[e[26]||(e[26]=o("div",{class:"warning-icon"},[o("i",{class:"fa fa-exclamation-circle"})],-1)),e[27]||(e[27]=o("h2",null,"Servidor não selecionado",-1)),e[28]||(e[28]=o("p",null,"Para gerenciar webhooks, acesse através de um servidor específico.",-1)),ke(r,{to:"/",class:"btn-primary"},{default:Ze(()=>[...e[25]||(e[25]=[o("i",{class:"fa fa-arrow-left"},null,-1),L(" Voltar para Servidores ",-1)])]),_:1})])):U("",!0),t.loading?(b(),w("div",v_,[...e[29]||(e[29]=[o("div",{class:"spinner"},null,-1),o("p",null,"Carregando...",-1)])])):t.data?(b(),w("div",b_,[o("div",y_,[e[37]||(e[37]=o("div",{class:"card-header"},[o("i",{class:"fa fa-plus-circle"}),o("h2",null,"Adicionar Webhook")],-1)),o("div",w_,[o("form",{onSubmit:e[8]||(e[8]=kt((...y)=>t.createWebhook&&t.createWebhook(...y),["prevent"])),class:"add-form"},[o("div",__,[o("div",C_,[e[30]||(e[30]=o("label",null,"URL do Webhook",-1)),Be(o("input",{"onUpdate:modelValue":e[1]||(e[1]=y=>t.newUrl=y),type:"url",class:"form-input",placeholder:"https://example.com/webhook",required:""},null,512),[[at,t.newUrl]])]),o("div",k_,[e[31]||(e[31]=o("label",null,"Track ID",-1)),Be(o("input",{"onUpdate:modelValue":e[2]||(e[2]=y=>t.newTrackId=y),type:"text",class:"form-input",placeholder:"Opcional"},null,512),[[at,t.newTrackId]])])]),o("div",S_,[o("label",E_,[Be(o("input",{type:"checkbox","onUpdate:modelValue":e[3]||(e[3]=y=>t.newForwardInternal=y)},null,512),[[_n,t.newForwardInternal]]),e[32]||(e[32]=o("span",null,"Forward Internal",-1))]),o("label",$_,[Be(o("input",{type:"checkbox","onUpdate:modelValue":e[4]||(e[4]=y=>t.newBroadcasts=y)},null,512),[[_n,t.newBroadcasts]]),e[33]||(e[33]=o("span",null,"Broadcasts",-1))]),o("label",T_,[Be(o("input",{type:"checkbox","onUpdate:modelValue":e[5]||(e[5]=y=>t.newGroups=y)},null,512),[[_n,t.newGroups]]),e[34]||(e[34]=o("span",null,"Grupos",-1))]),o("label",A_,[Be(o("input",{type:"checkbox","onUpdate:modelValue":e[6]||(e[6]=y=>t.newReadReceipts=y)},null,512),[[_n,t.newReadReceipts]]),e[35]||(e[35]=o("span",null,"Confirmações",-1))]),o("label",R_,[Be(o("input",{type:"checkbox","onUpdate:modelValue":e[7]||(e[7]=y=>t.newCalls=y)},null,512),[[_n,t.newCalls]]),e[36]||(e[36]=o("span",null,"Chamadas",-1))])]),o("button",{type:"submit",class:"btn-primary",disabled:!t.newUrl||t.creating},[t.creating?(b(),w("i",I_)):(b(),w("i",O_)),L(" "+A(t.creating?"Adicionando...":"Adicionar"),1)],8,P_)],32)])]),o("div",M_,[o("div",D_,[e[38]||(e[38]=o("i",{class:"fa fa-list"},null,-1)),e[39]||(e[39]=o("h2",null,"Webhooks Ativos",-1)),o("span",L_,A(((_=t.data.webhooks)==null?void 0:_.length)||0),1)]),o("div",N_,[!t.data.webhooks||t.data.webhooks.length===0?(b(),w("div",F_,[...e[40]||(e[40]=[o("i",{class:"fa fa-inbox"},null,-1),o("p",null,"Nenhum webhook configurado",-1)])])):(b(),w("div",x_,[(b(!0),w(Xe,null,Yt(t.data.webhooks,y=>(b(),w("div",{key:y.url,class:"webhook-item"},[o("div",B_,[o("div",z_,[o("div",H_,[o("strong",U_,A(y.url),1),y.trackid?(b(),w("span",V_,"Track: "+A(y.trackid),1)):U("",!0)]),o("div",j_,[o("span",{class:ae(["status-indicator",{success:!y.failure,error:y.failure}])},[o("i",{class:ae(y.failure?"fa fa-times-circle":"fa fa-check-circle")},null,2),L(" "+A(y.failure?"Falha":"OK"),1)],2)])]),o("div",q_,[o("button",{class:"btn-edit",onClick:P=>t.startEdit(y),title:"Editar"},[...e[41]||(e[41]=[o("i",{class:"fa fa-edit"},null,-1)])],8,W_),o("button",{class:"btn-delete",onClick:P=>t.confirmDelete(y.url),title:"Remover"},[...e[42]||(e[42]=[o("i",{class:"fa fa-trash"},null,-1)])],8,K_)])]),y.extra?(b(),w("div",G_,[e[43]||(e[43]=o("span",{class:"extra-label"},"Extra:",-1)),o("code",Q_,A(t.formatExtra(y.extra)),1)])):U("",!0),o("div",J_,[o("button",{class:ae(["flag-btn",t.getTriStateClass(y.forwardinternal?1:-1)]),onClick:P=>t.toggleWebhookFlag(y.url,"webhook-forwardinternal"),title:"Forward Internal"},[...e[44]||(e[44]=[o("i",{class:"fa fa-share"},null,-1)])],10,X_),o("button",{class:ae(["flag-btn",t.getTriStateClass(y.broadcasts)]),onClick:P=>t.toggleWebhookFlag(y.url,"webhook-broadcasts"),title:"Broadcasts"},[...e[45]||(e[45]=[o("i",{class:"fa fa-bullhorn"},null,-1)])],10,Y_),o("button",{class:ae(["flag-btn",t.getTriStateClass(y.groups)]),onClick:P=>t.toggleWebhookFlag(y.url,"webhook-groups"),title:"Grupos"},[...e[46]||(e[46]=[o("i",{class:"fa fa-users"},null,-1)])],10,Z_),o("button",{class:ae(["flag-btn",t.getTriStateClass(y.readreceipts)]),onClick:P=>t.toggleWebhookFlag(y.url,"webhook-readreceipts"),title:"Confirmações de Leitura"},[...e[47]||(e[47]=[o("i",{class:"fa fa-check-double"},null,-1)])],10,e4),o("button",{class:ae(["flag-btn",t.getTriStateClass(y.calls)]),onClick:P=>t.toggleWebhookFlag(y.url,"webhook-calls"),title:"Chamadas"},[...e[48]||(e[48]=[o("i",{class:"fa fa-phone"},null,-1)])],10,t4)])]))),128))]))])])])):U("",!0),ke(c,{show:t.showConfirm,title:"Remover Webhook",message:"Tem certeza que deseja remover este webhook?",onConfirm:t.doDeleteWebhook,onCancel:e[9]||(e[9]=y=>t.showConfirm=!1),confirmLabel:"Remover",cancelLabel:"Cancelar"},null,8,["show","onConfirm"]),t.showEditModal?(b(),w("div",{key:4,class:"modal-overlay",onClick:e[21]||(e[21]=kt(y=>t.showEditModal=!1,["self"]))},[o("div",n4,[o("div",s4,[e[50]||(e[50]=o("h3",null,[o("i",{class:"fa fa-edit"}),L(" Editar Webhook")],-1)),o("button",{class:"modal-close",onClick:e[10]||(e[10]=y=>t.showEditModal=!1)},[...e[49]||(e[49]=[o("i",{class:"fa fa-times"},null,-1)])])]),o("div",o4,[o("form",{onSubmit:e[20]||(e[20]=kt((...y)=>t.saveEdit&&t.saveEdit(...y),["prevent"]))},[o("div",i4,[e[51]||(e[51]=o("label",null,"URL do Webhook",-1)),Be(o("input",{"onUpdate:modelValue":e[11]||(e[11]=y=>t.editData.url=y),type:"url",class:"form-input",placeholder:"https://example.com/webhook",required:""},null,512),[[at,t.editData.url]])]),o("div",r4,[e[52]||(e[52]=o("label",null,"Track ID",-1)),Be(o("input",{"onUpdate:modelValue":e[12]||(e[12]=y=>t.editData.trackId=y),type:"text",class:"form-input",placeholder:"Identificador para evitar loop"},null,512),[[at,t.editData.trackId]])]),o("div",a4,[e[53]||(e[53]=o("label",null,"Extra (JSON)",-1)),Be(o("textarea",{"onUpdate:modelValue":e[13]||(e[13]=y=>t.editData.extraStr=y),class:"form-input extra-textarea",placeholder:'{"chave": "valor"}',rows:"4"},null,512),[[at,t.editData.extraStr]]),e[54]||(e[54]=o("small",{class:"form-hint"},"Dados JSON extras que serão enviados junto com o payload",-1))]),o("div",l4,[o("label",c4,[Be(o("input",{type:"checkbox","onUpdate:modelValue":e[14]||(e[14]=y=>t.editData.forwardInternal=y)},null,512),[[_n,t.editData.forwardInternal]]),e[55]||(e[55]=o("span",null,"Forward Internal",-1))])]),o("div",u4,[o("div",d4,[e[56]||(e[56]=o("label",null,"Broadcasts",-1)),ke(u,{modelValue:t.editData.broadcasts,"onUpdate:modelValue":e[15]||(e[15]=y=>t.editData.broadcasts=y)},null,8,["modelValue"])]),o("div",f4,[e[57]||(e[57]=o("label",null,"Grupos",-1)),ke(u,{modelValue:t.editData.groups,"onUpdate:modelValue":e[16]||(e[16]=y=>t.editData.groups=y)},null,8,["modelValue"])]),o("div",h4,[e[58]||(e[58]=o("label",null,"Confirmações",-1)),ke(u,{modelValue:t.editData.readReceipts,"onUpdate:modelValue":e[17]||(e[17]=y=>t.editData.readReceipts=y)},null,8,["modelValue"])]),o("div",p4,[e[59]||(e[59]=o("label",null,"Chamadas",-1)),ke(u,{modelValue:t.editData.calls,"onUpdate:modelValue":e[18]||(e[18]=y=>t.editData.calls=y)},null,8,["modelValue"])])]),o("div",g4,[o("button",{type:"button",class:"btn-secondary",onClick:e[19]||(e[19]=y=>t.showEditModal=!1)}," Cancelar "),o("button",{type:"submit",class:"btn-primary",disabled:t.saving},[t.saving?(b(),w("i",v4)):(b(),w("i",b4)),L(" "+A(t.saving?"Salvando...":"Salvar"),1)],8,m4)])],32)])])])):U("",!0)])}const Ju=It(l_,[["render",y4],["__scopeId","data-v-ba92e7b0"]]),w4=$t({components:{ConfirmModal:Wf},setup(){const t=O(null),e=O(""),n=O(!0),s=O(!1),i=ns(),l=O(!0);function r(F){return F?F.length<=16?F:F.substring(0,8)+"..."+F.substring(F.length-4):""}async function c(){var F,ne;try{n.value=!0,e.value="";const he=i.query.token||"";if(!he){l.value=!1,n.value=!1;return}l.value=!0;const ce=await be.get("/api/rabbitmq",{params:{token:he}});t.value=ce.data}catch(he){e.value=((ne=(F=he==null?void 0:he.response)==null?void 0:F.data)==null?void 0:ne.result)||he.message||"Erro ao carregar RabbitMQ"}finally{n.value=!1}}const u=O(""),h=O(""),f=O(!0),g=O(!0),C=O(!1),_=O("");async function y(){var F,ne,he,ce;if(u.value){s.value=!0;try{const Ee=i.query.token||((ne=(F=t.value)==null?void 0:F.server)==null?void 0:ne.Token)||"";if(!Ee)throw new Error("Token não encontrado");let Se=null;_.value&&(Se=JSON.parse(_.value)),await be.post("/api/rabbitmq",{token:Ee,connectionString:u.value,trackId:h.value,broadcasts:f.value,groups:g.value,readReceipts:C.value,extra:Se}),await c(),u.value="",h.value="",f.value=!0,g.value=!0,C.value=!1,_.value="",we("Configuração RabbitMQ criada","success")}catch(Ee){const Se=((ce=(he=Ee==null?void 0:Ee.response)==null?void 0:he.data)==null?void 0:ce.result)||Ee.message||"Erro ao criar RabbitMQ";e.value=Se,we(Se,"error")}finally{s.value=!1}}}const P=O(!1),I=O("");function H(F){I.value=F,P.value=!0}async function W(){var F,ne,he,ce;try{const Ee=i.query.token||((ne=(F=t.value)==null?void 0:F.server)==null?void 0:ne.Token)||"";if(!Ee)throw new Error("Token não encontrado");await be.delete("/api/rabbitmq",{params:{token:Ee},data:{connectionString:I.value}}),P.value=!1,I.value="",await c(),we("Configuração RabbitMQ removida","success")}catch(Ee){const Se=((ce=(he=Ee==null?void 0:Ee.response)==null?void 0:he.data)==null?void 0:ce.result)||Ee.message||"Erro ao remover";e.value=Se,we(Se,"error")}}async function G(F,ne){var he,ce,Ee,Se;try{const _e=i.query.token||((ce=(he=t.value)==null?void 0:he.server)==null?void 0:ce.Token)||"";if(!_e)throw new Error("Token não encontrado");await be.post("/api/toggle",{token:_e,key:ne,connectionString:F}),await c()}catch(_e){const ye=((Se=(Ee=_e==null?void 0:_e.response)==null?void 0:Ee.data)==null?void 0:Se.result)||_e.message||"Erro ao alternar";we(ye,"error")}}return cn(()=>{c()}),{data:t,error:e,loading:n,creating:s,hasToken:l,newConnectionString:u,newTrackId:h,newBroadcasts:f,newGroups:g,newReadReceipts:C,newExtra:_,createRabbit:y,showConfirm:P,confirmDelete:H,doDelete:W,toggleRabbitFlag:G,truncateToken:r}}}),_4={class:"rabbitmq-page"},C4={class:"page-header"},k4={class:"header-content"},S4={key:0},E4={key:1},$4={key:2},T4={key:0,class:"error-box"},A4={key:1,class:"no-token-warning"},R4={key:2,class:"loading-state"},P4={key:3,class:"rabbitmq-content"},I4={class:"add-card"},O4={class:"card-body"},M4={class:"form-row"},D4={class:"form-group flex-grow"},L4={class:"form-group"},N4={class:"form-row options-row"},F4={class:"checkbox-label"},x4={class:"checkbox-label"},B4={class:"checkbox-label"},z4=["disabled"],H4={key:0,class:"fa fa-spinner fa-spin"},U4={key:1,class:"fa fa-plus"},V4={class:"list-card"},j4={class:"card-header"},q4={class:"count-badge"},W4={class:"card-body"},K4={key:0,class:"empty-state"},G4={key:1,class:"rabbitmq-list"},Q4={class:"item-info"},J4={class:"item-main"},X4={class:"connection-string"},Y4={key:0,class:"track-id"},Z4={class:"item-meta"},eC={key:0},tC={key:1},nC={class:"item-flags"},sC=["onClick"],oC=["onClick"],iC=["onClick"],rC=["onClick"],aC=["onClick"],lC=["onClick"];function cC(t,e,n,s,i,l){var u,h,f,g,C;const r=zt("router-link"),c=zt("ConfirmModal");return b(),w("div",_4,[o("div",C4,[o("button",{onClick:e[0]||(e[0]=_=>t.$router.back()),class:"back-link hide-mobile"},[...e[8]||(e[8]=[o("i",{class:"fa fa-arrow-left"},null,-1),L(" Voltar ",-1)])]),o("div",k4,[e[9]||(e[9]=o("h1",null,[o("i",{class:"fa fa-server"}),L(" Configurações RabbitMQ ")],-1)),(h=(u=t.data)==null?void 0:u.server)!=null&&h.Wid?(b(),w("p",S4,"Servidor: "+A(t.data.server.Wid),1)):(g=(f=t.data)==null?void 0:f.server)!=null&&g.Token?(b(),w("p",E4,"Token: "+A(t.truncateToken(t.data.server.Token)),1)):(b(),w("p",$4,"Gerencie as integrações RabbitMQ"))])]),t.error?(b(),w("div",T4,[e[10]||(e[10]=o("i",{class:"fa fa-exclamation-triangle"},null,-1)),o("span",null,A(t.error),1)])):!t.hasToken&&!t.loading?(b(),w("div",A4,[e[12]||(e[12]=o("div",{class:"warning-icon"},[o("i",{class:"fa fa-exclamation-circle"})],-1)),e[13]||(e[13]=o("h2",null,"Servidor não selecionado",-1)),e[14]||(e[14]=o("p",null,"Para gerenciar RabbitMQ, acesse através de um servidor específico.",-1)),ke(r,{to:"/",class:"btn-primary"},{default:Ze(()=>[...e[11]||(e[11]=[o("i",{class:"fa fa-arrow-left"},null,-1),L(" Voltar para Servidores ",-1)])]),_:1})])):U("",!0),t.loading?(b(),w("div",R4,[...e[15]||(e[15]=[o("div",{class:"spinner"},null,-1),o("p",null,"Carregando...",-1)])])):t.data?(b(),w("div",P4,[o("div",I4,[e[21]||(e[21]=o("div",{class:"card-header"},[o("i",{class:"fa fa-plus-circle"}),o("h2",null,"Adicionar Configuração")],-1)),o("div",O4,[o("form",{onSubmit:e[6]||(e[6]=kt((..._)=>t.createRabbit&&t.createRabbit(..._),["prevent"])),class:"add-form"},[o("div",M4,[o("div",D4,[e[16]||(e[16]=o("label",null,"Connection String",-1)),Be(o("input",{"onUpdate:modelValue":e[1]||(e[1]=_=>t.newConnectionString=_),type:"text",class:"form-input",placeholder:"amqp://user:pass@host:5672/vhost",required:""},null,512),[[at,t.newConnectionString]])]),o("div",L4,[e[17]||(e[17]=o("label",null,"Track ID",-1)),Be(o("input",{"onUpdate:modelValue":e[2]||(e[2]=_=>t.newTrackId=_),type:"text",class:"form-input",placeholder:"Opcional"},null,512),[[at,t.newTrackId]])])]),o("div",N4,[o("label",F4,[Be(o("input",{type:"checkbox","onUpdate:modelValue":e[3]||(e[3]=_=>t.newBroadcasts=_)},null,512),[[_n,t.newBroadcasts]]),e[18]||(e[18]=o("span",null,"Broadcasts",-1))]),o("label",x4,[Be(o("input",{type:"checkbox","onUpdate:modelValue":e[4]||(e[4]=_=>t.newGroups=_)},null,512),[[_n,t.newGroups]]),e[19]||(e[19]=o("span",null,"Grupos",-1))]),o("label",B4,[Be(o("input",{type:"checkbox","onUpdate:modelValue":e[5]||(e[5]=_=>t.newReadReceipts=_)},null,512),[[_n,t.newReadReceipts]]),e[20]||(e[20]=o("span",null,"Confirmações",-1))])]),o("button",{type:"submit",class:"btn-primary",disabled:!t.newConnectionString||t.creating},[t.creating?(b(),w("i",H4)):(b(),w("i",U4)),L(" "+A(t.creating?"Adicionando...":"Adicionar"),1)],8,z4)],32)])]),o("div",V4,[o("div",j4,[e[22]||(e[22]=o("i",{class:"fa fa-list"},null,-1)),e[23]||(e[23]=o("h2",null,"Configurações Ativas",-1)),o("span",q4,A(((C=t.data.rabbitmq)==null?void 0:C.length)||0),1)]),o("div",W4,[!t.data.rabbitmq||t.data.rabbitmq.length===0?(b(),w("div",K4,[...e[24]||(e[24]=[o("i",{class:"fa fa-inbox"},null,-1),o("p",null,"Nenhuma configuração RabbitMQ",-1)])])):(b(),w("div",G4,[(b(!0),w(Xe,null,Yt(t.data.rabbitmq,_=>(b(),w("div",{key:_.ConnectionString,class:"rabbitmq-item"},[o("div",Q4,[o("div",J4,[o("strong",X4,A(_.ConnectionString),1),_.TrackId?(b(),w("span",Y4,"Track: "+A(_.TrackId),1)):U("",!0)]),o("div",Z4,[_.Exchange?(b(),w("span",eC,[e[25]||(e[25]=o("i",{class:"fa fa-exchange-alt"},null,-1)),L(" "+A(_.Exchange),1)])):U("",!0),_.Queue?(b(),w("span",tC,[e[26]||(e[26]=o("i",{class:"fa fa-stream"},null,-1)),L(" "+A(_.Queue),1)])):U("",!0)])]),o("div",nC,[o("button",{class:ae(["flag-btn",{active:_.ForwardInternal}]),onClick:y=>t.toggleRabbitFlag(_.ConnectionString,"rabbitmq-forwardinternal"),title:"Forward Internal"},[...e[27]||(e[27]=[o("i",{class:"fa fa-share"},null,-1)])],10,sC),o("button",{class:ae(["flag-btn",{active:_.Broadcasts}]),onClick:y=>t.toggleRabbitFlag(_.ConnectionString,"rabbitmq-broadcasts"),title:"Broadcasts"},[...e[28]||(e[28]=[o("i",{class:"fa fa-bullhorn"},null,-1)])],10,oC),o("button",{class:ae(["flag-btn",{active:_.Groups}]),onClick:y=>t.toggleRabbitFlag(_.ConnectionString,"rabbitmq-groups"),title:"Grupos"},[...e[29]||(e[29]=[o("i",{class:"fa fa-users"},null,-1)])],10,iC),o("button",{class:ae(["flag-btn",{active:_.ReadReceipts}]),onClick:y=>t.toggleRabbitFlag(_.ConnectionString,"rabbitmq-readreceipts"),title:"Confirmações de Leitura"},[...e[30]||(e[30]=[o("i",{class:"fa fa-check-double"},null,-1)])],10,rC),o("button",{class:ae(["flag-btn",{active:_.Calls}]),onClick:y=>t.toggleRabbitFlag(_.ConnectionString,"rabbitmq-calls"),title:"Chamadas"},[...e[31]||(e[31]=[o("i",{class:"fa fa-phone"},null,-1)])],10,aC)]),o("button",{class:"btn-delete",onClick:y=>t.confirmDelete(_.ConnectionString),title:"Remover"},[...e[32]||(e[32]=[o("i",{class:"fa fa-trash"},null,-1)])],8,lC)]))),128))]))])])])):U("",!0),ke(c,{show:t.showConfirm,title:"Remover Configuração",message:"Tem certeza que deseja remover esta configuração RabbitMQ?",onConfirm:t.doDelete,onCancel:e[7]||(e[7]=_=>t.showConfirm=!1),confirmLabel:"Remover",cancelLabel:"Cancelar"},null,8,["show","onConfirm"])])}const uC=It(w4,[["render",cC],["__scopeId","data-v-7f963124"]]),dC=$t({components:{TriStateToggle:Kf},setup(){const t=ns(),e=ti(),n=t.params.token,s=O(null),i=O(""),l=O(!1),r=O(""),c=O(!0),u=O(""),h=O(!1),f=O(!1),g=O(!1),C=O(!1),_=O(!1),y=O({broadcasts:0,groups:0,readreceipts:0,calls:0,historysync:""}),P=O(""),I=Ye(()=>window.location.origin+"/api"),H=Ye(()=>{var oe;const Y=((oe=i.value)==null?void 0:oe.toLowerCase())||"";return Y==="ready"?"connected":Y==="connecting"||Y==="starting"?"connecting":"disconnected"}),W=Ye(()=>l.value===!0),G=Ye(()=>{var oe;const Y=((oe=i.value)==null?void 0:oe.toLowerCase())||"";return Y!==""&&Y!=="stopped"&&Y!=="disabled"});async function F(){var Y,oe,Q,Re,He,z,Qe;c.value=!0,u.value="";try{const Ke=await be.get(`/api/server/${n}/info`);s.value=(Y=Ke.data)==null?void 0:Y.server,i.value=((oe=Ke.data)==null?void 0:oe.state)||"",l.value=((Q=Ke.data)==null?void 0:Q.connected)===!0,r.value=((Re=Ke.data)==null?void 0:Re.wid)||"",(He=Ke.data)!=null&&He.server&&(y.value.broadcasts=ce(Ke.data.server.broadcasts),y.value.groups=ce(Ke.data.server.groups),y.value.readreceipts=ce(Ke.data.server.readreceipts),y.value.calls=ce(Ke.data.server.calls),y.value.historysync=Ke.data.server.historysync==null?"":String(Ke.data.server.historysync))}catch(Ke){u.value=((Qe=(z=Ke==null?void 0:Ke.response)==null?void 0:z.data)==null?void 0:Qe.result)||Ke.message||"Erro ao carregar servidor"}finally{c.value=!1}}const ne=O(!1);async function he(){var Y,oe;ne.value=!0,u.value="";try{const Q={};y.value.historysync===""||y.value.historysync===null?Q.historysyncdays=null:Q.historysyncdays=Number(y.value.historysync),await be.post(`/api/server/${n}/update`,Q),await F()}catch(Q){u.value=((oe=(Y=Q==null?void 0:Q.response)==null?void 0:Y.data)==null?void 0:oe.result)||Q.message||"Erro ao salvar history sync"}finally{ne.value=!1}}function ce(Y){return Y===1||Y===!0?1:Y===-1||Y===!1?-1:0}async function Ee(Y,oe){var Q,Re;P.value=`server-${Y}`;try{const He={};He[Y]=oe,await be.post(`/api/server/${n}/update`,He),await F()}catch(He){u.value=((Re=(Q=He==null?void 0:He.response)==null?void 0:Q.data)==null?void 0:Re.result)||He.message||"Erro ao alterar opção",await F()}finally{P.value=""}}async function Se(Y){var oe,Q;P.value=Y;try{if(Y.startsWith("server-")){const He={"server-groups":"groups","server-broadcasts":"broadcasts","server-readreceipts":"readreceipts","server-calls":"calls","server-readupdate":"readupdate"}[Y];if(!He)throw new Error("invalid server option");await be.post("/api/command",{token:n,action:He})}else await be.post("/api/toggle",{token:n,key:Y});await F()}catch(Re){u.value=((Q=(oe=Re==null?void 0:Re.response)==null?void 0:oe.data)==null?void 0:Q.result)||Re.message||"Erro ao alterar opção",await F()}finally{P.value=""}}function _e(Y){if(!Y)return"";let oe=Y.split("@")[0];return oe=oe.split(":")[0],oe}async function ye(){try{await navigator.clipboard.writeText(n),h.value=!0,setTimeout(()=>h.value=!1,2e3)}catch{}}function Me(){f.value=!0}async function ve(){var Y,oe;g.value=!0;try{await be.post("/api/delete",{token:n}),e.push("/")}catch(Q){u.value=((oe=(Y=Q==null?void 0:Q.response)==null?void 0:Y.data)==null?void 0:oe.result)||Q.message||"Erro ao excluir servidor"}finally{g.value=!1,f.value=!1}}async function te(){var Y,oe;C.value=!0;try{await be.post(`/bot/${n}/disconnect`,{},{headers:{"X-QUEPASA-TOKEN":n}}),await F()}catch(Q){u.value=((oe=(Y=Q==null?void 0:Q.response)==null?void 0:Y.data)==null?void 0:oe.result)||Q.message||"Erro ao desconectar"}finally{C.value=!1}}async function Le(){var Y,oe;_.value=!0;try{const Q=G.value?"stop":"start";await be.post("/api/command",{token:n,action:Q}),await F()}catch(Q){u.value=((oe=(Y=Q==null?void 0:Q.response)==null?void 0:Y.data)==null?void 0:oe.result)||Q.message||"Erro ao alterar estado do servidor"}finally{_.value=!1}}return cn(()=>{F()}),{token:n,server:s,serverState:i,serverConnected:l,serverWid:r,loading:c,error:u,baseUrl:I,statusClass:H,isConnected:W,tokenCopied:h,copyToken:ye,showDeleteModal:f,confirmDelete:Me,deleteServer:ve,deleting:g,disconnect:te,disconnecting:C,options:y,togglingOption:P,toggleOption:Se,updateOption:Ee,toTriState:ce,isServerActive:G,togglingServer:_,toggleServer:Le,savingHistory:ne,saveHistorySync:he,formatWid:_e}}}),fC={class:"server-page"},hC={class:"server-header"},pC={class:"header-top"},gC={key:0,class:"loading-placeholder"},mC={key:1,class:"server-info"},vC={class:"server-details"},bC={class:"server-meta"},yC={key:2,class:"error-banner"},wC={key:0,class:"quick-actions"},_C={key:1,class:"quick-actions"},CC={key:2,class:"details-section"},kC={class:"details-grid"},SC={class:"detail-card"},EC={class:"detail-value token"},$C={key:0,viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},TC={key:1,viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},AC={class:"detail-card"},RC={class:"detail-value"},PC={class:"detail-card"},IC={class:"detail-value"},OC={key:3,class:"options-section"},MC={class:"options-list"},DC={class:"option-card history-sync-card"},LC={class:"history-sync-control"},NC={class:"history-input-group"},FC=["disabled"],xC={key:0,viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},BC={key:1,class:"spinner-tiny"},zC={class:"option-card"},HC={class:"option-card"},UC={class:"option-card"},VC={class:"option-card"},jC={key:4,class:"danger-section"},qC={class:"danger-actions"},WC=["disabled"],KC={key:0,viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},GC={key:1,viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},QC=["disabled"],JC=["disabled"],XC={class:"modal-content"},YC={class:"modal-actions"};function ZC(t,e,n,s,i,l){const r=zt("router-link"),c=zt("TriStateToggle");return b(),w("div",fC,[o("div",hC,[o("div",pC,[o("button",{onClick:e[0]||(e[0]=u=>t.$router.back()),class:"back-link hide-mobile"},[...e[18]||(e[18]=[o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"})],-1),L(" Voltar ",-1)])])]),t.loading?(b(),w("div",gC,[...e[19]||(e[19]=[o("div",{class:"spinner"},null,-1),o("span",null,"Carregando servidor...",-1)])])):t.server?(b(),w("div",mC,[o("div",{class:ae(["server-avatar",t.statusClass])},[...e[20]||(e[20]=[o("svg",{viewBox:"0 0 24 24",width:"40",height:"40",fill:"currentColor"},[o("path",{d:"M12.04 2c-5.46 0-9.91 4.45-9.91 9.91 0 1.75.46 3.45 1.32 4.95L2.05 22l5.25-1.38c1.45.79 3.08 1.21 4.74 1.21 5.46 0 9.91-4.45 9.91-9.91 0-2.65-1.03-5.14-2.9-7.01A9.816 9.816 0 0012.04 2z"})],-1)])],2),o("div",vC,[o("h1",null,A(t.formatWid(t.serverWid)||t.formatWid(t.server.wid)||"Não conectado"),1),o("div",bC,[e[21]||(e[21]=L(" Status ",-1)),o("span",{class:ae(["status-badge",t.statusClass])},A(t.serverState||"Desconhecido"),3)])])])):U("",!0),t.error?(b(),w("div",yC,[e[22]||(e[22]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)),o("span",null,A(t.error),1)])):U("",!0)]),t.server?(b(),w("div",wC,[ke(r,{to:`/server/${t.token}/qrcode`,class:ae(["action-card",{disabled:t.isConnected}])},{default:Ze(()=>[...e[23]||(e[23]=[o("div",{class:"action-icon"},[o("svg",{viewBox:"0 0 24 24",width:"28",height:"28",fill:"currentColor"},[o("path",{d:"M3 11h8V3H3v8zm2-6h4v4H5V5zM3 21h8v-8H3v8zm2-6h4v4H5v-4zm8-12v8h8V3h-8zm6 6h-4V5h4v4zm-6 4h2v2h-2zm2 2h2v2h-2zm-2 2h2v2h-2zm4 0h2v2h-2zm2 2h2v2h-2zm0-4h2v2h-2zm2-2h2v2h-2z"})])],-1),o("div",{class:"action-info"},[o("span",{class:"action-title"},"QR Code"),o("span",{class:"action-desc"},"Conectar via QR Code")],-1)])]),_:1},8,["to","class"]),ke(r,{to:`/server/${t.token}/paircode`,class:ae(["action-card",{disabled:t.isConnected}])},{default:Ze(()=>[...e[24]||(e[24]=[o("div",{class:"action-icon"},[o("svg",{viewBox:"0 0 24 24",width:"28",height:"28",fill:"currentColor"},[o("path",{d:"M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"})])],-1),o("div",{class:"action-info"},[o("span",{class:"action-title"},"Código de Pareamento"),o("span",{class:"action-desc"},"Conectar com código numérico")],-1)])]),_:1},8,["to","class"])])):U("",!0),t.server?(b(),w("div",_C,[ke(r,{to:`/server/${t.token}/send`,class:"action-card primary"},{default:Ze(()=>[...e[25]||(e[25]=[o("div",{class:"action-icon"},[o("svg",{viewBox:"0 0 24 24",width:"28",height:"28",fill:"currentColor"},[o("path",{d:"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"})])],-1),o("div",{class:"action-info"},[o("span",{class:"action-title"},"Enviar Mensagem"),o("span",{class:"action-desc"},"Envie texto, imagens e documentos")],-1)])]),_:1},8,["to"]),ke(r,{to:`/server/${t.token}/messages`,class:"action-card"},{default:Ze(()=>[...e[26]||(e[26]=[o("div",{class:"action-icon"},[o("svg",{viewBox:"0 0 24 24",width:"28",height:"28",fill:"currentColor"},[o("path",{d:"M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"})])],-1),o("div",{class:"action-info"},[o("span",{class:"action-title"},"Mensagens"),o("span",{class:"action-desc"},"Ver mensagens recebidas")],-1)])]),_:1},8,["to"]),ke(r,{to:`/server/${t.token}/groups`,class:"action-card"},{default:Ze(()=>[...e[27]||(e[27]=[o("div",{class:"action-icon"},[o("svg",{viewBox:"0 0 24 24",width:"28",height:"28",fill:"currentColor"},[o("path",{d:"M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"})])],-1),o("div",{class:"action-info"},[o("span",{class:"action-title"},"Grupos"),o("span",{class:"action-desc"},"Ver e gerenciar grupos")],-1)])]),_:1},8,["to"])])):U("",!0),t.server?(b(),w("div",CC,[e[33]||(e[33]=o("h2",null,[o("svg",{viewBox:"0 0 24 24",width:"22",height:"22",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"})]),L(" Informações do Servidor ")],-1)),o("div",kC,[o("div",SC,[e[30]||(e[30]=o("span",{class:"detail-label"},"Token",-1)),o("div",EC,[o("code",null,A(t.token),1),o("button",{onClick:e[1]||(e[1]=(...u)=>t.copyToken&&t.copyToken(...u)),class:ae(["copy-btn",{copied:t.tokenCopied}])},[t.tokenCopied?(b(),w("svg",TC,[...e[29]||(e[29]=[o("path",{d:"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"},null,-1)])])):(b(),w("svg",$C,[...e[28]||(e[28]=[o("path",{d:"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"},null,-1)])]))],2)])]),o("div",AC,[e[31]||(e[31]=o("span",{class:"detail-label"},"WhatsApp ID",-1)),o("span",RC,A(t.formatWid(t.serverWid)||t.formatWid(t.server.wid)||"—"),1)]),o("div",PC,[e[32]||(e[32]=o("span",{class:"detail-label"},"Reconectar",-1)),o("span",IC,A(t.server.reconnect?"Sim":"Não"),1)])])])):U("",!0),t.server?(b(),w("div",OC,[e[41]||(e[41]=o("h2",null,[o("svg",{viewBox:"0 0 24 24",width:"22",height:"22",fill:"currentColor"},[o("path",{d:"M19.14 12.94c.04-.31.06-.63.06-.94 0-.31-.02-.63-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"})]),L(" Opções do Servidor ")],-1)),o("div",MC,[o("div",DC,[e[36]||(e[36]=Cn('
Sincronização de Histórico

Número de dias de histórico a sincronizar no primeiro pareamento.

',1)),o("div",LC,[o("div",NC,[Be(o("input",{type:"number",min:"0",max:"365","onUpdate:modelValue":e[2]||(e[2]=u=>t.options.historysync=u),class:"history-input",placeholder:"0"},null,512),[[at,t.options.historysync]]),e[34]||(e[34]=o("span",{class:"history-input-suffix"},"dias",-1))]),o("button",{class:"btn-save",onClick:e[3]||(e[3]=(...u)=>t.saveHistorySync&&t.saveHistorySync(...u)),disabled:t.savingHistory},[t.savingHistory?(b(),w("span",BC)):(b(),w("svg",xC,[...e[35]||(e[35]=[o("path",{d:"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"},null,-1)])]))],8,FC)])]),o("div",zC,[e[37]||(e[37]=Cn('
Mensagens de Broadcast

Receber mensagens enviadas para listas de transmissão. Quando ativo, mensagens de broadcast aparecem no webhook.

',1)),ke(c,{modelValue:t.options.broadcasts,"onUpdate:modelValue":e[4]||(e[4]=u=>t.options.broadcasts=u),onChange:e[5]||(e[5]=u=>t.updateOption("broadcasts",u)),disabled:t.togglingOption==="server-broadcasts"},null,8,["modelValue","disabled"])]),o("div",HC,[e[38]||(e[38]=Cn('
Mensagens de Grupos

Receber mensagens de grupos. Quando ativo, todas as mensagens de grupos serão entregues via webhook.

',1)),ke(c,{modelValue:t.options.groups,"onUpdate:modelValue":e[6]||(e[6]=u=>t.options.groups=u),onChange:e[7]||(e[7]=u=>t.updateOption("groups",u)),disabled:t.togglingOption==="server-groups"},null,8,["modelValue","disabled"])]),o("div",UC,[e[39]||(e[39]=Cn('
Confirmação de Leitura

Enviar confirmação de leitura automaticamente. Quando ativo, o "visto azul" é enviado ao receber mensagens.

',1)),ke(c,{modelValue:t.options.readreceipts,"onUpdate:modelValue":e[8]||(e[8]=u=>t.options.readreceipts=u),onChange:e[9]||(e[9]=u=>t.updateOption("readreceipts",u)),disabled:t.togglingOption==="server-readreceipts"},null,8,["modelValue","disabled"])]),o("div",VC,[e[40]||(e[40]=Cn('
Notificação de Chamadas

Receber notificações de chamadas via webhook. Quando ativo, você será notificado sobre chamadas recebidas.

',1)),ke(c,{modelValue:t.options.calls,"onUpdate:modelValue":e[10]||(e[10]=u=>t.options.calls=u),onChange:e[11]||(e[11]=u=>t.updateOption("calls",u)),disabled:t.togglingOption==="server-calls"},null,8,["modelValue","disabled"])])])])):U("",!0),t.server?(b(),w("div",jC,[e[46]||(e[46]=o("h2",null,[o("svg",{viewBox:"0 0 24 24",width:"22",height:"22",fill:"currentColor"},[o("path",{d:"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"})]),L(" Zona de Perigo ")],-1)),o("div",qC,[o("button",{onClick:e[12]||(e[12]=(...u)=>t.toggleServer&&t.toggleServer(...u)),class:"btn-warning-outline",disabled:t.togglingServer},[t.isServerActive?(b(),w("svg",KC,[...e[42]||(e[42]=[o("path",{d:"M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99 7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17 5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6.83z"},null,-1)])])):(b(),w("svg",GC,[...e[43]||(e[43]=[o("path",{d:"M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"},null,-1)])])),L(" "+A(t.togglingServer?"Processando...":t.isServerActive?"Desativar Servidor":"Ativar Servidor"),1)],8,WC),t.isConnected?(b(),w("button",{key:0,onClick:e[13]||(e[13]=(...u)=>t.disconnect&&t.disconnect(...u)),class:"btn-danger-outline",disabled:t.disconnecting},[e[44]||(e[44]=o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99 7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17 5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6.83z"})],-1)),L(" "+A(t.disconnecting?"Desconectando...":"Desconectar"),1)],8,QC)):U("",!0),o("button",{onClick:e[14]||(e[14]=(...u)=>t.confirmDelete&&t.confirmDelete(...u)),class:"btn-danger",disabled:t.deleting},[e[45]||(e[45]=o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"})],-1)),L(" "+A(t.deleting?"Excluindo...":"Excluir Servidor"),1)],8,JC)])])):U("",!0),t.showDeleteModal?(b(),w("div",{key:5,class:"modal-overlay",onClick:e[17]||(e[17]=kt(u=>t.showDeleteModal=!1,["self"]))},[o("div",XC,[e[47]||(e[47]=o("div",{class:"modal-icon danger"},[o("svg",{viewBox:"0 0 24 24",width:"48",height:"48",fill:"currentColor"},[o("path",{d:"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"})])],-1)),e[48]||(e[48]=o("h3",null,"Excluir Servidor?",-1)),e[49]||(e[49]=o("p",null,"Esta ação não pode ser desfeita. O servidor e todas as configurações serão removidos permanentemente.",-1)),o("div",YC,[o("button",{onClick:e[15]||(e[15]=u=>t.showDeleteModal=!1),class:"btn-secondary"},"Cancelar"),o("button",{onClick:e[16]||(e[16]=(...u)=>t.deleteServer&&t.deleteServer(...u)),class:"btn-danger"},"Excluir")])])])):U("",!0)])}const e3=It(dC,[["render",ZC],["__scopeId","data-v-0a139a54"]]),t3=$t({setup(){const t=O(""),e=O(""),n=O(""),s=O(!1),i=O(!1),l=O(""),r=O(""),c=O(""),u=Ye(()=>{const _=e.value;if(!_)return 0;let y=0;return _.length>=6&&(y+=25),_.length>=8&&(y+=25),/[A-Z]/.test(_)&&(y+=25),(/[0-9]/.test(_)||/[^A-Za-z0-9]/.test(_))&&(y+=25),y}),h=Ye(()=>u.value<50?"weak":u.value<75?"medium":"strong"),f=Ye(()=>t.value&&e.value&&e.value.length>=4&&e.value===n.value);async function g(){var _;try{const y=await be.get("/api/session");c.value=((_=y.data)==null?void 0:_.version)||""}catch{}}async function C(){var _,y;if(f.value){i.value=!0,l.value="",r.value="";try{await be.post("/api/user",{email:t.value,password:e.value}),r.value="Usuário criado com sucesso!",we("Usuário criado com sucesso!","success"),t.value="",e.value="",n.value=""}catch(P){const I=((y=(_=P==null?void 0:P.response)==null?void 0:_.data)==null?void 0:y.result)||P.message||"Erro ao criar usuário";l.value=I,we(I,"error")}finally{i.value=!1}}}return cn(()=>{g()}),{email:t,password:e,confirmPassword:n,showPassword:s,loading:i,error:l,success:r,version:c,passwordStrength:u,passwordStrengthClass:h,isFormValid:f,createUser:C}}}),n3={class:"setup-page"},s3={class:"setup-content"},o3={class:"setup-card"},i3={class:"card-body"},r3={key:0,class:"error-box"},a3={key:1,class:"success-box"},l3={class:"form-group"},c3={class:"form-group"},u3={class:"password-wrapper"},d3=["type"],f3={key:0,class:"password-strength"},h3={class:"form-group"},p3={key:0,class:"error-hint"},g3=["disabled"],m3={key:0,class:"fa fa-spinner fa-spin"},v3={key:1,class:"fa fa-user-plus"},b3={class:"setup-card"},y3={class:"card-body"},w3={class:"info-row"},_3={class:"info-value"};function C3(t,e,n,s,i,l){return b(),w("div",n3,[e[15]||(e[15]=o("div",{class:"page-header"},[o("div",{class:"header-content"},[o("h1",null,[o("i",{class:"fa fa-cog"}),L(" Configuração ")]),o("p",null,"Configure o sistema e crie usuários")])],-1)),o("div",s3,[o("div",o3,[e[11]||(e[11]=o("div",{class:"card-header"},[o("i",{class:"fa fa-user-plus"}),o("h2",null,"Criar Usuário")],-1)),o("div",i3,[o("form",{onSubmit:e[4]||(e[4]=kt((...r)=>t.createUser&&t.createUser(...r),["prevent"])),class:"setup-form"},[t.error?(b(),w("div",r3,[e[5]||(e[5]=o("i",{class:"fa fa-exclamation-triangle"},null,-1)),o("span",null,A(t.error),1)])):U("",!0),t.success?(b(),w("div",a3,[e[6]||(e[6]=o("i",{class:"fa fa-check-circle"},null,-1)),o("span",null,A(t.success),1)])):U("",!0),o("div",l3,[e[7]||(e[7]=o("label",{for:"email"},[o("i",{class:"fa fa-envelope"}),L(" Email ")],-1)),Be(o("input",{id:"email","onUpdate:modelValue":e[0]||(e[0]=r=>t.email=r),type:"email",class:"form-input",placeholder:"usuario@exemplo.com",required:""},null,512),[[at,t.email]])]),o("div",c3,[e[8]||(e[8]=o("label",{for:"password"},[o("i",{class:"fa fa-lock"}),L(" Senha ")],-1)),o("div",u3,[Be(o("input",{id:"password","onUpdate:modelValue":e[1]||(e[1]=r=>t.password=r),type:t.showPassword?"text":"password",class:"form-input",placeholder:"••••••••",required:""},null,8,d3),[[lf,t.password]]),o("button",{type:"button",class:"toggle-password",onClick:e[2]||(e[2]=r=>t.showPassword=!t.showPassword)},[o("i",{class:ae(t.showPassword?"fa fa-eye-slash":"fa fa-eye")},null,2)])]),t.password?(b(),w("div",f3,[o("div",{class:ae(["strength-bar",t.passwordStrengthClass]),style:Sn({width:t.passwordStrength+"%"})},null,6)])):U("",!0),e[9]||(e[9]=o("small",{class:"password-hint"},"Mínimo de 6 caracteres recomendado",-1))]),o("div",h3,[e[10]||(e[10]=o("label",{for:"confirmPassword"},[o("i",{class:"fa fa-lock"}),L(" Confirmar Senha ")],-1)),Be(o("input",{id:"confirmPassword","onUpdate:modelValue":e[3]||(e[3]=r=>t.confirmPassword=r),type:"password",class:"form-input",placeholder:"••••••••",required:""},null,512),[[at,t.confirmPassword]]),t.confirmPassword&&t.password!==t.confirmPassword?(b(),w("small",p3," As senhas não coincidem ")):U("",!0)]),o("button",{type:"submit",class:"btn-primary",disabled:t.loading||!t.isFormValid},[t.loading?(b(),w("i",m3)):(b(),w("i",v3)),L(" "+A(t.loading?"Criando...":"Criar Usuário"),1)],8,g3)],32)])]),o("div",b3,[e[14]||(e[14]=o("div",{class:"card-header"},[o("i",{class:"fa fa-info-circle"}),o("h2",null,"Informações do Sistema")],-1)),o("div",y3,[o("div",w3,[e[12]||(e[12]=o("span",{class:"info-label"},"Versão:",-1)),o("code",_3,A(t.version||"Carregando..."),1)]),e[13]||(e[13]=o("div",{class:"info-row"},[o("span",{class:"info-label"},"Cadastro de Conta:"),o("span",{class:"info-value"},[o("span",{class:"badge badge-success"},"Habilitado")])],-1))])])])])}const k3=It(t3,[["render",C3],["__scopeId","data-v-700a0a46"]]),S3=$t({name:"Connect",setup(){const t=ti(),e=O(!1),n=O("");return{loading:e,error:n,connectWith:async i=>{var l,r;e.value=!0,n.value="";try{const c=await be.post("/api/server/create",{});if(c.data&&c.data.token){const u=c.data.token;we("Servidor criado com sucesso!","success"),i==="qrcode"?t.push(`/server/${u}/qrcode`):t.push(`/server/${u}/paircode`)}else throw new Error("Token não recebido do servidor")}catch(c){console.error("Error creating server:",c),n.value=((r=(l=c.response)==null?void 0:l.data)==null?void 0:r.message)||c.message||"Erro ao criar servidor",we(n.value,"error")}finally{e.value=!1}}}}}),E3={class:"connect-page"},$3={class:"connect-header"},T3={key:0,class:"loading-state"},A3={key:1,class:"error-state"},R3={key:2,class:"connection-methods"};function P3(t,e,n,s,i,l){return b(),w("div",E3,[o("div",$3,[o("button",{onClick:e[0]||(e[0]=r=>t.$router.back()),class:"back-link"},[...e[4]||(e[4]=[o("svg",{viewBox:"0 0 24 24",width:"24",height:"24",fill:"currentColor"},[o("path",{d:"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"})],-1),L(" Voltar ",-1)])]),e[5]||(e[5]=o("h1",null,"Conectar WhatsApp",-1)),e[6]||(e[6]=o("p",{class:"subtitle"},"Escolha o método de conexão",-1))]),t.loading?(b(),w("div",T3,[...e[7]||(e[7]=[o("div",{class:"spinner"},null,-1),o("p",null,"Criando servidor...",-1)])])):t.error?(b(),w("div",A3,[e[8]||(e[8]=o("svg",{viewBox:"0 0 24 24",width:"48",height:"48",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)),o("p",null,A(t.error),1),o("button",{onClick:e[1]||(e[1]=r=>t.error=""),class:"btn-retry"},"Tentar novamente")])):(b(),w("div",R3,[o("div",{class:"method-card",onClick:e[2]||(e[2]=r=>t.connectWith("qrcode"))},[...e[9]||(e[9]=[Cn('

QR Code

Escaneie o código QR com seu WhatsApp

  • ✓ Conexão rápida
  • ✓ Use a câmera do celular
  • ✓ Método tradicional
Escanear QR Code →',5)])]),o("div",{class:"method-card",onClick:e[3]||(e[3]=r=>t.connectWith("paircode"))},[...e[10]||(e[10]=[Cn('

Pair Code

Digite o código de 8 dígitos no WhatsApp

  • ✓ Sem necessidade de câmera
  • ✓ Use o teclado
  • ✓ Método alternativo
Usar Pair Code →',5)])])])),e[11]||(e[11]=o("div",{class:"help-section"},[o("h4",null,"Como conectar?"),o("ol",null,[o("li",null,"Escolha um método acima"),o("li",null,"Abra o WhatsApp no seu celular"),o("li",null,[L("Vá em "),o("strong",null,"Configurações → Aparelhos conectados")]),o("li",null,[L("Toque em "),o("strong",null,"Conectar um aparelho")]),o("li",null,"Escaneie o QR Code ou digite o Pair Code")])],-1))])}const I3=It(S3,[["render",P3],["__scopeId","data-v-180bf89a"]]),O3=$t({setup(){const t=O([]),e=O(!0),n=O(""),s=O(""),i=O(!1),l=O(null);async function r(){var f,g;e.value=!0,n.value="";try{const C=await be.get("/api/users");t.value=C.data.users||[]}catch(C){n.value=((g=(f=C==null?void 0:C.response)==null?void 0:f.data)==null?void 0:g.result)||"Failed to load users"}finally{e.value=!1}}function c(f){try{return new Date(f).toLocaleDateString()}catch{return f}}function u(f){l.value=f,i.value=!0}async function h(){var f,g;if(l.value){s.value=l.value.username,i.value=!1;try{await be.delete("/api/user",{data:{username:l.value.username}}),we("User deleted successfully","success"),await r()}catch(C){we(((g=(f=C==null?void 0:C.response)==null?void 0:f.data)==null?void 0:g.result)||"Failed to delete user","error")}finally{s.value="",l.value=null}}}return cn(()=>{r()}),{users:t,loading:e,error:n,deleting:s,showDeleteModal:i,userToDelete:l,load:r,formatDate:c,confirmDelete:u,deleteUser:h}}}),M3={class:"users-page"},D3={class:"page-header"},L3={class:"header-actions"},N3={key:0,class:"loading-state"},F3={key:1,class:"error-box"},x3={key:2,class:"empty-state"},B3={key:3,class:"users-list"},z3={class:"user-info"},H3={class:"user-details"},U3={key:0,class:"self-badge"},V3={key:0},j3={class:"user-actions"},q3=["onClick","disabled"],W3={key:0,class:"fa fa-spinner fa-spin"},K3={key:1,class:"fa fa-trash"},G3={class:"modal-content"},Q3={class:"modal-actions"};function J3(t,e,n,s,i,l){var c;const r=zt("router-link");return b(),w("div",M3,[o("div",D3,[e[5]||(e[5]=o("div",{class:"header-content"},[o("h1",null,[o("i",{class:"fa fa-users"}),L(" Users ")]),o("p",{class:"hide-mobile"},"Manage users in your account")],-1)),o("div",L3,[ke(r,{to:"/users/create",class:"btn-primary"},{default:Ze(()=>[...e[4]||(e[4]=[o("i",{class:"fa fa-user-plus"},null,-1),L(" New User ",-1)])]),_:1})])]),t.loading?(b(),w("div",N3,[...e[6]||(e[6]=[o("div",{class:"spinner-large"},null,-1),o("p",null,"Loading users...",-1)])])):U("",!0),t.error?(b(),w("div",F3,[e[7]||(e[7]=o("i",{class:"fa fa-exclamation-triangle"},null,-1)),o("span",null,A(t.error),1),o("button",{onClick:e[0]||(e[0]=(...u)=>t.load&&t.load(...u)),class:"retry-btn"},"Retry")])):!t.loading&&t.users.length===0?(b(),w("div",x3,[e[9]||(e[9]=o("div",{class:"empty-icon"},[o("i",{class:"fa fa-users fa-4x"})],-1)),e[10]||(e[10]=o("h2",null,"No users yet",-1)),e[11]||(e[11]=o("p",null,"Create your first user to get started",-1)),ke(r,{to:"/users/create",class:"btn-primary-large"},{default:Ze(()=>[...e[8]||(e[8]=[o("i",{class:"fa fa-user-plus"},null,-1),L(" Create User ",-1)])]),_:1})])):(b(),w("div",B3,[(b(!0),w(Xe,null,Yt(t.users,u=>(b(),w("div",{key:u.username,class:ae(["user-card",{"user-self":u.is_self}])},[o("div",z3,[o("div",{class:ae(["user-avatar",{"avatar-self":u.is_self}])},[...e[12]||(e[12]=[o("i",{class:"fa fa-user"},null,-1)])],2),o("div",H3,[o("h3",null,[L(A(u.username)+" ",1),u.is_self?(b(),w("span",U3,"You")):U("",!0)]),u.timestamp?(b(),w("small",V3,"Created: "+A(t.formatDate(u.timestamp)),1)):U("",!0)])]),o("div",j3,[u.is_self?U("",!0):(b(),w("button",{key:0,class:"btn-danger-small",onClick:h=>t.confirmDelete(u),disabled:t.deleting===u.username},[t.deleting===u.username?(b(),w("i",W3)):(b(),w("i",K3))],8,q3))])],2))),128))])),t.showDeleteModal?(b(),w("div",{key:4,class:"modal-overlay",onClick:e[3]||(e[3]=kt(u=>t.showDeleteModal=!1,["self"]))},[o("div",G3,[e[15]||(e[15]=o("div",{class:"modal-icon danger"},[o("i",{class:"fa fa-exclamation-triangle fa-3x"})],-1)),e[16]||(e[16]=o("h3",null,"Delete User?",-1)),o("p",null,[e[13]||(e[13]=L("Are you sure you want to delete ",-1)),o("strong",null,A((c=t.userToDelete)==null?void 0:c.username),1),e[14]||(e[14]=L("? This action cannot be undone.",-1))]),o("div",Q3,[o("button",{onClick:e[1]||(e[1]=u=>t.showDeleteModal=!1),class:"btn-secondary"},"Cancel"),o("button",{onClick:e[2]||(e[2]=(...u)=>t.deleteUser&&t.deleteUser(...u)),class:"btn-danger"},"Delete")])])])):U("",!0)])}const X3=It(O3,[["render",J3],["__scopeId","data-v-425a59c2"]]),Y3=$t({setup(){const t=O(""),e=O(""),n=O(""),s=O(!1),i=O(!1),l=O(""),r=O(""),c=Ye(()=>{const g=e.value;if(!g)return 0;let C=0;return g.length>=6&&(C+=25),g.length>=8&&(C+=25),/[A-Z]/.test(g)&&(C+=25),(/[0-9]/.test(g)||/[^A-Za-z0-9]/.test(g))&&(C+=25),C}),u=Ye(()=>c.value<50?"weak":c.value<75?"medium":"strong"),h=Ye(()=>t.value&&e.value&&e.value.length>=4&&e.value===n.value);async function f(){var g,C;if(h.value){i.value=!0,l.value="",r.value="";try{await be.post("/api/user",{email:t.value,password:e.value}),r.value="Usuário criado com sucesso!",we("Usuário criado com sucesso!","success"),t.value="",e.value="",n.value=""}catch(_){const y=((C=(g=_==null?void 0:_.response)==null?void 0:g.data)==null?void 0:C.result)||_.message||"Erro ao criar usuário";l.value=y,we(y,"error")}finally{i.value=!1}}}return{email:t,password:e,confirmPassword:n,showPassword:s,loading:i,error:l,success:r,passwordStrength:c,passwordStrengthClass:u,isFormValid:h,createUser:f}}}),Z3={class:"user-create-page"},ek={class:"page-header"},tk={class:"create-card"},nk={key:0,class:"error-box"},sk={key:1,class:"success-box"},ok={class:"form-group"},ik={class:"form-group"},rk={class:"password-wrapper"},ak=["type"],lk={key:0,class:"password-strength"},ck={class:"form-group"},uk={key:0,class:"error-hint"},dk={class:"form-actions"},fk=["disabled"],hk={key:0,class:"fa fa-spinner fa-spin"},pk={key:1,class:"fa fa-user-plus"};function gk(t,e,n,s,i,l){const r=zt("router-link");return b(),w("div",Z3,[o("div",ek,[o("button",{onClick:e[0]||(e[0]=c=>t.$router.back()),class:"back-link hide-mobile"},[...e[6]||(e[6]=[o("i",{class:"fa fa-arrow-left"},null,-1),L(" Voltar ",-1)])]),e[7]||(e[7]=o("div",{class:"header-content"},[o("h1",null,[o("i",{class:"fa fa-user-plus"}),L(" Criar Usuário ")]),o("p",null,"Adicione um novo usuário ao sistema")],-1))]),o("div",tk,[o("form",{onSubmit:e[5]||(e[5]=kt((...c)=>t.createUser&&t.createUser(...c),["prevent"])),class:"create-form"},[t.error?(b(),w("div",nk,[e[8]||(e[8]=o("i",{class:"fa fa-exclamation-triangle"},null,-1)),o("span",null,A(t.error),1)])):U("",!0),t.success?(b(),w("div",sk,[e[9]||(e[9]=o("i",{class:"fa fa-check-circle"},null,-1)),o("span",null,A(t.success),1)])):U("",!0),o("div",ok,[e[10]||(e[10]=o("label",{for:"email"},[o("i",{class:"fa fa-envelope"}),L(" Email ")],-1)),Be(o("input",{id:"email","onUpdate:modelValue":e[1]||(e[1]=c=>t.email=c),type:"email",class:"form-input",placeholder:"usuario@exemplo.com",required:""},null,512),[[at,t.email]])]),o("div",ik,[e[11]||(e[11]=o("label",{for:"password"},[o("i",{class:"fa fa-lock"}),L(" Senha ")],-1)),o("div",rk,[Be(o("input",{id:"password","onUpdate:modelValue":e[2]||(e[2]=c=>t.password=c),type:t.showPassword?"text":"password",class:"form-input",placeholder:"••••••••",required:""},null,8,ak),[[lf,t.password]]),o("button",{type:"button",class:"toggle-password",onClick:e[3]||(e[3]=c=>t.showPassword=!t.showPassword)},[o("i",{class:ae(t.showPassword?"fa fa-eye-slash":"fa fa-eye")},null,2)])]),t.password?(b(),w("div",lk,[o("div",{class:ae(["strength-bar",t.passwordStrengthClass]),style:Sn({width:t.passwordStrength+"%"})},null,6)])):U("",!0)]),o("div",ck,[e[12]||(e[12]=o("label",{for:"confirmPassword"},[o("i",{class:"fa fa-lock"}),L(" Confirmar Senha ")],-1)),Be(o("input",{id:"confirmPassword","onUpdate:modelValue":e[4]||(e[4]=c=>t.confirmPassword=c),type:"password",class:"form-input",placeholder:"••••••••",required:""},null,512),[[at,t.confirmPassword]]),t.confirmPassword&&t.password!==t.confirmPassword?(b(),w("small",uk," As senhas não coincidem ")):U("",!0)]),o("div",dk,[ke(r,{to:"/account",class:"btn-secondary"},{default:Ze(()=>[...e[13]||(e[13]=[L(" Cancelar ",-1)])]),_:1}),o("button",{type:"submit",class:"btn-primary",disabled:t.loading||!t.isFormValid},[t.loading?(b(),w("i",hk)):(b(),w("i",pk)),L(" "+A(t.loading?"Criando...":"Criar Usuário"),1)],8,fk)])],32)])])}const mk=It(Y3,[["render",gk],["__scopeId","data-v-0fc64e90"]]),vk=$t({name:"Environment",components:{RouterLink:el},setup(){const t=O(!0),e=O(""),n=O([]);return cn(async()=>{var i;try{const l=await be.get("/api/environment");(i=l.data)!=null&&i.categories&&(n.value=l.data.categories)}catch(l){e.value=l.message||"Failed to load environment variables"}finally{t.value=!1}}),{loading:t,error:e,categories:n}}}),bk={class:"environment-page"},yk={class:"d-flex justify-content-between align-items-center mb-4"},wk={key:0,class:"text-center py-5"},_k={key:1,class:"alert alert-danger"},Ck={key:2},kk={class:"accordion",id:"envAccordion"},Sk=["id"],Ek=["data-bs-target","aria-expanded","aria-controls"],$k={class:"category-badge me-2"},Tk=["id","aria-labelledby"],Ak={class:"accordion-body p-0"},Rk={class:"table table-hover mb-0"},Pk={class:"font-monospace text-primary"},Ik={key:0,class:"env-value"},Ok={key:1,class:"text-muted"},Mk={class:"text-muted small"};function Dk(t,e,n,s,i,l){return b(),w("div",bk,[o("div",yk,[e[2]||(e[2]=o("h2",null,"Environment Variables",-1)),o("button",{onClick:e[0]||(e[0]=r=>t.$router.back()),class:"back-link hide-mobile"},[...e[1]||(e[1]=[o("i",{class:"fa fa-arrow-left me-2"},null,-1),L(" Back ",-1)])])]),t.loading?(b(),w("div",wk,[...e[3]||(e[3]=[o("div",{class:"spinner-border text-primary",role:"status"},[o("span",{class:"visually-hidden"},"Loading...")],-1)])])):t.error?(b(),w("div",_k,A(t.error),1)):(b(),w("div",Ck,[o("div",kk,[(b(!0),w(Xe,null,Yt(t.categories,(r,c)=>(b(),w("div",{key:r.name,class:"accordion-item"},[o("h2",{class:"accordion-header",id:"heading"+c},[o("button",{class:ae(["accordion-button",{collapsed:c!==0}]),type:"button","data-bs-toggle":"collapse","data-bs-target":"#collapse"+c,"aria-expanded":c===0?"true":"false","aria-controls":"collapse"+c},[o("span",$k,A(r.variables.length),1),L(" "+A(r.name),1)],10,Ek)],8,Sk),o("div",{id:"collapse"+c,class:ae(["accordion-collapse collapse",{show:c===0}]),"aria-labelledby":"heading"+c,"data-bs-parent":"#envAccordion"},[o("div",Ak,[o("table",Rk,[e[4]||(e[4]=o("thead",{class:"table-light"},[o("tr",null,[o("th",{style:{width:"30%"}},"Variable"),o("th",{style:{width:"35%"}},"Value"),o("th",{style:{width:"35%"}},"Description")])],-1)),o("tbody",null,[(b(!0),w(Xe,null,Yt(r.variables,u=>(b(),w("tr",{key:u.name},[o("td",Pk,A(u.name),1),o("td",null,[u.value?(b(),w("code",Ik,A(u.value),1)):(b(),w("span",Ok,"Not set"))]),o("td",Mk,A(u.description),1)]))),128))])])])],10,Tk)]))),128))])]))])}const Lk=It(vk,[["render",Dk],["__scopeId","data-v-89157469"]]),Nk=$t({setup(){const e=ns().params.token,n=O(!1),s=O(""),i=O(""),l=O(!1);let r=null;async function c(){var g,C,_,y,P,I;n.value=!0,s.value="",i.value="";try{const H=await be.get(`/api/server/${e}/qrcode`);if((g=H.data)!=null&&g.connected){l.value=!0;return}(C=H.data)!=null&&C.qrcode?(i.value=H.data.qrcode,h()):s.value="Nenhum QR Code recebido"}catch(H){s.value=((y=(_=H.response)==null?void 0:_.data)==null?void 0:y.result)||((I=(P=H.response)==null?void 0:P.data)==null?void 0:I.message)||H.message||"Erro ao gerar QR Code"}finally{n.value=!1}}async function u(){var g,C;try{const _=await be.get(`/api/server/${e}/info`);((g=_.data)!=null&&g.connected||((C=_.data)==null?void 0:C.state)==="Ready")&&(l.value=!0,f())}catch{}}function h(){f(),r=setInterval(u,3e3)}function f(){r&&(clearInterval(r),r=null)}return cn(()=>{c()}),bo(()=>{f()}),{token:e,loading:n,error:s,qrImage:i,connected:l,generateQR:c}}}),Fk={class:"qrcode-page"},xk={class:"page-header"},Bk={class:"header-content"},zk={class:"content-card"},Hk={key:0,class:"error-box"},Uk={class:"qr-container"},Vk={key:0,class:"qr-loading"},jk={key:1,class:"qr-success"},qk={key:2,class:"qr-display"},Wk=["src"],Kk={key:1,class:"qr-placeholder"},Gk={class:"qr-actions"},Qk=["disabled"],Jk={class:"alt-method"};function Xk(t,e,n,s,i,l){const r=zt("router-link");return b(),w("div",Fk,[o("div",xk,[o("div",Bk,[o("button",{onClick:e[0]||(e[0]=c=>t.$router.back()),class:"back-link hide-mobile"},[...e[2]||(e[2]=[o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"})],-1),L(" Voltar ",-1)])]),e[3]||(e[3]=o("h1",null,"Conectar WhatsApp",-1)),e[4]||(e[4]=o("p",null,"Escaneie o QR Code com seu WhatsApp",-1))])]),o("div",zk,[t.error?(b(),w("div",Hk,[e[5]||(e[5]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)),o("span",null,A(t.error),1)])):U("",!0),o("div",Uk,[t.loading?(b(),w("div",Vk,[...e[6]||(e[6]=[o("div",{class:"spinner-large"},null,-1),o("p",null,"Gerando QR Code...",-1)])])):t.connected?(b(),w("div",jk,[e[8]||(e[8]=o("svg",{viewBox:"0 0 24 24",width:"80",height:"80",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L18 9l-9 9z"})],-1)),e[9]||(e[9]=o("h3",null,"Conectado com Sucesso!",-1)),e[10]||(e[10]=o("p",null,"Seu WhatsApp está pareado.",-1)),ke(r,{to:`/server/${t.token}`,class:"btn-success"},{default:Ze(()=>[...e[7]||(e[7]=[L(" Ir para o Servidor ",-1)])]),_:1},8,["to"])])):(b(),w("div",qk,[t.qrImage?(b(),w("img",{key:0,src:t.qrImage,alt:"QR Code",class:"qr-image"},null,8,Wk)):(b(),w("div",Kk,[...e[11]||(e[11]=[o("svg",{viewBox:"0 0 24 24",width:"60",height:"60",fill:"currentColor"},[o("path",{d:"M3 11h8V3H3v8zm2-6h4v4H5V5zM3 21h8v-8H3v8zm2-6h4v4H5v-4zm8-12v8h8V3h-8zm6 6h-4V5h4v4zm-6 4h2v2h-2zm2 2h2v2h-2zm-2 2h2v2h-2zm4 0h2v2h-2zm2 2h2v2h-2zm0-4h2v2h-2zm2-2h2v2h-2z"})],-1),o("p",null,'Clique em "Gerar QR Code"',-1)])]))])),o("div",Gk,[o("button",{onClick:e[1]||(e[1]=(...c)=>t.generateQR&&t.generateQR(...c)),class:"btn-primary",disabled:t.loading},[e[12]||(e[12]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"})],-1)),L(" "+A(t.loading?"Gerando...":"Gerar QR Code"),1)],8,Qk)]),e[13]||(e[13]=Cn('

Como conectar:

  1. Abra o WhatsApp no seu celular
  2. Toque em Menu ou Configurações
  3. Toque em Aparelhos Conectados
  4. Toque em Conectar um aparelho
  5. Aponte a câmera para o QR Code
',1))]),o("div",Jk,[e[15]||(e[15]=o("p",null,"Prefere usar código numérico?",-1)),ke(r,{to:`/server/${t.token}/paircode`,class:"link-primary"},{default:Ze(()=>[...e[14]||(e[14]=[L(" Conectar com Código de Pareamento ",-1)])]),_:1},8,["to"])])])])}const Yk=It(Nk,[["render",Xk],["__scopeId","data-v-1576019b"]]),Zk=$t({setup(){const e=ns().params.token,n=O(""),s=O(""),i=O(!1),l=O(!1),r=O(""),c=O(!1),u=O(!1);let h=null,f=0;const g=60,C=Ye(()=>{if(!s.value)return[];const F=s.value.replace(/[^0-9A-Za-z]/g,"");return F.length>=8?(F.substring(0,4)+"-"+F.substring(4,8)).split(""):F.split("")});async function _(){var F,ne,he,ce,Ee,Se,_e,ye;if(n.value){i.value=!0,r.value="";try{const Me=await be.get(`/api/server/${e}/paircode`,{params:{phone:n.value}});if((F=Me.data)!=null&&F.connected||((ne=Me.data)==null?void 0:ne.state)==="Ready"){u.value=!0;return}(he=Me.data)!=null&&he.paircode?(s.value=Me.data.paircode,W()):r.value=((ce=Me.data)==null?void 0:ce.result)||"Erro ao gerar código"}catch(Me){const ve=((Se=(Ee=Me==null?void 0:Me.response)==null?void 0:Ee.data)==null?void 0:Se.result)||((ye=(_e=Me==null?void 0:Me.response)==null?void 0:_e.data)==null?void 0:ye.message)||Me.message||"Erro ao gerar código";r.value=ve}finally{i.value=!1}}}function y(){s.value="",G()}async function P(){if(s.value)try{await navigator.clipboard.writeText(s.value),c.value=!0,setTimeout(()=>c.value=!1,2e3)}catch{}}async function I(){var F,ne,he,ce,Ee;try{const Se=await be.get(`/api/server/${e}/info`),_e=((F=Se.data)==null?void 0:F.connected)===!0||((ne=Se.data)==null?void 0:ne.state)==="Ready",ye=((he=Se.data)==null?void 0:he.wid)||((Ee=(ce=Se.data)==null?void 0:ce.server)==null?void 0:Ee.wid);if(_e)return u.value=!0,G(),!0;f++,f>=g&&G()}catch{}return!1}async function H(){l.value=!0,r.value="";for(let F=0;F<5;F++){if(await I()){l.value=!1;return}await new Promise(he=>setTimeout(he,1e3))}l.value=!1,r.value="Pareamento ainda não detectado. Certifique-se de ter digitado o código corretamente no WhatsApp."}function W(){G(),f=0,h=setInterval(I,3e3)}function G(){h&&(clearInterval(h),h=null)}return bo(()=>{G()}),{token:e,phone:n,pairCode:s,loading:i,checking:l,error:r,copied:c,connected:u,formattedCode:C,generateCode:_,resetCode:y,copyCode:P,confirmPairing:H}}}),eS={class:"paircode-page"},tS={class:"page-header"},nS={class:"header-content"},sS={class:"content-card"},oS={key:0,class:"error-box"},iS={key:1,class:"success-section"},rS={key:2},aS={key:0,class:"step-section"},lS={class:"phone-input-group"},cS={class:"input-wrapper"},uS=["disabled"],dS={key:0,class:"spinner"},fS={key:1},hS={key:1,class:"step-section"},pS={class:"step-header"},gS={class:"step-info"},mS={key:2,class:"step-section"},vS={class:"code-display"},bS={class:"code-box"},yS={key:0,viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},wS={key:1,viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},_S={class:"action-buttons"},CS=["disabled"],kS={key:0,class:"spinner"},SS={key:1,viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},ES={class:"alt-method"};function $S(t,e,n,s,i,l){const r=zt("router-link");return b(),w("div",eS,[o("div",tS,[o("div",nS,[o("button",{onClick:e[0]||(e[0]=c=>t.$router.back()),class:"back-link hide-mobile"},[...e[8]||(e[8]=[o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"})],-1),L(" Voltar ",-1)])]),e[9]||(e[9]=o("h1",null,"Código de Pareamento",-1)),e[10]||(e[10]=o("p",null,"Conecte usando um código numérico",-1))])]),o("div",sS,[t.error?(b(),w("div",oS,[e[11]||(e[11]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)),o("span",null,A(t.error),1)])):U("",!0),t.connected?(b(),w("div",iS,[e[13]||(e[13]=o("div",{class:"success-icon"},[o("svg",{viewBox:"0 0 24 24",width:"80",height:"80",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L18 9l-9 9z"})])],-1)),e[14]||(e[14]=o("h3",null,"Conectado com Sucesso!",-1)),e[15]||(e[15]=o("p",null,"Seu WhatsApp está pareado.",-1)),ke(r,{to:`/server/${t.token}`,class:"btn-success"},{default:Ze(()=>[...e[12]||(e[12]=[L(" Ir para o Servidor ",-1)])]),_:1},8,["to"])])):(b(),w("div",rS,[t.pairCode?U("",!0):(b(),w("div",aS,[e[17]||(e[17]=o("div",{class:"step-header"},[o("div",{class:"step-number"},"1"),o("div",{class:"step-info"},[o("h3",null,"Informe o número do WhatsApp"),o("p",null,"Digite o número com código do país (ex: 5511999999999)")])],-1)),o("div",lS,[o("div",cS,[e[16]||(e[16]=o("span",{class:"input-prefix"},"+",-1)),Be(o("input",{"onUpdate:modelValue":e[1]||(e[1]=c=>t.phone=c),type:"tel",class:"phone-input",placeholder:"5511999999999",onKeyup:e[2]||(e[2]=Wi((...c)=>t.generateCode&&t.generateCode(...c),["enter"]))},null,544),[[at,t.phone]])]),o("button",{onClick:e[3]||(e[3]=(...c)=>t.generateCode&&t.generateCode(...c)),class:"btn-primary",disabled:t.loading||!t.phone},[t.loading?(b(),w("span",dS)):(b(),w("span",fS,"Gerar Código"))],8,uS)])])),t.pairCode?(b(),w("div",hS,[o("div",pS,[e[18]||(e[18]=o("div",{class:"step-number completed"},"✓",-1)),o("div",gS,[o("h3",null,"Número: +"+A(t.phone),1),o("button",{onClick:e[4]||(e[4]=(...c)=>t.resetCode&&t.resetCode(...c)),class:"btn-link"},"Alterar número")])])])):U("",!0),t.pairCode?(b(),w("div",mS,[e[23]||(e[23]=o("div",{class:"step-header"},[o("div",{class:"step-number"},"2"),o("div",{class:"step-info"},[o("h3",null,"Digite este código no WhatsApp"),o("p",null,"Acesse Aparelhos Conectados → Conectar com número")])],-1)),o("div",vS,[o("div",bS,[(b(!0),w(Xe,null,Yt(t.formattedCode,(c,u)=>(b(),w("span",{key:u,class:ae(["code-char",{separator:c==="-"}])},A(c),3))),128))]),o("button",{onClick:e[5]||(e[5]=(...c)=>t.copyCode&&t.copyCode(...c)),class:ae(["btn-copy",{copied:t.copied}])},[t.copied?(b(),w("svg",wS,[...e[20]||(e[20]=[o("path",{d:"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"},null,-1)])])):(b(),w("svg",yS,[...e[19]||(e[19]=[o("path",{d:"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"},null,-1)])])),L(" "+A(t.copied?"Copiado!":"Copiar"),1)],2)]),e[24]||(e[24]=o("div",{class:"code-timer"},[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"})]),o("span",null,"O código expira em alguns minutos")],-1)),o("div",_S,[o("button",{onClick:e[6]||(e[6]=(...c)=>t.confirmPairing&&t.confirmPairing(...c)),class:"btn-confirm",disabled:t.checking},[t.checking?(b(),w("span",kS)):(b(),w("svg",SS,[...e[21]||(e[21]=[o("path",{d:"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"},null,-1)])])),L(" "+A(t.checking?"Verificando...":"Já digitei o código"),1)],8,CS),o("button",{onClick:e[7]||(e[7]=(...c)=>t.generateCode&&t.generateCode(...c)),class:"btn-secondary"},[...e[22]||(e[22]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"})],-1),L(" Gerar Novo Código ",-1)])])])])):U("",!0),e[27]||(e[27]=Cn('

Como conectar com código:

  1. Abra o WhatsApp no seu celular
  2. Vá em Configurações → Aparelhos Conectados
  3. Toque em Conectar um aparelho
  4. Toque em "Conectar com número de telefone"
  5. Digite o código de 8 dígitos mostrado acima
  6. Clique em "Já digitei o código" para confirmar
',1)),o("div",ES,[e[26]||(e[26]=o("p",null,"Prefere escanear QR Code?",-1)),ke(r,{to:`/server/${t.token}/qrcode`,class:"link-primary"},{default:Ze(()=>[...e[25]||(e[25]=[L(" Conectar com QR Code ",-1)])]),_:1},8,["to"])])]))])])}const TS=It(Zk,[["render",$S],["__scopeId","data-v-8958d222"]]);class Ns extends Error{constructor(e,n){const s=new.target.prototype;super(`${e}: Status code '${n}'`),this.statusCode=n,this.__proto__=s}}class rl extends Error{constructor(e="A timeout occurred."){const n=new.target.prototype;super(e),this.__proto__=n}}class kn extends Error{constructor(e="An abort occurred."){const n=new.target.prototype;super(e),this.__proto__=n}}class AS extends Error{constructor(e,n){const s=new.target.prototype;super(e),this.transport=n,this.errorType="UnsupportedTransportError",this.__proto__=s}}class RS extends Error{constructor(e,n){const s=new.target.prototype;super(e),this.transport=n,this.errorType="DisabledTransportError",this.__proto__=s}}class PS extends Error{constructor(e,n){const s=new.target.prototype;super(e),this.transport=n,this.errorType="FailedToStartTransportError",this.__proto__=s}}class Xu extends Error{constructor(e){const n=new.target.prototype;super(e),this.errorType="FailedToNegotiateWithServerError",this.__proto__=n}}class IS extends Error{constructor(e,n){const s=new.target.prototype;super(e),this.innerErrors=n,this.__proto__=s}}class Gf{constructor(e,n,s){this.statusCode=e,this.statusText=n,this.content=s}}class gr{get(e,n){return this.send({...n,method:"GET",url:e})}post(e,n){return this.send({...n,method:"POST",url:e})}delete(e,n){return this.send({...n,method:"DELETE",url:e})}getCookieString(e){return""}}var q;(function(t){t[t.Trace=0]="Trace",t[t.Debug=1]="Debug",t[t.Information=2]="Information",t[t.Warning=3]="Warning",t[t.Error=4]="Error",t[t.Critical=5]="Critical",t[t.None=6]="None"})(q||(q={}));class Jo{constructor(){}log(e,n){}}Jo.instance=new Jo;const OS="10.0.0";class Tt{static isRequired(e,n){if(e==null)throw new Error(`The '${n}' argument is required.`)}static isNotEmpty(e,n){if(!e||e.match(/^\s*$/))throw new Error(`The '${n}' argument should not be empty.`)}static isIn(e,n,s){if(!(e in n))throw new Error(`Unknown ${s} value: ${e}.`)}}class wt{static get isBrowser(){return!wt.isNode&&typeof window=="object"&&typeof window.document=="object"}static get isWebWorker(){return!wt.isNode&&typeof self=="object"&&"importScripts"in self}static get isReactNative(){return!wt.isNode&&typeof window=="object"&&typeof window.document>"u"}static get isNode(){return typeof process<"u"&&process.release&&process.release.name==="node"}}function Xo(t,e){let n="";return zs(t)?(n=`Binary data of length ${t.byteLength}`,e&&(n+=`. Content: '${MS(t)}'`)):typeof t=="string"&&(n=`String data of length ${t.length}`,e&&(n+=`. Content: '${t}'`)),n}function MS(t){const e=new Uint8Array(t);let n="";return e.forEach(s=>{const i=s<16?"0":"";n+=`0x${i}${s.toString(16)} `}),n.substring(0,n.length-1)}function zs(t){return t&&typeof ArrayBuffer<"u"&&(t instanceof ArrayBuffer||t.constructor&&t.constructor.name==="ArrayBuffer")}async function Qf(t,e,n,s,i,l){const r={},[c,u]=mo();r[c]=u,t.log(q.Trace,`(${e} transport) sending data. ${Xo(i,l.logMessageContent)}.`);const h=zs(i)?"arraybuffer":"text",f=await n.post(s,{content:i,headers:{...r,...l.headers},responseType:h,timeout:l.timeout,withCredentials:l.withCredentials});t.log(q.Trace,`(${e} transport) request complete. Response status: ${f.statusCode}.`)}function DS(t){return t===void 0?new Ji(q.Information):t===null?Jo.instance:t.log!==void 0?t:new Ji(t)}class LS{constructor(e,n){this._subject=e,this._observer=n}dispose(){const e=this._subject.observers.indexOf(this._observer);e>-1&&this._subject.observers.splice(e,1),this._subject.observers.length===0&&this._subject.cancelCallback&&this._subject.cancelCallback().catch(n=>{})}}class Ji{constructor(e){this._minLevel=e,this.out=console}log(e,n){if(e>=this._minLevel){const s=`[${new Date().toISOString()}] ${q[e]}: ${n}`;switch(e){case q.Critical:case q.Error:this.out.error(s);break;case q.Warning:this.out.warn(s);break;case q.Information:this.out.info(s);break;default:this.out.log(s);break}}}}function mo(){let t="X-SignalR-User-Agent";return wt.isNode&&(t="User-Agent"),[t,NS(OS,FS(),BS(),xS())]}function NS(t,e,n,s){let i="Microsoft SignalR/";const l=t.split(".");return i+=`${l[0]}.${l[1]}`,i+=` (${t}; `,e&&e!==""?i+=`${e}; `:i+="Unknown OS; ",i+=`${n}`,s?i+=`; ${s}`:i+="; Unknown Runtime Version",i+=")",i}function FS(){if(wt.isNode)switch(process.platform){case"win32":return"Windows NT";case"darwin":return"macOS";case"linux":return"Linux";default:return process.platform}else return""}function xS(){if(wt.isNode)return process.versions.node}function BS(){return wt.isNode?"NodeJS":"Browser"}function fa(t){return t.stack?t.stack:t.message?t.message:`${t}`}function zS(){if(typeof globalThis<"u")return globalThis;if(typeof self<"u")return self;if(typeof window<"u")return window;if(typeof global<"u")return global;throw new Error("could not find global")}class HS extends gr{constructor(e){if(super(),this._logger=e,typeof fetch>"u"||wt.isNode){const n=typeof __webpack_require__=="function"?__non_webpack_require__:require;this._jar=new(n("tough-cookie")).CookieJar,typeof fetch>"u"?this._fetchType=n("node-fetch"):this._fetchType=fetch,this._fetchType=n("fetch-cookie")(this._fetchType,this._jar)}else this._fetchType=fetch.bind(zS());if(typeof AbortController>"u"){const n=typeof __webpack_require__=="function"?__non_webpack_require__:require;this._abortControllerType=n("abort-controller")}else this._abortControllerType=AbortController}async send(e){if(e.abortSignal&&e.abortSignal.aborted)throw new kn;if(!e.method)throw new Error("No method defined.");if(!e.url)throw new Error("No url defined.");const n=new this._abortControllerType;let s;e.abortSignal&&(e.abortSignal.onabort=()=>{n.abort(),s=new kn});let i=null;if(e.timeout){const u=e.timeout;i=setTimeout(()=>{n.abort(),this._logger.log(q.Warning,"Timeout from HTTP request."),s=new rl},u)}e.content===""&&(e.content=void 0),e.content&&(e.headers=e.headers||{},zs(e.content)?e.headers["Content-Type"]="application/octet-stream":e.headers["Content-Type"]="text/plain;charset=UTF-8");let l;try{l=await this._fetchType(e.url,{body:e.content,cache:"no-cache",credentials:e.withCredentials===!0?"include":"same-origin",headers:{"X-Requested-With":"XMLHttpRequest",...e.headers},method:e.method,mode:"cors",redirect:"follow",signal:n.signal})}catch(u){throw s||(this._logger.log(q.Warning,`Error from HTTP request. ${u}.`),u)}finally{i&&clearTimeout(i),e.abortSignal&&(e.abortSignal.onabort=null)}if(!l.ok){const u=await Yu(l,"text");throw new Ns(u||l.statusText,l.status)}const c=await Yu(l,e.responseType);return new Gf(l.status,l.statusText,c)}getCookieString(e){let n="";return wt.isNode&&this._jar&&this._jar.getCookies(e,(s,i)=>n=i.join("; ")),n}}function Yu(t,e){let n;switch(e){case"arraybuffer":n=t.arrayBuffer();break;case"text":n=t.text();break;case"blob":case"document":case"json":throw new Error(`${e} is not supported.`);default:n=t.text();break}return n}class US extends gr{constructor(e){super(),this._logger=e}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new kn):e.method?e.url?new Promise((n,s)=>{const i=new XMLHttpRequest;i.open(e.method,e.url,!0),i.withCredentials=e.withCredentials===void 0?!0:e.withCredentials,i.setRequestHeader("X-Requested-With","XMLHttpRequest"),e.content===""&&(e.content=void 0),e.content&&(zs(e.content)?i.setRequestHeader("Content-Type","application/octet-stream"):i.setRequestHeader("Content-Type","text/plain;charset=UTF-8"));const l=e.headers;l&&Object.keys(l).forEach(r=>{i.setRequestHeader(r,l[r])}),e.responseType&&(i.responseType=e.responseType),e.abortSignal&&(e.abortSignal.onabort=()=>{i.abort(),s(new kn)}),e.timeout&&(i.timeout=e.timeout),i.onload=()=>{e.abortSignal&&(e.abortSignal.onabort=null),i.status>=200&&i.status<300?n(new Gf(i.status,i.statusText,i.response||i.responseText)):s(new Ns(i.response||i.responseText||i.statusText,i.status))},i.onerror=()=>{this._logger.log(q.Warning,`Error from HTTP request. ${i.status}: ${i.statusText}.`),s(new Ns(i.statusText,i.status))},i.ontimeout=()=>{this._logger.log(q.Warning,"Timeout from HTTP request."),s(new rl)},i.send(e.content)}):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))}}class VS extends gr{constructor(e){if(super(),typeof fetch<"u"||wt.isNode)this._httpClient=new HS(e);else if(typeof XMLHttpRequest<"u")this._httpClient=new US(e);else throw new Error("No usable HttpClient found.")}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new kn):e.method?e.url?this._httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))}getCookieString(e){return this._httpClient.getCookieString(e)}}class ln{static write(e){return`${e}${ln.RecordSeparator}`}static parse(e){if(e[e.length-1]!==ln.RecordSeparator)throw new Error("Message is incomplete.");const n=e.split(ln.RecordSeparator);return n.pop(),n}}ln.RecordSeparatorCode=30;ln.RecordSeparator=String.fromCharCode(ln.RecordSeparatorCode);class jS{writeHandshakeRequest(e){return ln.write(JSON.stringify(e))}parseHandshakeResponse(e){let n,s;if(zs(e)){const c=new Uint8Array(e),u=c.indexOf(ln.RecordSeparatorCode);if(u===-1)throw new Error("Message is incomplete.");const h=u+1;n=String.fromCharCode.apply(null,Array.prototype.slice.call(c.slice(0,h))),s=c.byteLength>h?c.slice(h).buffer:null}else{const c=e,u=c.indexOf(ln.RecordSeparator);if(u===-1)throw new Error("Message is incomplete.");const h=u+1;n=c.substring(0,h),s=c.length>h?c.substring(h):null}const i=ln.parse(n),l=JSON.parse(i[0]);if(l.type)throw new Error("Expected a handshake response from the server.");return[s,l]}}var xe;(function(t){t[t.Invocation=1]="Invocation",t[t.StreamItem=2]="StreamItem",t[t.Completion=3]="Completion",t[t.StreamInvocation=4]="StreamInvocation",t[t.CancelInvocation=5]="CancelInvocation",t[t.Ping=6]="Ping",t[t.Close=7]="Close",t[t.Ack=8]="Ack",t[t.Sequence=9]="Sequence"})(xe||(xe={}));class qS{constructor(){this.observers=[]}next(e){for(const n of this.observers)n.next(e)}error(e){for(const n of this.observers)n.error&&n.error(e)}complete(){for(const e of this.observers)e.complete&&e.complete()}subscribe(e){return this.observers.push(e),new LS(this,e)}}class WS{constructor(e,n,s){this._bufferSize=1e5,this._messages=[],this._totalMessageCount=0,this._waitForSequenceMessage=!1,this._nextReceivingSequenceId=1,this._latestReceivedSequenceId=0,this._bufferedByteCount=0,this._reconnectInProgress=!1,this._protocol=e,this._connection=n,this._bufferSize=s}async _send(e){const n=this._protocol.writeMessage(e);let s=Promise.resolve();if(this._isInvocationMessage(e)){this._totalMessageCount++;let i=()=>{},l=()=>{};zs(n)?this._bufferedByteCount+=n.byteLength:this._bufferedByteCount+=n.length,this._bufferedByteCount>=this._bufferSize&&(s=new Promise((r,c)=>{i=r,l=c})),this._messages.push(new KS(n,this._totalMessageCount,i,l))}try{this._reconnectInProgress||await this._connection.send(n)}catch{this._disconnected()}await s}_ack(e){let n=-1;for(let s=0;sthis._nextReceivingSequenceId){this._connection.stop(new Error("Sequence ID greater than amount of messages we've received."));return}this._nextReceivingSequenceId=e.sequenceId}_disconnected(){this._reconnectInProgress=!0,this._waitForSequenceMessage=!0}async _resend(){const e=this._messages.length!==0?this._messages[0]._id:this._totalMessageCount+1;await this._connection.send(this._protocol.writeMessage({type:xe.Sequence,sequenceId:e}));const n=this._messages;for(const s of n)await this._connection.send(s._message);this._reconnectInProgress=!1}_dispose(e){e??(e=new Error("Unable to reconnect to server."));for(const n of this._messages)n._rejector(e)}_isInvocationMessage(e){switch(e.type){case xe.Invocation:case xe.StreamItem:case xe.Completion:case xe.StreamInvocation:case xe.CancelInvocation:return!0;case xe.Close:case xe.Sequence:case xe.Ping:case xe.Ack:return!1}}_ackTimer(){this._ackTimerHandle===void 0&&(this._ackTimerHandle=setTimeout(async()=>{try{this._reconnectInProgress||await this._connection.send(this._protocol.writeMessage({type:xe.Ack,sequenceId:this._latestReceivedSequenceId}))}catch{}clearTimeout(this._ackTimerHandle),this._ackTimerHandle=void 0},1e3))}}class KS{constructor(e,n,s,i){this._message=e,this._id=n,this._resolver=s,this._rejector=i}}const GS=30*1e3,QS=15*1e3,JS=1e5;var ut;(function(t){t.Disconnected="Disconnected",t.Connecting="Connecting",t.Connected="Connected",t.Disconnecting="Disconnecting",t.Reconnecting="Reconnecting"})(ut||(ut={}));class al{static create(e,n,s,i,l,r,c){return new al(e,n,s,i,l,r,c)}constructor(e,n,s,i,l,r,c){this._nextKeepAlive=0,this._freezeEventListener=()=>{this._logger.log(q.Warning,"The page is being frozen, this will likely lead to the connection being closed and messages being lost. For more information see the docs at https://learn.microsoft.com/aspnet/core/signalr/javascript-client#bsleep")},Tt.isRequired(e,"connection"),Tt.isRequired(n,"logger"),Tt.isRequired(s,"protocol"),this.serverTimeoutInMilliseconds=l??GS,this.keepAliveIntervalInMilliseconds=r??QS,this._statefulReconnectBufferSize=c??JS,this._logger=n,this._protocol=s,this.connection=e,this._reconnectPolicy=i,this._handshakeProtocol=new jS,this.connection.onreceive=u=>this._processIncomingData(u),this.connection.onclose=u=>this._connectionClosed(u),this._callbacks={},this._methods={},this._closedCallbacks=[],this._reconnectingCallbacks=[],this._reconnectedCallbacks=[],this._invocationId=0,this._receivedHandshakeResponse=!1,this._connectionState=ut.Disconnected,this._connectionStarted=!1,this._cachedPingMessage=this._protocol.writeMessage({type:xe.Ping})}get state(){return this._connectionState}get connectionId(){return this.connection&&this.connection.connectionId||null}get baseUrl(){return this.connection.baseUrl||""}set baseUrl(e){if(this._connectionState!==ut.Disconnected&&this._connectionState!==ut.Reconnecting)throw new Error("The HubConnection must be in the Disconnected or Reconnecting state to change the url.");if(!e)throw new Error("The HubConnection url must be a valid url.");this.connection.baseUrl=e}start(){return this._startPromise=this._startWithStateTransitions(),this._startPromise}async _startWithStateTransitions(){if(this._connectionState!==ut.Disconnected)return Promise.reject(new Error("Cannot start a HubConnection that is not in the 'Disconnected' state."));this._connectionState=ut.Connecting,this._logger.log(q.Debug,"Starting HubConnection.");try{await this._startInternal(),wt.isBrowser&&window.document.addEventListener("freeze",this._freezeEventListener),this._connectionState=ut.Connected,this._connectionStarted=!0,this._logger.log(q.Debug,"HubConnection connected successfully.")}catch(e){return this._connectionState=ut.Disconnected,this._logger.log(q.Debug,`HubConnection failed to start successfully because of error '${e}'.`),Promise.reject(e)}}async _startInternal(){this._stopDuringStartError=void 0,this._receivedHandshakeResponse=!1;const e=new Promise((n,s)=>{this._handshakeResolver=n,this._handshakeRejecter=s});await this.connection.start(this._protocol.transferFormat);try{let n=this._protocol.version;this.connection.features.reconnect||(n=1);const s={protocol:this._protocol.name,version:n};if(this._logger.log(q.Debug,"Sending handshake request."),await this._sendMessage(this._handshakeProtocol.writeHandshakeRequest(s)),this._logger.log(q.Information,`Using HubProtocol '${this._protocol.name}'.`),this._cleanupTimeout(),this._resetTimeoutPeriod(),this._resetKeepAliveInterval(),await e,this._stopDuringStartError)throw this._stopDuringStartError;(this.connection.features.reconnect||!1)&&(this._messageBuffer=new WS(this._protocol,this.connection,this._statefulReconnectBufferSize),this.connection.features.disconnected=this._messageBuffer._disconnected.bind(this._messageBuffer),this.connection.features.resend=()=>{if(this._messageBuffer)return this._messageBuffer._resend()}),this.connection.features.inherentKeepAlive||await this._sendMessage(this._cachedPingMessage)}catch(n){throw this._logger.log(q.Debug,`Hub handshake failed with error '${n}' during start(). Stopping HubConnection.`),this._cleanupTimeout(),this._cleanupPingTimer(),await this.connection.stop(n),n}}async stop(){const e=this._startPromise;this.connection.features.reconnect=!1,this._stopPromise=this._stopInternal(),await this._stopPromise;try{await e}catch{}}_stopInternal(e){if(this._connectionState===ut.Disconnected)return this._logger.log(q.Debug,`Call to HubConnection.stop(${e}) ignored because it is already in the disconnected state.`),Promise.resolve();if(this._connectionState===ut.Disconnecting)return this._logger.log(q.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnecting state.`),this._stopPromise;const n=this._connectionState;return this._connectionState=ut.Disconnecting,this._logger.log(q.Debug,"Stopping HubConnection."),this._reconnectDelayHandle?(this._logger.log(q.Debug,"Connection stopped during reconnect delay. Done reconnecting."),clearTimeout(this._reconnectDelayHandle),this._reconnectDelayHandle=void 0,this._completeClose(),Promise.resolve()):(n===ut.Connected&&this._sendCloseMessage(),this._cleanupTimeout(),this._cleanupPingTimer(),this._stopDuringStartError=e||new kn("The connection was stopped before the hub handshake could complete."),this.connection.stop(e))}async _sendCloseMessage(){try{await this._sendWithProtocol(this._createCloseMessage())}catch{}}stream(e,...n){const[s,i]=this._replaceStreamingParams(n),l=this._createStreamInvocation(e,n,i);let r;const c=new qS;return c.cancelCallback=()=>{const u=this._createCancelInvocation(l.invocationId);return delete this._callbacks[l.invocationId],r.then(()=>this._sendWithProtocol(u))},this._callbacks[l.invocationId]=(u,h)=>{if(h){c.error(h);return}else u&&(u.type===xe.Completion?u.error?c.error(new Error(u.error)):c.complete():c.next(u.item))},r=this._sendWithProtocol(l).catch(u=>{c.error(u),delete this._callbacks[l.invocationId]}),this._launchStreams(s,r),c}_sendMessage(e){return this._resetKeepAliveInterval(),this.connection.send(e)}_sendWithProtocol(e){return this._messageBuffer?this._messageBuffer._send(e):this._sendMessage(this._protocol.writeMessage(e))}send(e,...n){const[s,i]=this._replaceStreamingParams(n),l=this._sendWithProtocol(this._createInvocation(e,n,!0,i));return this._launchStreams(s,l),l}invoke(e,...n){const[s,i]=this._replaceStreamingParams(n),l=this._createInvocation(e,n,!1,i);return new Promise((c,u)=>{this._callbacks[l.invocationId]=(f,g)=>{if(g){u(g);return}else f&&(f.type===xe.Completion?f.error?u(new Error(f.error)):c(f.result):u(new Error(`Unexpected message type: ${f.type}`)))};const h=this._sendWithProtocol(l).catch(f=>{u(f),delete this._callbacks[l.invocationId]});this._launchStreams(s,h)})}on(e,n){!e||!n||(e=e.toLowerCase(),this._methods[e]||(this._methods[e]=[]),this._methods[e].indexOf(n)===-1&&this._methods[e].push(n))}off(e,n){if(!e)return;e=e.toLowerCase();const s=this._methods[e];if(s)if(n){const i=s.indexOf(n);i!==-1&&(s.splice(i,1),s.length===0&&delete this._methods[e])}else delete this._methods[e]}onclose(e){e&&this._closedCallbacks.push(e)}onreconnecting(e){e&&this._reconnectingCallbacks.push(e)}onreconnected(e){e&&this._reconnectedCallbacks.push(e)}_processIncomingData(e){if(this._cleanupTimeout(),this._receivedHandshakeResponse||(e=this._processHandshakeResponse(e),this._receivedHandshakeResponse=!0),e){const n=this._protocol.parseMessages(e,this._logger);for(const s of n)if(!(this._messageBuffer&&!this._messageBuffer._shouldProcessMessage(s)))switch(s.type){case xe.Invocation:this._invokeClientMethod(s).catch(i=>{this._logger.log(q.Error,`Invoke client method threw error: ${fa(i)}`)});break;case xe.StreamItem:case xe.Completion:{const i=this._callbacks[s.invocationId];if(i){s.type===xe.Completion&&delete this._callbacks[s.invocationId];try{i(s)}catch(l){this._logger.log(q.Error,`Stream callback threw error: ${fa(l)}`)}}break}case xe.Ping:break;case xe.Close:{this._logger.log(q.Information,"Close message received from server.");const i=s.error?new Error("Server returned an error on close: "+s.error):void 0;s.allowReconnect===!0?this.connection.stop(i):this._stopPromise=this._stopInternal(i);break}case xe.Ack:this._messageBuffer&&this._messageBuffer._ack(s);break;case xe.Sequence:this._messageBuffer&&this._messageBuffer._resetSequence(s);break;default:this._logger.log(q.Warning,`Invalid message type: ${s.type}.`);break}}this._resetTimeoutPeriod()}_processHandshakeResponse(e){let n,s;try{[s,n]=this._handshakeProtocol.parseHandshakeResponse(e)}catch(i){const l="Error parsing handshake response: "+i;this._logger.log(q.Error,l);const r=new Error(l);throw this._handshakeRejecter(r),r}if(n.error){const i="Server returned handshake error: "+n.error;this._logger.log(q.Error,i);const l=new Error(i);throw this._handshakeRejecter(l),l}else this._logger.log(q.Debug,"Server handshake complete.");return this._handshakeResolver(),s}_resetKeepAliveInterval(){this.connection.features.inherentKeepAlive||(this._nextKeepAlive=new Date().getTime()+this.keepAliveIntervalInMilliseconds,this._cleanupPingTimer())}_resetTimeoutPeriod(){if(!this.connection.features||!this.connection.features.inherentKeepAlive){this._timeoutHandle=setTimeout(()=>this.serverTimeout(),this.serverTimeoutInMilliseconds);let e=this._nextKeepAlive-new Date().getTime();if(e<0){this._connectionState===ut.Connected&&this._trySendPingMessage();return}this._pingServerHandle===void 0&&(e<0&&(e=0),this._pingServerHandle=setTimeout(async()=>{this._connectionState===ut.Connected&&await this._trySendPingMessage()},e))}}serverTimeout(){this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server."))}async _invokeClientMethod(e){const n=e.target.toLowerCase(),s=this._methods[n];if(!s){this._logger.log(q.Warning,`No client method with the name '${n}' found.`),e.invocationId&&(this._logger.log(q.Warning,`No result given for '${n}' method and invocation ID '${e.invocationId}'.`),await this._sendWithProtocol(this._createCompletionMessage(e.invocationId,"Client didn't provide a result.",null)));return}const i=s.slice(),l=!!e.invocationId;let r,c,u;for(const h of i)try{const f=r;r=await h.apply(this,e.arguments),l&&r&&f&&(this._logger.log(q.Error,`Multiple results provided for '${n}'. Sending error to server.`),u=this._createCompletionMessage(e.invocationId,"Client provided multiple results.",null)),c=void 0}catch(f){c=f,this._logger.log(q.Error,`A callback for the method '${n}' threw error '${f}'.`)}u?await this._sendWithProtocol(u):l?(c?u=this._createCompletionMessage(e.invocationId,`${c}`,null):r!==void 0?u=this._createCompletionMessage(e.invocationId,null,r):(this._logger.log(q.Warning,`No result given for '${n}' method and invocation ID '${e.invocationId}'.`),u=this._createCompletionMessage(e.invocationId,"Client didn't provide a result.",null)),await this._sendWithProtocol(u)):r&&this._logger.log(q.Error,`Result given for '${n}' method but server is not expecting a result.`)}_connectionClosed(e){this._logger.log(q.Debug,`HubConnection.connectionClosed(${e}) called while in state ${this._connectionState}.`),this._stopDuringStartError=this._stopDuringStartError||e||new kn("The underlying connection was closed before the hub handshake could complete."),this._handshakeResolver&&this._handshakeResolver(),this._cancelCallbacksWithError(e||new Error("Invocation canceled due to the underlying connection being closed.")),this._cleanupTimeout(),this._cleanupPingTimer(),this._connectionState===ut.Disconnecting?this._completeClose(e):this._connectionState===ut.Connected&&this._reconnectPolicy?this._reconnect(e):this._connectionState===ut.Connected&&this._completeClose(e)}_completeClose(e){if(this._connectionStarted){this._connectionState=ut.Disconnected,this._connectionStarted=!1,this._messageBuffer&&(this._messageBuffer._dispose(e??new Error("Connection closed.")),this._messageBuffer=void 0),wt.isBrowser&&window.document.removeEventListener("freeze",this._freezeEventListener);try{this._closedCallbacks.forEach(n=>n.apply(this,[e]))}catch(n){this._logger.log(q.Error,`An onclose callback called with error '${e}' threw error '${n}'.`)}}}async _reconnect(e){const n=Date.now();let s=0,i=e!==void 0?e:new Error("Attempting to reconnect due to a unknown error."),l=this._getNextRetryDelay(s,0,i);if(l===null){this._logger.log(q.Debug,"Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt."),this._completeClose(e);return}if(this._connectionState=ut.Reconnecting,e?this._logger.log(q.Information,`Connection reconnecting because of error '${e}'.`):this._logger.log(q.Information,"Connection reconnecting."),this._reconnectingCallbacks.length!==0){try{this._reconnectingCallbacks.forEach(r=>r.apply(this,[e]))}catch(r){this._logger.log(q.Error,`An onreconnecting callback called with error '${e}' threw error '${r}'.`)}if(this._connectionState!==ut.Reconnecting){this._logger.log(q.Debug,"Connection left the reconnecting state in onreconnecting callback. Done reconnecting.");return}}for(;l!==null;){if(this._logger.log(q.Information,`Reconnect attempt number ${s+1} will start in ${l} ms.`),await new Promise(r=>{this._reconnectDelayHandle=setTimeout(r,l)}),this._reconnectDelayHandle=void 0,this._connectionState!==ut.Reconnecting){this._logger.log(q.Debug,"Connection left the reconnecting state during reconnect delay. Done reconnecting.");return}try{if(await this._startInternal(),this._connectionState=ut.Connected,this._logger.log(q.Information,"HubConnection reconnected successfully."),this._reconnectedCallbacks.length!==0)try{this._reconnectedCallbacks.forEach(r=>r.apply(this,[this.connection.connectionId]))}catch(r){this._logger.log(q.Error,`An onreconnected callback called with connectionId '${this.connection.connectionId}; threw error '${r}'.`)}return}catch(r){if(this._logger.log(q.Information,`Reconnect attempt failed because of error '${r}'.`),this._connectionState!==ut.Reconnecting){this._logger.log(q.Debug,`Connection moved to the '${this._connectionState}' from the reconnecting state during reconnect attempt. Done reconnecting.`),this._connectionState===ut.Disconnecting&&this._completeClose();return}s++,i=r instanceof Error?r:new Error(r.toString()),l=this._getNextRetryDelay(s,Date.now()-n,i)}}this._logger.log(q.Information,`Reconnect retries have been exhausted after ${Date.now()-n} ms and ${s} failed attempts. Connection disconnecting.`),this._completeClose()}_getNextRetryDelay(e,n,s){try{return this._reconnectPolicy.nextRetryDelayInMilliseconds({elapsedMilliseconds:n,previousRetryCount:e,retryReason:s})}catch(i){return this._logger.log(q.Error,`IRetryPolicy.nextRetryDelayInMilliseconds(${e}, ${n}) threw error '${i}'.`),null}}_cancelCallbacksWithError(e){const n=this._callbacks;this._callbacks={},Object.keys(n).forEach(s=>{const i=n[s];try{i(null,e)}catch(l){this._logger.log(q.Error,`Stream 'error' callback called with '${e}' threw error: ${fa(l)}`)}})}_cleanupPingTimer(){this._pingServerHandle&&(clearTimeout(this._pingServerHandle),this._pingServerHandle=void 0)}_cleanupTimeout(){this._timeoutHandle&&clearTimeout(this._timeoutHandle)}_createInvocation(e,n,s,i){if(s)return i.length!==0?{target:e,arguments:n,streamIds:i,type:xe.Invocation}:{target:e,arguments:n,type:xe.Invocation};{const l=this._invocationId;return this._invocationId++,i.length!==0?{target:e,arguments:n,invocationId:l.toString(),streamIds:i,type:xe.Invocation}:{target:e,arguments:n,invocationId:l.toString(),type:xe.Invocation}}}_launchStreams(e,n){if(e.length!==0){n||(n=Promise.resolve());for(const s in e)e[s].subscribe({complete:()=>{n=n.then(()=>this._sendWithProtocol(this._createCompletionMessage(s)))},error:i=>{let l;i instanceof Error?l=i.message:i&&i.toString?l=i.toString():l="Unknown error",n=n.then(()=>this._sendWithProtocol(this._createCompletionMessage(s,l)))},next:i=>{n=n.then(()=>this._sendWithProtocol(this._createStreamItemMessage(s,i)))}})}}_replaceStreamingParams(e){const n=[],s=[];for(let i=0;i0)&&(n=!1,this._accessToken=await this._accessTokenFactory()),this._setAuthorizationHeader(e);const s=await this._innerClient.send(e);return n&&s.statusCode===401&&this._accessTokenFactory?(this._accessToken=await this._accessTokenFactory(),this._setAuthorizationHeader(e),await this._innerClient.send(e)):s}_setAuthorizationHeader(e){e.headers||(e.headers={}),this._accessToken?e.headers[Fs.Authorization]=`Bearer ${this._accessToken}`:this._accessTokenFactory&&e.headers[Fs.Authorization]&&delete e.headers[Fs.Authorization]}getCookieString(e){return this._innerClient.getCookieString(e)}}var Pt;(function(t){t[t.None=0]="None",t[t.WebSockets=1]="WebSockets",t[t.ServerSentEvents=2]="ServerSentEvents",t[t.LongPolling=4]="LongPolling"})(Pt||(Pt={}));var Nt;(function(t){t[t.Text=1]="Text",t[t.Binary=2]="Binary"})(Nt||(Nt={}));let ZS=class{constructor(){this._isAborted=!1,this.onabort=null}abort(){this._isAborted||(this._isAborted=!0,this.onabort&&this.onabort())}get signal(){return this}get aborted(){return this._isAborted}};class ed{get pollAborted(){return this._pollAbort.aborted}constructor(e,n,s){this._httpClient=e,this._logger=n,this._pollAbort=new ZS,this._options=s,this._running=!1,this.onreceive=null,this.onclose=null}async connect(e,n){if(Tt.isRequired(e,"url"),Tt.isRequired(n,"transferFormat"),Tt.isIn(n,Nt,"transferFormat"),this._url=e,this._logger.log(q.Trace,"(LongPolling transport) Connecting."),n===Nt.Binary&&typeof XMLHttpRequest<"u"&&typeof new XMLHttpRequest().responseType!="string")throw new Error("Binary protocols over XmlHttpRequest not implementing advanced features are not supported.");const[s,i]=mo(),l={[s]:i,...this._options.headers},r={abortSignal:this._pollAbort.signal,headers:l,timeout:1e5,withCredentials:this._options.withCredentials};n===Nt.Binary&&(r.responseType="arraybuffer");const c=`${e}&_=${Date.now()}`;this._logger.log(q.Trace,`(LongPolling transport) polling: ${c}.`);const u=await this._httpClient.get(c,r);u.statusCode!==200?(this._logger.log(q.Error,`(LongPolling transport) Unexpected response code: ${u.statusCode}.`),this._closeError=new Ns(u.statusText||"",u.statusCode),this._running=!1):this._running=!0,this._receiving=this._poll(this._url,r)}async _poll(e,n){try{for(;this._running;)try{const s=`${e}&_=${Date.now()}`;this._logger.log(q.Trace,`(LongPolling transport) polling: ${s}.`);const i=await this._httpClient.get(s,n);i.statusCode===204?(this._logger.log(q.Information,"(LongPolling transport) Poll terminated by server."),this._running=!1):i.statusCode!==200?(this._logger.log(q.Error,`(LongPolling transport) Unexpected response code: ${i.statusCode}.`),this._closeError=new Ns(i.statusText||"",i.statusCode),this._running=!1):i.content?(this._logger.log(q.Trace,`(LongPolling transport) data received. ${Xo(i.content,this._options.logMessageContent)}.`),this.onreceive&&this.onreceive(i.content)):this._logger.log(q.Trace,"(LongPolling transport) Poll timed out, reissuing.")}catch(s){this._running?s instanceof rl?this._logger.log(q.Trace,"(LongPolling transport) Poll timed out, reissuing."):(this._closeError=s,this._running=!1):this._logger.log(q.Trace,`(LongPolling transport) Poll errored after shutdown: ${s.message}`)}}finally{this._logger.log(q.Trace,"(LongPolling transport) Polling complete."),this.pollAborted||this._raiseOnClose()}}async send(e){return this._running?Qf(this._logger,"LongPolling",this._httpClient,this._url,e,this._options):Promise.reject(new Error("Cannot send until the transport is connected"))}async stop(){this._logger.log(q.Trace,"(LongPolling transport) Stopping polling."),this._running=!1,this._pollAbort.abort();try{await this._receiving,this._logger.log(q.Trace,`(LongPolling transport) sending DELETE request to ${this._url}.`);const e={},[n,s]=mo();e[n]=s;const i={headers:{...e,...this._options.headers},timeout:this._options.timeout,withCredentials:this._options.withCredentials};let l;try{await this._httpClient.delete(this._url,i)}catch(r){l=r}l?l instanceof Ns&&(l.statusCode===404?this._logger.log(q.Trace,"(LongPolling transport) A 404 response was returned from sending a DELETE request."):this._logger.log(q.Trace,`(LongPolling transport) Error sending a DELETE request: ${l}`)):this._logger.log(q.Trace,"(LongPolling transport) DELETE request accepted.")}finally{this._logger.log(q.Trace,"(LongPolling transport) Stop finished."),this._raiseOnClose()}}_raiseOnClose(){if(this.onclose){let e="(LongPolling transport) Firing onclose event.";this._closeError&&(e+=" Error: "+this._closeError),this._logger.log(q.Trace,e),this.onclose(this._closeError)}}}class eE{constructor(e,n,s,i){this._httpClient=e,this._accessToken=n,this._logger=s,this._options=i,this.onreceive=null,this.onclose=null}async connect(e,n){return Tt.isRequired(e,"url"),Tt.isRequired(n,"transferFormat"),Tt.isIn(n,Nt,"transferFormat"),this._logger.log(q.Trace,"(SSE transport) Connecting."),this._url=e,this._accessToken&&(e+=(e.indexOf("?")<0?"?":"&")+`access_token=${encodeURIComponent(this._accessToken)}`),new Promise((s,i)=>{let l=!1;if(n!==Nt.Text){i(new Error("The Server-Sent Events transport only supports the 'Text' transfer format"));return}let r;if(wt.isBrowser||wt.isWebWorker)r=new this._options.EventSource(e,{withCredentials:this._options.withCredentials});else{const c=this._httpClient.getCookieString(e),u={};u.Cookie=c;const[h,f]=mo();u[h]=f,r=new this._options.EventSource(e,{withCredentials:this._options.withCredentials,headers:{...u,...this._options.headers}})}try{r.onmessage=c=>{if(this.onreceive)try{this._logger.log(q.Trace,`(SSE transport) data received. ${Xo(c.data,this._options.logMessageContent)}.`),this.onreceive(c.data)}catch(u){this._close(u);return}},r.onerror=c=>{l?this._close():i(new Error("EventSource failed to connect. The connection could not be found on the server, either the connection ID is not present on the server, or a proxy is refusing/buffering the connection. If you have multiple servers check that sticky sessions are enabled."))},r.onopen=()=>{this._logger.log(q.Information,`SSE connected to ${this._url}`),this._eventSource=r,l=!0,s()}}catch(c){i(c);return}})}async send(e){return this._eventSource?Qf(this._logger,"SSE",this._httpClient,this._url,e,this._options):Promise.reject(new Error("Cannot send until the transport is connected"))}stop(){return this._close(),Promise.resolve()}_close(e){this._eventSource&&(this._eventSource.close(),this._eventSource=void 0,this.onclose&&this.onclose(e))}}class tE{constructor(e,n,s,i,l,r){this._logger=s,this._accessTokenFactory=n,this._logMessageContent=i,this._webSocketConstructor=l,this._httpClient=e,this.onreceive=null,this.onclose=null,this._headers=r}async connect(e,n){Tt.isRequired(e,"url"),Tt.isRequired(n,"transferFormat"),Tt.isIn(n,Nt,"transferFormat"),this._logger.log(q.Trace,"(WebSockets transport) Connecting.");let s;return this._accessTokenFactory&&(s=await this._accessTokenFactory()),new Promise((i,l)=>{e=e.replace(/^http/,"ws");let r;const c=this._httpClient.getCookieString(e);let u=!1;if(wt.isNode||wt.isReactNative){const h={},[f,g]=mo();h[f]=g,s&&(h[Fs.Authorization]=`Bearer ${s}`),c&&(h[Fs.Cookie]=c),r=new this._webSocketConstructor(e,void 0,{headers:{...h,...this._headers}})}else s&&(e+=(e.indexOf("?")<0?"?":"&")+`access_token=${encodeURIComponent(s)}`);r||(r=new this._webSocketConstructor(e)),n===Nt.Binary&&(r.binaryType="arraybuffer"),r.onopen=h=>{this._logger.log(q.Information,`WebSocket connected to ${e}.`),this._webSocket=r,u=!0,i()},r.onerror=h=>{let f=null;typeof ErrorEvent<"u"&&h instanceof ErrorEvent?f=h.error:f="There was an error with the transport",this._logger.log(q.Information,`(WebSockets transport) ${f}.`)},r.onmessage=h=>{if(this._logger.log(q.Trace,`(WebSockets transport) data received. ${Xo(h.data,this._logMessageContent)}.`),this.onreceive)try{this.onreceive(h.data)}catch(f){this._close(f);return}},r.onclose=h=>{if(u)this._close(h);else{let f=null;typeof ErrorEvent<"u"&&h instanceof ErrorEvent?f=h.error:f="WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.",l(new Error(f))}}})}send(e){return this._webSocket&&this._webSocket.readyState===this._webSocketConstructor.OPEN?(this._logger.log(q.Trace,`(WebSockets transport) sending data. ${Xo(e,this._logMessageContent)}.`),this._webSocket.send(e),Promise.resolve()):Promise.reject("WebSocket is not in the OPEN state")}stop(){return this._webSocket&&this._close(void 0),Promise.resolve()}_close(e){this._webSocket&&(this._webSocket.onclose=()=>{},this._webSocket.onmessage=()=>{},this._webSocket.onerror=()=>{},this._webSocket.close(),this._webSocket=void 0),this._logger.log(q.Trace,"(WebSockets transport) socket closed."),this.onclose&&(this._isCloseEvent(e)&&(e.wasClean===!1||e.code!==1e3)?this.onclose(new Error(`WebSocket closed with status code: ${e.code} (${e.reason||"no reason given"}).`)):e instanceof Error?this.onclose(e):this.onclose())}_isCloseEvent(e){return e&&typeof e.wasClean=="boolean"&&typeof e.code=="number"}}const td=100;class nE{constructor(e,n={}){if(this._stopPromiseResolver=()=>{},this.features={},this._negotiateVersion=1,Tt.isRequired(e,"url"),this._logger=DS(n.logger),this.baseUrl=this._resolveUrl(e),n=n||{},n.logMessageContent=n.logMessageContent===void 0?!1:n.logMessageContent,typeof n.withCredentials=="boolean"||n.withCredentials===void 0)n.withCredentials=n.withCredentials===void 0?!0:n.withCredentials;else throw new Error("withCredentials option was not a 'boolean' or 'undefined' value");n.timeout=n.timeout===void 0?100*1e3:n.timeout;let s=null,i=null;if(wt.isNode&&typeof require<"u"){const l=typeof __webpack_require__=="function"?__non_webpack_require__:require;s=l("ws"),i=l("eventsource")}!wt.isNode&&typeof WebSocket<"u"&&!n.WebSocket?n.WebSocket=WebSocket:wt.isNode&&!n.WebSocket&&s&&(n.WebSocket=s),!wt.isNode&&typeof EventSource<"u"&&!n.EventSource?n.EventSource=EventSource:wt.isNode&&!n.EventSource&&typeof i<"u"&&(n.EventSource=i),this._httpClient=new YS(n.httpClient||new VS(this._logger),n.accessTokenFactory),this._connectionState="Disconnected",this._connectionStarted=!1,this._options=n,this.onreceive=null,this.onclose=null}async start(e){if(e=e||Nt.Binary,Tt.isIn(e,Nt,"transferFormat"),this._logger.log(q.Debug,`Starting connection with transfer format '${Nt[e]}'.`),this._connectionState!=="Disconnected")return Promise.reject(new Error("Cannot start an HttpConnection that is not in the 'Disconnected' state."));if(this._connectionState="Connecting",this._startInternalPromise=this._startInternal(e),await this._startInternalPromise,this._connectionState==="Disconnecting"){const n="Failed to start the HttpConnection before stop() was called.";return this._logger.log(q.Error,n),await this._stopPromise,Promise.reject(new kn(n))}else if(this._connectionState!=="Connected"){const n="HttpConnection.startInternal completed gracefully but didn't enter the connection into the connected state!";return this._logger.log(q.Error,n),Promise.reject(new kn(n))}this._connectionStarted=!0}send(e){return this._connectionState!=="Connected"?Promise.reject(new Error("Cannot send data if the connection is not in the 'Connected' State.")):(this._sendQueue||(this._sendQueue=new ll(this.transport)),this._sendQueue.send(e))}async stop(e){if(this._connectionState==="Disconnected")return this._logger.log(q.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnected state.`),Promise.resolve();if(this._connectionState==="Disconnecting")return this._logger.log(q.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnecting state.`),this._stopPromise;this._connectionState="Disconnecting",this._stopPromise=new Promise(n=>{this._stopPromiseResolver=n}),await this._stopInternal(e),await this._stopPromise}async _stopInternal(e){this._stopError=e;try{await this._startInternalPromise}catch{}if(this.transport){try{await this.transport.stop()}catch(n){this._logger.log(q.Error,`HttpConnection.transport.stop() threw error '${n}'.`),this._stopConnection()}this.transport=void 0}else this._logger.log(q.Debug,"HttpConnection.transport is undefined in HttpConnection.stop() because start() failed.")}async _startInternal(e){let n=this.baseUrl;this._accessTokenFactory=this._options.accessTokenFactory,this._httpClient._accessTokenFactory=this._accessTokenFactory;try{if(this._options.skipNegotiation)if(this._options.transport===Pt.WebSockets)this.transport=this._constructTransport(Pt.WebSockets),await this._startTransport(n,e);else throw new Error("Negotiation can only be skipped when using the WebSocket transport directly.");else{let s=null,i=0;do{if(s=await this._getNegotiationResponse(n),this._connectionState==="Disconnecting"||this._connectionState==="Disconnected")throw new kn("The connection was stopped during negotiation.");if(s.error)throw new Error(s.error);if(s.ProtocolVersion)throw new Error("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.");if(s.url&&(n=s.url),s.accessToken){const l=s.accessToken;this._accessTokenFactory=()=>l,this._httpClient._accessToken=l,this._httpClient._accessTokenFactory=void 0}i++}while(s.url&&i0?Promise.reject(new IS(`Unable to connect to the server with any of the available transports. ${r.join(" ")}`,r)):Promise.reject(new Error("None of the transports supported by the client are supported by the server."))}_constructTransport(e){switch(e){case Pt.WebSockets:if(!this._options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new tE(this._httpClient,this._accessTokenFactory,this._logger,this._options.logMessageContent,this._options.WebSocket,this._options.headers||{});case Pt.ServerSentEvents:if(!this._options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new eE(this._httpClient,this._httpClient._accessToken,this._logger,this._options);case Pt.LongPolling:return new ed(this._httpClient,this._logger,this._options);default:throw new Error(`Unknown transport: ${e}.`)}}_startTransport(e,n){return this.transport.onreceive=this.onreceive,this.features.reconnect?this.transport.onclose=async s=>{let i=!1;if(this.features.reconnect)try{this.features.disconnected(),await this.transport.connect(e,n),await this.features.resend()}catch{i=!0}else{this._stopConnection(s);return}i&&this._stopConnection(s)}:this.transport.onclose=s=>this._stopConnection(s),this.transport.connect(e,n)}_resolveTransportOrError(e,n,s,i){const l=Pt[e.transport];if(l==null)return this._logger.log(q.Debug,`Skipping transport '${e.transport}' because it is not supported by this client.`),new Error(`Skipping transport '${e.transport}' because it is not supported by this client.`);if(sE(n,l))if(e.transferFormats.map(c=>Nt[c]).indexOf(s)>=0){if(l===Pt.WebSockets&&!this._options.WebSocket||l===Pt.ServerSentEvents&&!this._options.EventSource)return this._logger.log(q.Debug,`Skipping transport '${Pt[l]}' because it is not supported in your environment.'`),new AS(`'${Pt[l]}' is not supported in your environment.`,l);this._logger.log(q.Debug,`Selecting transport '${Pt[l]}'.`);try{return this.features.reconnect=l===Pt.WebSockets?i:void 0,this._constructTransport(l)}catch(c){return c}}else return this._logger.log(q.Debug,`Skipping transport '${Pt[l]}' because it does not support the requested transfer format '${Nt[s]}'.`),new Error(`'${Pt[l]}' does not support ${Nt[s]}.`);else return this._logger.log(q.Debug,`Skipping transport '${Pt[l]}' because it was disabled by the client.`),new RS(`'${Pt[l]}' is disabled by the client.`,l)}_isITransport(e){return e&&typeof e=="object"&&"connect"in e}_stopConnection(e){if(this._logger.log(q.Debug,`HttpConnection.stopConnection(${e}) called while in state ${this._connectionState}.`),this.transport=void 0,e=this._stopError||e,this._stopError=void 0,this._connectionState==="Disconnected"){this._logger.log(q.Debug,`Call to HttpConnection.stopConnection(${e}) was ignored because the connection is already in the disconnected state.`);return}if(this._connectionState==="Connecting")throw this._logger.log(q.Warning,`Call to HttpConnection.stopConnection(${e}) was ignored because the connection is still in the connecting state.`),new Error(`HttpConnection.stopConnection(${e}) was called while the connection is still in the connecting state.`);if(this._connectionState==="Disconnecting"&&this._stopPromiseResolver(),e?this._logger.log(q.Error,`Connection disconnected with error '${e}'.`):this._logger.log(q.Information,"Connection disconnected."),this._sendQueue&&(this._sendQueue.stop().catch(n=>{this._logger.log(q.Error,`TransportSendQueue.stop() threw error '${n}'.`)}),this._sendQueue=void 0),this.connectionId=void 0,this._connectionState="Disconnected",this._connectionStarted){this._connectionStarted=!1;try{this.onclose&&this.onclose(e)}catch(n){this._logger.log(q.Error,`HttpConnection.onclose(${e}) threw error '${n}'.`)}}}_resolveUrl(e){if(e.lastIndexOf("https://",0)===0||e.lastIndexOf("http://",0)===0)return e;if(!wt.isBrowser)throw new Error(`Cannot resolve '${e}'.`);const n=window.document.createElement("a");return n.href=e,this._logger.log(q.Information,`Normalizing '${e}' to '${n.href}'.`),n.href}_resolveNegotiateUrl(e){const n=new URL(e);n.pathname.endsWith("/")?n.pathname+="negotiate":n.pathname+="/negotiate";const s=new URLSearchParams(n.searchParams);return s.has("negotiateVersion")||s.append("negotiateVersion",this._negotiateVersion.toString()),s.has("useStatefulReconnect")?s.get("useStatefulReconnect")==="true"&&(this._options._useStatefulReconnect=!0):this._options._useStatefulReconnect===!0&&s.append("useStatefulReconnect","true"),n.search=s.toString(),n.toString()}}function sE(t,e){return!t||(e&t)!==0}class ll{constructor(e){this._transport=e,this._buffer=[],this._executing=!0,this._sendBufferedData=new Ri,this._transportResult=new Ri,this._sendLoopPromise=this._sendLoop()}send(e){return this._bufferData(e),this._transportResult||(this._transportResult=new Ri),this._transportResult.promise}stop(){return this._executing=!1,this._sendBufferedData.resolve(),this._sendLoopPromise}_bufferData(e){if(this._buffer.length&&typeof this._buffer[0]!=typeof e)throw new Error(`Expected data to be of type ${typeof this._buffer} but was of type ${typeof e}`);this._buffer.push(e),this._sendBufferedData.resolve()}async _sendLoop(){for(;;){if(await this._sendBufferedData.promise,!this._executing){this._transportResult&&this._transportResult.reject("Connection stopped.");break}this._sendBufferedData=new Ri;const e=this._transportResult;this._transportResult=void 0;const n=typeof this._buffer[0]=="string"?this._buffer.join(""):ll._concatBuffers(this._buffer);this._buffer.length=0;try{await this._transport.send(n),e.resolve()}catch(s){e.reject(s)}}}static _concatBuffers(e){const n=e.map(l=>l.byteLength).reduce((l,r)=>l+r),s=new Uint8Array(n);let i=0;for(const l of e)s.set(new Uint8Array(l),i),i+=l.byteLength;return s.buffer}}class Ri{constructor(){this.promise=new Promise((e,n)=>[this._resolver,this._rejecter]=[e,n])}resolve(){this._resolver()}reject(e){this._rejecter(e)}}const oE="json";class iE{constructor(){this.name=oE,this.version=2,this.transferFormat=Nt.Text}parseMessages(e,n){if(typeof e!="string")throw new Error("Invalid input for JSON hub protocol. Expected a string.");if(!e)return[];n===null&&(n=Jo.instance);const s=ln.parse(e),i=[];for(const l of s){const r=JSON.parse(l);if(typeof r.type!="number")throw new Error("Invalid payload.");switch(r.type){case xe.Invocation:this._isInvocationMessage(r);break;case xe.StreamItem:this._isStreamItemMessage(r);break;case xe.Completion:this._isCompletionMessage(r);break;case xe.Ping:break;case xe.Close:break;case xe.Ack:this._isAckMessage(r);break;case xe.Sequence:this._isSequenceMessage(r);break;default:n.log(q.Information,"Unknown message type '"+r.type+"' ignored.");continue}i.push(r)}return i}writeMessage(e){return ln.write(JSON.stringify(e))}_isInvocationMessage(e){this._assertNotEmptyString(e.target,"Invalid payload for Invocation message."),e.invocationId!==void 0&&this._assertNotEmptyString(e.invocationId,"Invalid payload for Invocation message.")}_isStreamItemMessage(e){if(this._assertNotEmptyString(e.invocationId,"Invalid payload for StreamItem message."),e.item===void 0)throw new Error("Invalid payload for StreamItem message.")}_isCompletionMessage(e){if(e.result&&e.error)throw new Error("Invalid payload for Completion message.");!e.result&&e.error&&this._assertNotEmptyString(e.error,"Invalid payload for Completion message."),this._assertNotEmptyString(e.invocationId,"Invalid payload for Completion message.")}_isAckMessage(e){if(typeof e.sequenceId!="number")throw new Error("Invalid SequenceId for Ack message.")}_isSequenceMessage(e){if(typeof e.sequenceId!="number")throw new Error("Invalid SequenceId for Sequence message.")}_assertNotEmptyString(e,n){if(typeof e!="string"||e==="")throw new Error(n)}}const rE={trace:q.Trace,debug:q.Debug,info:q.Information,information:q.Information,warn:q.Warning,warning:q.Warning,error:q.Error,critical:q.Critical,none:q.None};function aE(t){const e=rE[t.toLowerCase()];if(typeof e<"u")return e;throw new Error(`Unknown log level: ${t}`)}class lE{configureLogging(e){if(Tt.isRequired(e,"logging"),cE(e))this.logger=e;else if(typeof e=="string"){const n=aE(e);this.logger=new Ji(n)}else this.logger=new Ji(e);return this}withUrl(e,n){return Tt.isRequired(e,"url"),Tt.isNotEmpty(e,"url"),this.url=e,typeof n=="object"?this.httpConnectionOptions={...this.httpConnectionOptions,...n}:this.httpConnectionOptions={...this.httpConnectionOptions,transport:n},this}withHubProtocol(e){return Tt.isRequired(e,"protocol"),this.protocol=e,this}withAutomaticReconnect(e){if(this.reconnectPolicy)throw new Error("A reconnectPolicy has already been set.");return e?Array.isArray(e)?this.reconnectPolicy=new Zu(e):this.reconnectPolicy=e:this.reconnectPolicy=new Zu,this}withServerTimeout(e){return Tt.isRequired(e,"milliseconds"),this._serverTimeoutInMilliseconds=e,this}withKeepAliveInterval(e){return Tt.isRequired(e,"milliseconds"),this._keepAliveIntervalInMilliseconds=e,this}withStatefulReconnect(e){return this.httpConnectionOptions===void 0&&(this.httpConnectionOptions={}),this.httpConnectionOptions._useStatefulReconnect=!0,this._statefulReconnectBufferSize=e==null?void 0:e.bufferSize,this}build(){const e=this.httpConnectionOptions||{};if(e.logger===void 0&&(e.logger=this.logger),!this.url)throw new Error("The 'HubConnectionBuilder.withUrl' method must be called before building the connection.");const n=new nE(this.url,e);return al.create(n,this.logger||Jo.instance,this.protocol||new iE,this.reconnectPolicy,this._serverTimeoutInMilliseconds,this._keepAliveIntervalInMilliseconds,this._statefulReconnectBufferSize)}}function cE(t){return t.log!==void 0}class uE{constructor(){this.connection=null,this.messageHandlers=[],this.token="",this.isConnecting=!1,this.reconnectAttempts=0,this.maxReconnectAttempts=5}async connect(e){if(this.isConnecting){console.log("SignalR: Already connecting...");return}if(this.connection&&this.token===e&&this.connection.state===ut.Connected){console.log("SignalR: Already connected to",e);return}await this.disconnect(),this.isConnecting=!0,this.token=e;try{const n=`${window.location.origin}/signalr`;this.connection=new lE().withUrl(n).withAutomaticReconnect({nextRetryDelayInMilliseconds:s=>Math.min(1e3*Math.pow(2,s.previousRetryCount),16e3)}).configureLogging(q.Information).build(),this.connection.on("message",s=>{console.log("SignalR: Received message",s),this.messageHandlers.forEach(i=>{try{i(s)}catch(l){console.error("SignalR: Error in message handler",l)}})}),this.connection.onclose(s=>{console.log("SignalR: Connection closed",s)}),this.connection.onreconnecting(s=>{console.log("SignalR: Reconnecting...",s)}),this.connection.onreconnected(s=>{console.log("SignalR: Reconnected with ID:",s),this.registerToken()}),await this.connection.start(),console.log("SignalR: Connected successfully"),await this.registerToken(),this.reconnectAttempts=0}catch(n){if(console.error("SignalR: Connection error",n),this.reconnectAttempts++,this.reconnectAttemptsthis.connect(e),s)}}finally{this.isConnecting=!1}}async registerToken(){if(this.connection&&this.connection.state===ut.Connected&&this.token)try{await this.connection.invoke("Token",this.token),console.log("SignalR: Token registered:",this.token)}catch(e){console.error("SignalR: Error registering token",e)}}async disconnect(){if(this.connection){try{await this.connection.stop(),console.log("SignalR: Disconnected")}catch(e){console.error("SignalR: Error disconnecting",e)}this.connection=null}this.token="",this.reconnectAttempts=0}onMessage(e){return this.messageHandlers.push(e),()=>{const n=this.messageHandlers.indexOf(e);n>-1&&this.messageHandlers.splice(n,1)}}clearHandlers(){this.messageHandlers=[]}isConnected(){var e;return((e=this.connection)==null?void 0:e.state)===ut.Connected}getState(){var e;return((e=this.connection)==null?void 0:e.state)??null}}const Oo=new uE,dE=$t({setup(){const e=ns().params.token,n=O([]),s=O(""),i=O(null),l=O([]),r=Xt({}),c=Xt({}),u=O(!1),h=O(""),f=O(""),g=O(""),C=O(!1),_=O(!1),y=O(1),P=O(50),I=O(0),H=Xt({}),W=Xt({}),G=Xt({}),F=Xt({}),ne=Xt({}),he=Xt({});O([]);function ce(k){const N=k.indexOf("{"),ue=k.lastIndexOf("}");return N>=0&&ue>N?k.substring(N,ue+1):""}function Ee(k){try{const N=ce(k);return N?(JSON.parse(N),!0):!1}catch{return!1}}function Se(k){try{const N=ce(k),ue=JSON.parse(N);return JSON.stringify(ue,null,2)}catch{return k}}function _e(k){H[k]=!H[k]}function ye(k){var N;k&&((N=navigator.clipboard)==null||N.writeText(k))}const Me=Ye(()=>{let k=n.value;if(f.value){const N=f.value.toLowerCase();k=k.filter(ue=>{var me,qe,Ot,Ut,mt,et,In,bn,ms,dt;return!!(ue.text&&ue.text.toLowerCase().includes(N)||(me=ue.chat)!=null&&me.title&&ue.chat.title.toLowerCase().includes(N)||(qe=ue.chat)!=null&&qe.id&&ue.chat.id.toLowerCase().includes(N)||(Ot=ue.chat)!=null&&Ot.phone&&ue.chat.phone.toLowerCase().includes(N)||(Ut=ue.chat)!=null&&Ut.lid&&ue.chat.lid.toLowerCase().includes(N)||(mt=ue.chat)!=null&&mt.LId&&ue.chat.LId.toLowerCase().includes(N)||ue.from&&ue.from.toLowerCase().includes(N)||(et=ue.participant)!=null&&et.id&&ue.participant.id.toLowerCase().includes(N)||(In=ue.participant)!=null&&In.phone&&ue.participant.phone.toLowerCase().includes(N)||(bn=ue.participant)!=null&&bn.lid&&ue.participant.lid.toLowerCase().includes(N)||(ms=ue.participant)!=null&&ms.LId&&ue.participant.LId.toLowerCase().includes(N)||(dt=ue.participant)!=null&&dt.title&&ue.participant.title.toLowerCase().includes(N))})}return g.value&&(k=k.filter(N=>g.value==="text"?N.type==="text"||!N.attachment&&N.text:g.value==="image"?N.attachment&&te(N.attachment):g.value==="audio"?N.attachment&&Le(N.attachment):g.value==="video"?N.attachment&&Y(N.attachment):g.value==="document"?N.attachment&&!te(N.attachment)&&!Le(N.attachment)&&!Y(N.attachment):!0)),C.value&&(k=k.filter(N=>{var me;return(((me=N.chat)==null?void 0:me.id)||N.from||"").endsWith("@g.us")})),k});async function ve(){var k,N,ue,me,qe,Ot,Ut,mt;for(const et in W)delete W[et];u.value=!0,h.value="";try{const et=await be.get(`/api/server/${e}/messages`,{params:{page:y.value,limit:P.value,timestamp:0}});n.value=((k=et.data)==null?void 0:k.messages)||[],s.value=((N=et.data)==null?void 0:N.server.wid)||"",i.value=((ue=et.data)==null?void 0:ue.total)??((me=et.data)!=null&&me.messages?et.data.messages.length:null),I.value=((qe=et.data)==null?void 0:qe.total_pages)||0;try{const In=await be.get(`/api/server/${e}/contacts`);l.value=((Ot=In.data)==null?void 0:Ot.contacts)||[];for(const dt of l.value)dt.id&&(r[dt.id]=dt.title||""),dt.phone&&(r[dt.phone]=dt.title||""),dt.lid&&(r[dt.lid]=dt.title||"");const bn=new Set;for(const dt of n.value)dt.chat&&dt.chat.id&&bn.add(dt.chat.id),dt.participant&&(dt.participant.id||dt.participant.phone)&&bn.add(dt.participant.id||dt.participant.phone);const ms=[];for(const dt of bn){if(c[dt])continue;const mr=be.get(`/api/picinfo/${encodeURIComponent(dt)}?token=${encodeURIComponent(e)}`).then(ss=>{ss&&ss.data&&ss.data.info&&ss.data.info.url&&(c[dt]=ss.data.info.url)}).catch(()=>{});ms.push(mr)}await Promise.all(ms)}catch{}}catch(et){h.value=((mt=(Ut=et==null?void 0:et.response)==null?void 0:Ut.data)==null?void 0:mt.result)||et.message||"Erro ao carregar mensagens"}finally{u.value=!1}}function te(k){var N;return(N=k==null?void 0:k.mimetype)==null?void 0:N.startsWith("image/")}function Le(k){var N;return(N=k==null?void 0:k.mimetype)==null?void 0:N.startsWith("audio/")}function Y(k){var N;return(N=k==null?void 0:k.mimetype)==null?void 0:N.startsWith("video/")}function oe(k){return k?k.attachment&&v(k.attachment)?v(k.attachment).startsWith("image/"):k.type==="image":!1}function Q(k){return k?k.attachment&&v(k.attachment)?v(k.attachment).startsWith("audio/"):k.type==="audio":!1}function Re(k){return k?k.attachment&&v(k.attachment)?v(k.attachment).startsWith("video/"):k.type==="video":!1}function He(k){return k!=null&&k.attachment&&(k.attachment.url||k.attachment.Url)?k.attachment.url||k.attachment.Url:`/api/server/${encodeURIComponent(e.trim())}/download/${encodeURIComponent(k.id)}`}function z(k){k.target.style.display="none"}function Qe(k){k&&delete c[k]}function Ke(k){return k?new Date(k).toLocaleString("pt-BR",{day:"2-digit",month:"2-digit",hour:"2-digit",minute:"2-digit"}):""}function yt(k){return k?k<1024?k+" B":k<1024*1024?(k/1024).toFixed(1)+" KB":(k/(1024*1024)).toFixed(1)+" MB":""}function gt(k){const N=["#7C3AED","#5B21B6","#8B5CF6","#34b7f1","#00a884"],ue=(k||"").split("").reduce((me,qe)=>me+qe.charCodeAt(0),0);return N[ue%N.length]}function Ae(k){return(k||"?").charAt(0).toUpperCase()}function M(k){var N;return k&&(((N=k.thumbnail)==null?void 0:N.url)||k.thumbnail||k.thumbnailUrl||k.ThumbnailUrl)||""}function ee(k){var N;return k&&(((N=k.thumbnail)==null?void 0:N.url)||k.thumbnail||k.thumbnailUrl||k.ThumbnailUrl)||""}function S(k){return k?typeof k.isvalidsize<"u"?!!k.isvalidsize:typeof k.IsValidSize<"u"?!!k.IsValidSize:typeof k.valid<"u"?!!k.valid:typeof k.status=="string"?k.status.toLowerCase()==="valid"||k.status.toLowerCase()==="ok":!0:!1}function x(k){return(k==null?void 0:k.filename)||(k==null?void 0:k.FileName)||(k==null?void 0:k.fileName)||(k==null?void 0:k.name)||"arquivo"}function Z(k){return(k==null?void 0:k.filelength)||(k==null?void 0:k.FileLength)||(k==null?void 0:k.FileLength)||0}function v(k){return(k==null?void 0:k.mimetype)||(k==null?void 0:k.Mimetype)||(k==null?void 0:k.MimeType)||""}function E(k){const N=v(k);return N&&N.toLowerCase().includes("pdf")}function R(k){const N=(k==null?void 0:k.chat)||{};return N.title&&N.title.length>0?N.title:N.id&&r[N.id]?r[N.id]:N.phone&&r[N.phone]?r[N.phone]:N.lid&&r[N.lid]?r[N.lid]:k!=null&&k.from&&r[k.from]?r[k.from]:N.title||N.phone||N.id||"Desconhecido"}async function j(k){var N,ue;if(!(!k||!k.id)){W[k.id]=!0;try{await be.post(`/api/server/${e}/messages/${k.id}/history/download`),await ve(),we("Mídia do histórico baixada","success")}catch(me){console.error("history download error",me),we(((ue=(N=me==null?void 0:me.response)==null?void 0:N.data)==null?void 0:ue.result)||(me==null?void 0:me.message)||"Erro ao baixar histórico","error")}finally{W[k.id]=!1}}}function K(k){k<1||k>I.value||(y.value=k,ve())}function V(){y.value=1,ve()}function le(k){!k||!k.id||(G[k.id]=!0,F[k.id]=k.text||"")}function ie(k){!k||!k.id||(G[k.id]=!1,F[k.id]="")}async function se(k){var ue,me;if(!k||!k.id)return;const N=F[k.id]||"";if(N.trim().length===0){we("Conteúdo vazio não permitido","error");return}try{await be.put(`/api/server/${encodeURIComponent(e.trim())}/message/${encodeURIComponent(k.id)}/edit`,{content:N}),G[k.id]=!1,await ve(),we("Mensagem editada","success")}catch(qe){we(((me=(ue=qe==null?void 0:qe.response)==null?void 0:ue.data)==null?void 0:me.result)||(qe==null?void 0:qe.message)||"Erro ao editar mensagem","error")}}async function X(k){var N,ue;if(!(!k||!k.id)&&confirm("Deseja realmente revogar esta mensagem?"))try{await be.delete(`/api/server/${encodeURIComponent(e.trim())}/message/${encodeURIComponent(k.id)}`),await ve(),we("Mensagem revogada","success")}catch(me){we(((ue=(N=me==null?void 0:me.response)==null?void 0:N.data)==null?void 0:ue.result)||(me==null?void 0:me.message)||"Erro ao revogar mensagem","error")}}async function $e(k){var N,ue;if(!(!k||!k.chat||!k.chat.id)&&confirm("Deseja arquivar esta conversa?")){he[k.chat.id]=!0;try{await be.post(`/api/server/${encodeURIComponent(e.trim())}/chat/archive`,{chatid:k.chat.id,archive:!0}),we("Conversa arquivada","success"),await ve()}catch(me){we(((ue=(N=me==null?void 0:me.response)==null?void 0:N.data)==null?void 0:ue.result)||(me==null?void 0:me.message)||"Erro ao arquivar","error")}finally{he[k.chat.id]=!1}}}async function de(k){var N,ue;if(!(!k||!k.chat||!k.chat.id)){ne[k.chat.id]=!0;try{await be.post(`/api/server/${encodeURIComponent(e.trim())}/chat/presence`,{chatid:k.chat.id,type:"composing"}),we("Indicador de presença enviado","success")}catch(me){we(((ue=(N=me==null?void 0:me.response)==null?void 0:N.data)==null?void 0:ue.result)||(me==null?void 0:me.message)||"Erro ao enviar presença","error")}finally{ne[k.chat.id]=!1}}}function Ce(k){const N=(k==null?void 0:k.participant)||{};return N.title&&N.title.length>0?N.title:N.phone&&r[N.phone]?r[N.phone]:N.id&&r[N.id]?r[N.id]:N.lid&&r[N.lid]?r[N.lid]:k!=null&&k.chat&&k.chat.title?k.chat.title:N.title||N.phone||N.id||"Desconhecido"}function Te(k){if(k!=null&&k.fromme){if(s.value&&s.value.length>0){const N=s.value;return r[N]?r[N]+" (Você)":"Você ("+N+")"}return"Você"}return R(k)}let Oe=null,Je=null;return cn(()=>{ve(),Oo.connect(e).then(()=>{console.log("Messages: SignalR connected"),_.value=Oo.isConnected()}).catch(k=>{console.error("Messages: SignalR connection error",k),_.value=!1}),Je=setInterval(()=>{_.value=Oo.isConnected()},2e3),Oe=Oo.onMessage(k=>{var N,ue;if(console.log("Messages: Received new message via SignalR",k),k&&k.id&&!n.value.some(qe=>qe.id===k.id)){n.value.unshift(k),i.value!==null&&i.value++;const qe=(N=k.chat)==null?void 0:N.id;qe&&!c[qe]&&be.get(`/api/picinfo/${encodeURIComponent(qe)}?token=${encodeURIComponent(e)}`).then(Ut=>{var mt,et;(et=(mt=Ut==null?void 0:Ut.data)==null?void 0:mt.info)!=null&&et.url&&(c[qe]=Ut.data.info.url)}).catch(()=>{});const Ot=((ue=k.chat)==null?void 0:ue.title)||k.from||"Novo";we(`Nova mensagem de ${Ot}`,"info")}})}),bo(()=>{Oe&&(Oe(),Oe=null),Je&&(clearInterval(Je),Je=null),Oo.disconnect()}),{token:e,messages:n,serverNumber:s,totalMessages:i,loading:u,error:h,search:f,filterType:g,filterGroupsOnly:C,wsConnected:_,filteredMessages:Me,currentPage:y,messagesPerPage:P,totalPages:I,loadMessages:ve,isImage:te,isAudio:Le,isVideo:Y,getMediaUrl:He,handleImageError:z,handleAvatarError:Qe,formatTime:Ke,formatSize:yt,getAvatarColor:gt,getInitial:Ae,adThumbnailUrl:M,urlThumbnailUrl:ee,isAttachmentValid:S,contactPicMap:c,getFilename:x,getFileLength:Z,getMimetype:v,isPdf:E,getChatDisplayName:R,getParticipantDisplayName:Ce,getSenderDisplayName:Te,fetchingDownload:W,downloadHistory:j,editing:G,editContent:F,startEdit:le,cancelEdit:ie,saveEdit:se,revokeMessage:X,archiveChat:$e,sendPresence:de,archiving:he,presenceLoading:ne,isImageMessage:oe,isAudioMessage:Q,isVideoMessage:Re,goToPage:K,changePageSize:V,collapsed:H,isLikelyJson:Ee,extractJsonFromText:ce,prettyJson:Se,toggleCollapse:_e,copyText:ye}}}),fE={class:"messages-page"},hE={class:"page-header"},pE={class:"header-left"},gE={key:0,class:"header-sub"},mE={class:"text-muted"},vE={key:0,class:"ws-status ws-connected",title:"WebSocket conectado - Atualizações em tempo real"},bE={key:1,class:"ws-status ws-disconnected",title:"WebSocket desconectado"},yE={class:"header-actions"},wE=["disabled"],_E={key:0,class:"error-box"},CE={class:"filters-bar"},kE={class:"search-box"},SE={class:"filter-group"},EE={class:"filter-group"},$E={class:"messages-count"},TE={key:0,class:"text-muted"},AE={key:1,class:"pagination-controls"},RE=["disabled"],PE=["disabled"],IE={class:"page-info"},OE=["disabled"],ME=["disabled"],DE=["disabled"],LE={key:2,class:"loading-container"},NE={key:3,class:"empty-state"},FE={key:4,class:"messages-list"},xE=["id"],BE={class:"message-header"},zE={class:"message-sender"},HE={key:0,class:"sender-avatar sender-avatar-img"},UE=["src","onError"],VE={class:"sender-info"},jE={class:"sender-name"},qE={class:"sender-phone"},WE={key:0,class:"sender-lid"},KE={key:1,class:"chat-title"},GE={class:"message-meta"},QE={class:"message-time"},JE={class:"message-badges"},XE={key:0,class:"badge badge-sent"},YE={key:1,class:"badge badge-received"},ZE={key:2,class:"badge badge-status"},e5={key:3,class:"badge badge-warning"},t5={key:4,class:"badge badge-secondary"},n5={key:5,class:"badge badge-danger"},s5=["onClick","disabled"],o5={key:0,class:"message-participant"},i5={class:"participant-field",style:{display:"flex",gap:"8px","align-items":"center"}},r5={style:{display:"flex","align-items":"center",gap:"8px"}},a5=["src","onError"],l5={class:"participant-field"},c5={class:"participant-field"},u5={key:0,class:"participant-field"},d5={key:1,class:"participant-lid"},f5={class:"message-body"},h5={key:0,class:"message-text"},p5={key:0,class:"json-message"},g5={class:"json-controls"},m5=["onClick"],v5=["onClick"],b5=["onClick","disabled"],y5={key:0,class:"json-block"},w5={key:1,class:"json-collapsed"},_5={key:1},C5={key:1,class:"message-url"},k5={class:"url-preview"},S5={key:0},E5=["href"],$5={key:0,class:"url-thumbnail"},T5=["src"],A5={key:2,class:"message-ads"},R5={class:"ads-header"},P5={key:0},I5={class:"ads-meta"},O5={key:0},M5={key:1},D5={key:2},L5={key:0,class:"ads-thumbnail"},N5=["src"],F5=["href"],x5={key:3,class:"message-attachment"},B5={key:0,class:"attachment-image"},z5=["src","alt"],H5={class:"attachment-actions"},U5=["href","download"],V5=["href","download"],j5={key:1,class:"attachment-audio"},q5=["src"],W5={class:"attachment-actions"},K5=["href","download"],G5={key:2,class:"attachment-video"},Q5=["src"],J5={class:"attachment-actions"},X5=["href","download"],Y5={key:3,class:"attachment-file"},Z5={class:"file-info"},e$={class:"file-name"},t$={class:"file-size"},n$={class:"attachment-actions"},s$=["href"],o$=["href","download"],i$={key:4,class:"attachment-file"},r$={class:"file-info"},a$={class:"file-name"},l$={class:"file-size"},c$=["href","download"],u$={class:"attachment-status"},d$={key:0,class:"badge badge-success"},f$={key:1,class:"badge badge-danger"},h$={class:"attachment-meta"},p$={class:"mime-type"},g$={key:4,class:"message-reply"},m$=["href"],v$={key:5,class:"message-exceptions"},b$={class:"exceptions-list"},y$={class:"message-footer"},w$={class:"message-id"},_$={key:0,class:"message-trackid"},C$={class:"message-type"},k$={class:"message-actions"},S$=["onUpdate:modelValue"],E$=["onClick"],$$=["onClick"],T$=["onClick"],A$=["onClick"],R$=["onClick","disabled"],P$={key:5,class:"pagination-controls"},I$=["disabled"],O$=["disabled"],M$={class:"page-info"},D$=["disabled"],L$=["disabled"],N$=["disabled"];function F$(t,e,n,s,i,l){return b(),w("div",fE,[o("div",hE,[o("div",pE,[o("button",{onClick:e[0]||(e[0]=r=>t.$router.back()),class:"back-link hide-mobile"},[...e[18]||(e[18]=[o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"})],-1),L(" Voltar ",-1)])]),o("div",null,[e[21]||(e[21]=o("h1",null,"Mensagens Recebidas",-1)),t.serverNumber||t.totalMessages!==null?(b(),w("div",gE,[o("small",mE,"Servidor: "+A(t.serverNumber||"—")+" — Total: "+A(t.totalMessages!==null?t.totalMessages:t.messages.length)+" mensagens",1),t.wsConnected?(b(),w("span",vE,[...e[19]||(e[19]=[o("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"currentColor"},[o("circle",{cx:"12",cy:"12",r:"8"})],-1),L(" Live ",-1)])])):(b(),w("span",bE,[...e[20]||(e[20]=[o("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"currentColor"},[o("circle",{cx:"12",cy:"12",r:"8"})],-1),L(" Offline ",-1)])]))])):U("",!0)])]),o("div",yE,[o("button",{onClick:e[1]||(e[1]=(...r)=>t.loadMessages&&t.loadMessages(...r)),class:"btn-refresh",disabled:t.loading},[(b(),w("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor",class:ae({spinning:t.loading})},[...e[22]||(e[22]=[o("path",{d:"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"},null,-1)])],2)),e[23]||(e[23]=L(" Atualizar ",-1))],8,wE)])]),t.error?(b(),w("div",_E,[e[24]||(e[24]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)),o("span",null,A(t.error),1)])):U("",!0),o("div",CE,[o("div",kE,[e[25]||(e[25]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"})],-1)),Be(o("input",{"onUpdate:modelValue":e[2]||(e[2]=r=>t.search=r),type:"text",placeholder:"Buscar por texto, nome, número ou LId...",class:"search-input"},null,512),[[at,t.search]])]),o("div",SE,[e[27]||(e[27]=o("label",null,"Tipo:",-1)),Be(o("select",{"onUpdate:modelValue":e[3]||(e[3]=r=>t.filterType=r),class:"filter-select"},[...e[26]||(e[26]=[Cn('',6)])],512),[[zo,t.filterType]])]),o("div",EE,[o("label",null,[Be(o("input",{type:"checkbox","onUpdate:modelValue":e[4]||(e[4]=r=>t.filterGroupsOnly=r),class:"filter-checkbox"},null,512),[[_n,t.filterGroupsOnly]]),e[28]||(e[28]=L(" Apenas grupos ",-1))])]),o("div",$E,[L(A(t.filteredMessages.length)+" mensagens ",1),t.totalMessages!==null?(b(),w("span",TE," (Total: "+A(t.totalMessages)+")",1)):U("",!0)])]),t.messages.length>0||t.totalMessages!==null&&t.totalMessages>0?(b(),w("div",AE,[o("button",{onClick:e[5]||(e[5]=r=>t.goToPage(1)),disabled:t.currentPage===1||t.loading,class:"btn-page"},[...e[29]||(e[29]=[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M18.41 16.59L13.82 12l4.59-4.59L17 6l-6 6 6 6zM6 6h2v12H6z"})],-1)])],8,RE),o("button",{onClick:e[6]||(e[6]=r=>t.goToPage(t.currentPage-1)),disabled:t.currentPage===1||t.loading,class:"btn-page"},[...e[30]||(e[30]=[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"})],-1)])],8,PE),o("span",IE,"Página "+A(t.currentPage)+" de "+A(t.totalPages),1),o("button",{onClick:e[7]||(e[7]=r=>t.goToPage(t.currentPage+1)),disabled:t.currentPage>=t.totalPages||t.loading,class:"btn-page"},[...e[31]||(e[31]=[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"})],-1)])],8,OE),o("button",{onClick:e[8]||(e[8]=r=>t.goToPage(t.totalPages)),disabled:t.currentPage>=t.totalPages||t.loading,class:"btn-page"},[...e[32]||(e[32]=[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M5.59 7.41L10.18 12l-4.59 4.59L7 18l6-6-6-6zM16 6h2v12h-2z"})],-1)])],8,ME),Be(o("select",{"onUpdate:modelValue":e[9]||(e[9]=r=>t.messagesPerPage=r),onChange:e[10]||(e[10]=(...r)=>t.changePageSize&&t.changePageSize(...r)),class:"page-size-select",disabled:t.loading},[...e[33]||(e[33]=[o("option",{value:5},"5 por página",-1),o("option",{value:10},"10 por página",-1),o("option",{value:15},"15 por página",-1),o("option",{value:25},"25 por página",-1),o("option",{value:50},"50 por página",-1),o("option",{value:100},"100 por página",-1),o("option",{value:200},"200 por página",-1)])],40,DE),[[zo,t.messagesPerPage,void 0,{number:!0}]])])):U("",!0),t.loading?(b(),w("div",LE,[...e[34]||(e[34]=[o("div",{class:"spinner-large"},null,-1),o("p",null,"Carregando mensagens...",-1)])])):t.filteredMessages.length===0?(b(),w("div",NE,[...e[35]||(e[35]=[o("svg",{viewBox:"0 0 24 24",width:"64",height:"64",fill:"currentColor"},[o("path",{d:"M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"})],-1),o("h3",null,"Nenhuma mensagem encontrada",-1),o("p",null,"As mensagens recebidas aparecerão aqui",-1)])])):(b(),w("div",FE,[(b(!0),w(Xe,null,Yt(t.filteredMessages,r=>{var c,u,h,f,g,C,_,y,P,I,H,W,G,F,ne,he,ce,Ee,Se,_e,ye,Me;return b(),w("div",{key:r.id,id:"msg-"+r.id,class:ae(["message-card",{"from-me":r.fromme,"has-exceptions":((c=r.exceptions)==null?void 0:c.length)>0}])},[o("div",BE,[o("div",zE,[t.contactPicMap[(u=r.chat)==null?void 0:u.id]?(b(),w("div",HE,[o("img",{src:t.contactPicMap[(h=r.chat)==null?void 0:h.id],class:"avatar-img",onError:ve=>{var te;return t.handleAvatarError((te=r.chat)==null?void 0:te.id)}},null,40,UE)])):(b(),w("div",{key:1,class:"sender-avatar",style:Sn({background:t.getAvatarColor(((f=r.chat)==null?void 0:f.id)||r.from)})},A(t.getInitial(((g=r.chat)==null?void 0:g.title)||r.from)),5)),o("div",VE,[o("span",jE,A(t.getSenderDisplayName(r)),1),o("span",qE,A(r.fromme?t.serverNumber||((C=r.chat)==null?void 0:C.id)||r.from:((_=r.chat)==null?void 0:_.id)||r.from),1),(y=r.chat)!=null&&y.lid||(P=r.chat)!=null&&P.LId?(b(),w("small",WE,"LId: "+A(((I=r.chat)==null?void 0:I.lid)||((H=r.chat)==null?void 0:H.LId)),1)):U("",!0),(W=r.chat)!=null&&W.title?(b(),w("small",KE,"Chat: "+A(r.chat.title),1)):U("",!0)])]),o("div",GE,[o("div",QE,A(t.formatTime(r.timestamp)),1),o("div",JE,[r.fromme?(b(),w("span",XE,"Enviada")):(b(),w("span",YE,"Recebida")),r.status?(b(),w("span",ZE,A(r.status),1)):U("",!0),r.edited?(b(),w("span",e5,"Editada")):U("",!0),r.fromhistory?(b(),w("span",t5,"Histórico")):U("",!0),r.ads?(b(),w("span",n5,"Anúncio")):U("",!0)]),o("button",{class:"btn-small",onClick:ve=>t.archiveChat(r),disabled:t.archiving[(G=r.chat)==null?void 0:G.id]},A(t.archiving[(F=r.chat)==null?void 0:F.id]?"Arquivando...":"Arquivar conversa"),9,s5)])]),r.participant?(b(),w("div",o5,[e[40]||(e[40]=o("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"currentColor"},[o("path",{d:"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"})],-1)),o("div",null,[o("div",i5,[e[36]||(e[36]=o("strong",null,"Número:",-1)),o("div",r5,[t.contactPicMap[((ne=r.participant)==null?void 0:ne.id)||((he=r.participant)==null?void 0:he.phone)]?(b(),w("img",{key:0,src:t.contactPicMap[((ce=r.participant)==null?void 0:ce.id)||((Ee=r.participant)==null?void 0:Ee.phone)],alt:"avatar",class:"participant-avatar",onError:ve=>{var te,Le;return t.handleAvatarError(((te=r.participant)==null?void 0:te.id)||((Le=r.participant)==null?void 0:Le.phone))}},null,40,a5)):U("",!0),o("span",null,A(r.participant.phone),1)])]),o("div",l5,[e[37]||(e[37]=o("strong",null,"Lid:",-1)),L(" "+A(r.participant.id),1)]),o("div",c5,[e[38]||(e[38]=o("strong",null,"Nome:",-1)),L(" "+A(t.getParticipantDisplayName(r)),1)]),(Se=r.participant)!=null&&Se.title?(b(),w("div",u5,[e[39]||(e[39]=o("strong",null,"Título:",-1)),L(" "+A(r.participant.title),1)])):U("",!0),r.participant.lid||r.participant.LId?(b(),w("small",d5,"LId: "+A(r.participant.lid||r.participant.LId),1)):U("",!0)])])):U("",!0),o("div",f5,[r.text?(b(),w("div",h5,[t.isLikelyJson(r.text)?(b(),w("div",p5,[o("div",g5,[o("button",{class:"btn-small",onClick:ve=>t.toggleCollapse(r.id)},A(t.collapsed[r.id]?"Ocultar":"Mostrar"),9,m5),o("button",{class:"btn-small",onClick:ve=>t.copyText(t.extractJsonFromText(r.text))},"Copiar JSON",8,v5),r.debug&&r.debug.event==="ProtocolMessage"&&r.debug.reason&&r.debug.reason.includes("history sync")?(b(),w("button",{key:0,class:"btn-small",onClick:kt(ve=>t.downloadHistory(r),["prevent"]),disabled:t.fetchingDownload[r.id]},A(t.fetchingDownload[r.id]?"Baixando...":"Baixar mídia"),9,b5)):U("",!0)]),t.collapsed[r.id]?(b(),w("pre",y5,A(t.prettyJson(r.text)),1)):(b(),w("div",w5,"JSON ("+A(r.id)+")",1))])):(b(),w("div",_5,A(r.text),1))])):U("",!0),r.url?(b(),w("div",C5,[o("div",k5,[o("strong",null,A(r.url.title),1),r.url.description?(b(),w("p",S5,A(r.url.description),1)):U("",!0),o("a",{href:r.url.reference,target:"_blank",class:"url-link"},A(r.url.reference),9,E5)]),t.urlThumbnailUrl(r.url)?(b(),w("div",$5,[o("img",{src:t.urlThumbnailUrl(r.url),alt:"URL thumbnail"},null,8,T5)])):U("",!0)])):U("",!0),r.ads?(b(),w("div",A5,[o("div",R5,[e[41]||(e[41]=o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"})],-1)),o("span",null,[L("Anúncio: "+A(r.ads.title)+" ",1),r.ads.id?(b(),w("small",P5,"(#"+A(r.ads.id)+")",1)):U("",!0)])]),o("div",I5,[r.ads.sourceId?(b(),w("div",O5,[e[42]||(e[42]=o("strong",null,"Source ID:",-1)),L(" "+A(r.ads.sourceId),1)])):U("",!0),r.ads.app?(b(),w("div",M5,[e[43]||(e[43]=o("strong",null,"App:",-1)),L(" "+A(r.ads.app),1)])):U("",!0),r.ads.type?(b(),w("div",D5,[e[44]||(e[44]=o("strong",null,"Tipo:",-1)),L(" "+A(r.ads.type),1)])):U("",!0)]),t.adThumbnailUrl(r.ads)?(b(),w("div",L5,[o("img",{src:t.adThumbnailUrl(r.ads),alt:"Ad thumbnail"},null,8,N5)])):U("",!0),r.ads.sourceurl?(b(),w("a",{key:1,href:r.ads.sourceurl,target:"_blank",class:"ads-link"},"Ver anúncio",8,F5)):U("",!0)])):U("",!0),r.attachment?(b(),w("div",x5,[t.isImageMessage(r)?(b(),w("div",B5,[o("img",{src:t.getMediaUrl(r),alt:t.getFilename(r.attachment),onError:e[11]||(e[11]=(...ve)=>t.handleImageError&&t.handleImageError(...ve))},null,40,z5),o("div",H5,[o("a",{href:t.getMediaUrl(r),target:"_blank",class:"btn-download",download:t.getFilename(r.attachment)},"Abrir",8,U5),o("a",{href:t.getMediaUrl(r),download:t.getFilename(r.attachment),class:"btn-download"},"Baixar",8,V5)])])):t.isAudioMessage(r)?(b(),w("div",j5,[o("audio",{controls:"",src:t.getMediaUrl(r)},null,8,q5),o("div",W5,[o("a",{href:t.getMediaUrl(r),download:t.getFilename(r.attachment),class:"btn-download"},"Baixar áudio",8,K5)])])):t.isVideoMessage(r)?(b(),w("div",G5,[o("video",{controls:"",src:t.getMediaUrl(r)},null,8,Q5),o("div",J5,[o("a",{href:t.getMediaUrl(r),download:t.getFilename(r.attachment),class:"btn-download"},"Baixar vídeo",8,X5)])])):t.isPdf(r.attachment)?(b(),w("div",Y5,[o("div",Z5,[o("span",e$,A(t.getFilename(r.attachment)),1),o("span",t$,A(t.formatSize(t.getFileLength(r.attachment))),1)]),o("div",n$,[o("a",{href:t.getMediaUrl(r),target:"_blank",class:"btn-download"},"Abrir PDF",8,s$),o("a",{href:t.getMediaUrl(r),download:t.getFilename(r.attachment),class:"btn-download"},"Baixar",8,o$)])])):(b(),w("div",i$,[e[46]||(e[46]=o("svg",{viewBox:"0 0 24 24",width:"32",height:"32",fill:"currentColor"},[o("path",{d:"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"})],-1)),o("div",r$,[o("span",a$,A(t.getFilename(r.attachment)),1),o("span",l$,A(t.formatSize(t.getFileLength(r.attachment))),1)]),o("a",{href:t.getMediaUrl(r),download:t.getFilename(r.attachment),class:"btn-download"},[...e[45]||(e[45]=[o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"})],-1)])],8,c$)])),o("div",u$,[t.isAttachmentValid(r.attachment)?(b(),w("span",d$,"Válido")):(b(),w("span",f$,"Inválido"))]),o("div",h$,[o("span",p$,A(t.getMimetype(r.attachment)),1)])])):U("",!0),r.inreply?(b(),w("div",g$,[e[48]||(e[48]=o("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"currentColor"},[o("path",{d:"M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"})],-1)),o("span",null,[e[47]||(e[47]=L("Em resposta a: ",-1)),o("a",{href:"#msg-"+r.inreply},A(r.inreply),9,m$)])])):U("",!0),((_e=r.exceptions)==null?void 0:_e.length)>0?(b(),w("div",v$,[e[49]||(e[49]=o("div",{class:"exceptions-header"},[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"})]),o("span",null,"Erros de Dispatch:")],-1)),o("ul",b$,[(b(!0),w(Xe,null,Yt(r.exceptions,(ve,te)=>(b(),w("li",{key:te},A(ve),1))),128))])])):U("",!0)]),o("div",y$,[o("span",w$,"ID: "+A(r.id),1),r.trackid?(b(),w("span",_$,"Track: "+A(r.trackid),1)):U("",!0),o("span",C$,A(r.type),1),o("div",k$,[t.editing[r.id]?(b(),w(Xe,{key:0},[Be(o("input",{"onUpdate:modelValue":ve=>t.editContent[r.id]=ve,class:"edit-input"},null,8,S$),[[at,t.editContent[r.id]]]),o("button",{class:"btn-small me-1",onClick:ve=>t.saveEdit(r)},"Salvar",8,E$),o("button",{class:"btn-small",onClick:ve=>t.cancelEdit(r)},"Cancelar",8,$$)],64)):(b(),w(Xe,{key:1},[r.fromme?(b(),w("button",{key:0,class:"btn-small me-1",onClick:ve=>t.startEdit(r)},"Editar",8,T$)):U("",!0),o("button",{class:"btn-small me-1",onClick:ve=>t.revokeMessage(r)},"Cancelar Mensagem",8,A$),o("button",{class:"btn-small",onClick:ve=>t.sendPresence(r),disabled:t.presenceLoading[(ye=r.chat)==null?void 0:ye.id]},A(t.presenceLoading[(Me=r.chat)==null?void 0:Me.id]?"Enviando...":"Mostrar presença"),9,R$)],64))])])],10,xE)}),128))])),t.totalPages>1?(b(),w("div",P$,[o("button",{onClick:e[12]||(e[12]=r=>t.goToPage(1)),disabled:t.currentPage===1||t.loading,class:"btn-page"},[...e[50]||(e[50]=[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M18.41 16.59L13.82 12l4.59-4.59L17 6l-6 6 6 6zM6 6h2v12H6z"})],-1)])],8,I$),o("button",{onClick:e[13]||(e[13]=r=>t.goToPage(t.currentPage-1)),disabled:t.currentPage===1||t.loading,class:"btn-page"},[...e[51]||(e[51]=[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"})],-1)])],8,O$),o("span",M$,"Página "+A(t.currentPage)+" de "+A(t.totalPages),1),o("button",{onClick:e[14]||(e[14]=r=>t.goToPage(t.currentPage+1)),disabled:t.currentPage>=t.totalPages||t.loading,class:"btn-page"},[...e[52]||(e[52]=[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"})],-1)])],8,D$),o("button",{onClick:e[15]||(e[15]=r=>t.goToPage(t.totalPages)),disabled:t.currentPage>=t.totalPages||t.loading,class:"btn-page"},[...e[53]||(e[53]=[o("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"currentColor"},[o("path",{d:"M5.59 7.41L10.18 12l-4.59 4.59L7 18l6-6-6-6zM16 6h2v12h-2z"})],-1)])],8,L$),Be(o("select",{"onUpdate:modelValue":e[16]||(e[16]=r=>t.messagesPerPage=r),onChange:e[17]||(e[17]=(...r)=>t.changePageSize&&t.changePageSize(...r)),class:"page-size-select",disabled:t.loading},[...e[54]||(e[54]=[o("option",{value:5},"5 por página",-1),o("option",{value:10},"10 por página",-1),o("option",{value:15},"15 por página",-1),o("option",{value:25},"25 por página",-1),o("option",{value:50},"50 por página",-1),o("option",{value:100},"100 por página",-1),o("option",{value:200},"200 por página",-1)])],40,N$),[[zo,t.messagesPerPage,void 0,{number:!0}]])])):U("",!0)])}const x$=It(dE,[["render",F$],["__scopeId","data-v-9fa98ea1"]]),B$=$t({setup(){const e=ns().params.token,n=O(""),s=O(""),i=O("text"),l=O("file"),r=O(""),c=O(""),u=O(!1),h=O(""),f=O(""),g=O([]),C=O(""),_=O([]),y=O(!1),P=O(!1),I=O("");function H(){y.value=!0,C.value="",_.value=[]}function W(){y.value=!1}async function G(){var Ae,M,ee;if(!C.value){we("Digite nome ou telefone para buscar","error");return}P.value=!0,I.value="";try{const S=await be.post("/api/contact/search",{query:C.value});_.value=((Ae=S.data)==null?void 0:Ae.contacts)||[],_.value.length||we("Nenhum contato encontrado","info")}catch(S){I.value=((ee=(M=S==null?void 0:S.response)==null?void 0:M.data)==null?void 0:ee.result)||(S==null?void 0:S.message)||"Erro ao buscar contatos",we(I.value,"error")}finally{P.value=!1}}function F(Ae){Ae&&(n.value=Ae.phone||Ae.id||Ae.lid||"",y.value=!1,we(`Destinatário definido: ${n.value}`,"success"))}const ne=O(null),he=O(null),ce=O(null),Ee=O(null),Se=O(!1),_e=O("0:00"),ye=O(null),Me=O("");let ve=null,te=[],Le=null,Y=0;const oe=Ye(()=>new Date().toLocaleTimeString("pt-BR",{hour:"2-digit",minute:"2-digit"}));hs(i,Ae=>{Ae==="audio"?l.value="record":Ae!=="text"&&(l.value="file"),z(),yt(),r.value=""});function Q(Ae){return Ae?Ae.charAt(0):"?"}function Re(Ae){if(Ae===0)return"0 Bytes";const M=1024,ee=["Bytes","KB","MB","GB"],S=Math.floor(Math.log(Ae)/Math.log(M));return parseFloat((Ae/Math.pow(M,S)).toFixed(2))+" "+ee[S]}function He(Ae){const M=Ae.target;M.files&&M.files[0]&&(ne.value=M.files[0],i.value==="document"&&!c.value&&(c.value=ne.value.name))}function z(){ne.value=null}async function Qe(){try{const Ae=await navigator.mediaDevices.getUserMedia({audio:!0});ve=new MediaRecorder(Ae),te=[],ve.ondataavailable=M=>{te.push(M.data)},ve.onstop=()=>{const M=new Blob(te,{type:"audio/ogg; codecs=opus"});ye.value=M,Me.value=URL.createObjectURL(M),Ae.getTracks().forEach(ee=>ee.stop())},ve.start(),Se.value=!0,Y=Date.now(),Le=window.setInterval(()=>{const M=Math.floor((Date.now()-Y)/1e3),ee=Math.floor(M/60),S=M%60;_e.value=`${ee}:${S.toString().padStart(2,"0")}`},1e3)}catch{h.value="Não foi possível acessar o microfone"}}function Ke(){ve&&Se.value&&(ve.stop(),Se.value=!1,Le&&(clearInterval(Le),Le=null))}function yt(){ye.value=null,Me.value&&(URL.revokeObjectURL(Me.value),Me.value=""),_e.value="0:00"}bo(()=>{Le&&clearInterval(Le),Me.value&&URL.revokeObjectURL(Me.value)});async function gt(){var Ae,M;u.value=!0,h.value="",f.value="";try{if(i.value==="text"){const ee={recipient:n.value,message:s.value};await be.post(`/api/server/${e}/send`,ee)}else{const ee=ne.value||ye.value;if(l.value!=="url"&&ee){const S=new FormData;S.append("chatid",n.value),ye.value?S.append("attach",ye.value,"audio.ogg"):ne.value&&S.append("attach",ne.value),s.value&&S.append("text",s.value),c.value&&S.append("filename",c.value),await be.post(`/bot/${e}/sendattach`,S,{headers:{"X-QUEPASA-TOKEN":e,"Content-Type":"multipart/form-data"}})}else{const S={chatid:n.value,url:r.value};s.value&&(S.text=s.value),c.value&&(S.filename=c.value),await be.post(`/bot/${e}/send`,S,{headers:{"X-QUEPASA-TOKEN":e}})}}f.value=`Mensagem enviada para +${n.value}`,g.value.unshift({to:n.value}),g.value.length>5&&g.value.pop(),s.value="",r.value="",c.value="",z(),yt()}catch(ee){h.value=((M=(Ae=ee==null?void 0:ee.response)==null?void 0:Ae.data)==null?void 0:M.result)||ee.message||"Erro ao enviar mensagem",g.value.unshift({to:n.value,error:!0}),g.value.length>5&&g.value.pop()}finally{u.value=!1}}return{token:e,recipient:n,text:s,msgType:i,mediaSource:l,attachmentUrl:r,filename:c,sending:u,error:h,success:f,recentSends:g,currentTime:oe,selectedFile:ne,isRecording:Se,recordingTime:_e,audioBlob:ye,audioUrl:Me,imageInput:he,docInput:ce,audioInput:Ee,getInitial:Q,sendMessage:gt,formatFileSize:Re,handleFileSelect:He,clearFile:z,startRecording:Qe,stopRecording:Ke,clearAudio:yt,contactSearchQuery:C,contactSearchResults:_,contactSearchVisible:y,contactSearchLoading:P,openContactSearch:H,closeContactSearch:W,searchContacts:G,selectContact:F}}}),z$={class:"send-page"},H$={class:"page-header"},U$={class:"header-content"},V$={class:"content-grid"},j$={class:"send-card"},q$={key:0,class:"error-box"},W$={key:1,class:"success-box"},K$={class:"form-group"},G$={class:"input-wrapper"},Q$={key:0,class:"contact-search"},J$={class:"contact-search-controls"},X$={class:"contact-search-list"},Y$={key:0},Z$={key:1},e6={key:2},t6=["onClick"],n6={class:"form-group"},s6={class:"message-tabs"},o6={key:0,class:"form-group"},i6={class:"input-hint"},r6={key:1,class:"form-group"},a6={class:"source-tabs"},l6={key:2,class:"form-group"},c6={key:0,class:"upload-placeholder"},u6={key:1,class:"file-selected"},d6={class:"file-info"},f6={class:"file-name"},h6={class:"file-size"},p6={key:3,class:"form-group"},g6={key:4,class:"form-group"},m6={key:5,class:"form-group"},v6={class:"source-tabs"},b6={key:6,class:"form-group"},y6={key:0,class:"upload-placeholder"},w6={key:1,class:"file-selected"},_6={class:"file-info"},C6={class:"file-name"},k6={class:"file-size"},S6={key:7,class:"form-group"},E6={key:8,class:"form-group"},$6={key:9,class:"form-group"},T6={class:"source-tabs"},A6={key:10,class:"form-group"},R6={key:0,class:"recorder-idle"},P6={key:1,class:"recorder-active"},I6={class:"recording-indicator"},O6={class:"recording-time"},M6={key:2,class:"recorder-done"},D6=["src"],L6={key:11,class:"form-group"},N6={key:0,class:"upload-placeholder"},F6={key:1,class:"file-selected"},x6={class:"file-info"},B6={class:"file-name"},z6={class:"file-size"},H6={key:12,class:"form-group"},U6=["disabled"],V6={key:0,class:"spinner"},j6={key:1,viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},q6={class:"preview-card"},W6={class:"phone-mockup"},K6={class:"phone-header"},G6={class:"contact-info"},Q6={class:"contact-avatar"},J6={class:"phone-messages"},X6={class:"message-bubble sent"},Y6={key:0,class:"bubble-text"},Z6={key:1,class:"bubble-media"},e9={key:0,class:"bubble-text"},t9={key:2,class:"bubble-media"},n9={class:"media-placeholder file"},s9={class:"bubble-time"},o9={key:0,class:"recent-sends"},i9={class:"recent-list"},r9={class:"recent-to"},a9={class:"recent-status"};function l9(t,e,n,s,i,l){return b(),w("div",z$,[o("div",H$,[o("div",U$,[o("button",{onClick:e[0]||(e[0]=r=>t.$router.back()),class:"back-link"},[...e[37]||(e[37]=[o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"})],-1),L(" Voltar ",-1)])]),e[38]||(e[38]=o("h1",null,"Enviar Mensagem",-1)),e[39]||(e[39]=o("p",null,"Envie mensagens via WhatsApp",-1))])]),o("div",V$,[o("div",j$,[t.error?(b(),w("div",q$,[e[40]||(e[40]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)),o("span",null,A(t.error),1)])):U("",!0),t.success?(b(),w("div",W$,[e[41]||(e[41]=o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L18 9l-9 9z"})],-1)),o("span",null,A(t.success),1)])):U("",!0),o("form",{onSubmit:e[36]||(e[36]=kt((...r)=>t.sendMessage&&t.sendMessage(...r),["prevent"])),class:"send-form"},[o("div",K$,[e[43]||(e[43]=o("label",{for:"recipient"},[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"})]),L(" Destinatário ")],-1)),o("div",G$,[e[42]||(e[42]=o("span",{class:"input-prefix"},"+",-1)),Be(o("input",{id:"recipient","onUpdate:modelValue":e[1]||(e[1]=r=>t.recipient=r),type:"tel",class:"form-input with-prefix",placeholder:"5511999999999",required:""},null,512),[[at,t.recipient]]),o("button",{type:"button",class:"btn-small contact-search-btn",onClick:e[2]||(e[2]=r=>t.openContactSearch())},"Buscar")]),t.contactSearchVisible?(b(),w("div",Q$,[o("div",J$,[Be(o("input",{"onUpdate:modelValue":e[3]||(e[3]=r=>t.contactSearchQuery=r),onKeyup:e[4]||(e[4]=Wi(r=>t.searchContacts(),["enter"])),placeholder:"Pesquisar nome ou telefone",class:"form-input"},null,544),[[at,t.contactSearchQuery]]),o("button",{type:"button",class:"btn-small",onClick:e[5]||(e[5]=r=>t.searchContacts())},"Buscar"),o("button",{type:"button",class:"btn-small",onClick:e[6]||(e[6]=r=>t.closeContactSearch())},"Fechar")]),o("div",X$,[t.contactSearchLoading?(b(),w("div",Y$,"Buscando...")):!t.contactSearchLoading&&t.contactSearchResults.length===0?(b(),w("div",Z$,"Nenhum contato encontrado")):(b(),w("ul",e6,[(b(!0),w(Xe,null,Yt(t.contactSearchResults,r=>(b(),w("li",{key:r.id},[o("button",{type:"button",class:"contact-result",onClick:c=>t.selectContact(r)},A(r.title||r.id||r.phone)+" — "+A(r.phone),9,t6)]))),128))]))])])):U("",!0),e[44]||(e[44]=o("span",{class:"input-hint"},"Número completo com código do país (sem espaços ou traços)",-1))]),o("div",n6,[e[49]||(e[49]=o("label",null,"Tipo de Mensagem",-1)),o("div",s6,[o("button",{type:"button",onClick:e[7]||(e[7]=r=>t.msgType="text"),class:ae({active:t.msgType==="text"})},[...e[45]||(e[45]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"})],-1),L(" Texto ",-1)])],2),o("button",{type:"button",onClick:e[8]||(e[8]=r=>t.msgType="image"),class:ae({active:t.msgType==="image"})},[...e[46]||(e[46]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"})],-1),L(" Imagem ",-1)])],2),o("button",{type:"button",onClick:e[9]||(e[9]=r=>t.msgType="document"),class:ae({active:t.msgType==="document"})},[...e[47]||(e[47]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"})],-1),L(" Documento ",-1)])],2),o("button",{type:"button",onClick:e[10]||(e[10]=r=>t.msgType="audio"),class:ae({active:t.msgType==="audio"})},[...e[48]||(e[48]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"})],-1),L(" Áudio ",-1)])],2)])]),t.msgType==="text"?(b(),w("div",o6,[e[50]||(e[50]=o("label",{for:"text"},[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"})]),L(" Mensagem ")],-1)),Be(o("textarea",{id:"text","onUpdate:modelValue":e[11]||(e[11]=r=>t.text=r),class:"form-textarea",placeholder:"Digite sua mensagem...",rows:"5",required:""},null,512),[[at,t.text]]),o("span",i6,A(t.text.length)+" caracteres",1)])):U("",!0),t.msgType==="image"?(b(),w("div",r6,[e[53]||(e[53]=o("label",null,"Origem da Imagem",-1)),o("div",a6,[o("button",{type:"button",onClick:e[12]||(e[12]=r=>t.mediaSource="file"),class:ae({active:t.mediaSource==="file"})},[...e[51]||(e[51]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M9 16h6v-6h4l-7-7-7 7h4v6zm-4 2h14v2H5v-2z"})],-1),L(" Upload de Arquivo ",-1)])],2),o("button",{type:"button",onClick:e[13]||(e[13]=r=>t.mediaSource="url"),class:ae({active:t.mediaSource==="url"})},[...e[52]||(e[52]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"})],-1),L(" URL ",-1)])],2)])])):U("",!0),t.msgType==="image"&&t.mediaSource==="file"?(b(),w("div",l6,[e[56]||(e[56]=o("label",null,[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"})]),L(" Selecionar Imagem ")],-1)),o("div",{class:ae(["file-upload",{"has-file":t.selectedFile}]),onClick:e[16]||(e[16]=r=>{var c;return(c=t.imageInput)==null?void 0:c.click()})},[o("input",{ref:"imageInput",type:"file",accept:"image/*",onChange:e[14]||(e[14]=(...r)=>t.handleFileSelect&&t.handleFileSelect(...r)),hidden:""},null,544),t.selectedFile?(b(),w("div",u6,[e[55]||(e[55]=o("svg",{viewBox:"0 0 24 24",width:"32",height:"32",fill:"currentColor"},[o("path",{d:"M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"})],-1)),o("div",d6,[o("span",f6,A(t.selectedFile.name),1),o("span",h6,A(t.formatFileSize(t.selectedFile.size)),1)]),o("button",{type:"button",onClick:e[15]||(e[15]=kt((...r)=>t.clearFile&&t.clearFile(...r),["stop"])),class:"file-remove"},"✕")])):(b(),w("div",c6,[...e[54]||(e[54]=[o("svg",{viewBox:"0 0 24 24",width:"40",height:"40",fill:"currentColor"},[o("path",{d:"M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"})],-1),o("span",null,"Clique para selecionar uma imagem",-1),o("span",{class:"file-hint"},"JPG, PNG, GIF - Máx 16MB",-1)])]))],2)])):U("",!0),t.msgType==="image"&&t.mediaSource==="url"?(b(),w("div",p6,[e[57]||(e[57]=o("label",{for:"attachmentUrl"},[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"})]),L(" URL da Imagem ")],-1)),Be(o("input",{id:"attachmentUrl","onUpdate:modelValue":e[17]||(e[17]=r=>t.attachmentUrl=r),type:"url",class:"form-input",placeholder:"https://exemplo.com/imagem.jpg"},null,512),[[at,t.attachmentUrl]])])):U("",!0),t.msgType==="image"?(b(),w("div",g6,[e[58]||(e[58]=o("label",{for:"caption"},[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25z"})]),L(" Legenda (opcional) ")],-1)),Be(o("input",{id:"caption","onUpdate:modelValue":e[18]||(e[18]=r=>t.text=r),type:"text",class:"form-input",placeholder:"Legenda da imagem..."},null,512),[[at,t.text]])])):U("",!0),t.msgType==="document"?(b(),w("div",m6,[e[61]||(e[61]=o("label",null,"Origem do Documento",-1)),o("div",v6,[o("button",{type:"button",onClick:e[19]||(e[19]=r=>t.mediaSource="file"),class:ae({active:t.mediaSource==="file"})},[...e[59]||(e[59]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M9 16h6v-6h4l-7-7-7 7h4v6zm-4 2h14v2H5v-2z"})],-1),L(" Upload de Arquivo ",-1)])],2),o("button",{type:"button",onClick:e[20]||(e[20]=r=>t.mediaSource="url"),class:ae({active:t.mediaSource==="url"})},[...e[60]||(e[60]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"})],-1),L(" URL ",-1)])],2)])])):U("",!0),t.msgType==="document"&&t.mediaSource==="file"?(b(),w("div",b6,[e[64]||(e[64]=o("label",null,[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6z"})]),L(" Selecionar Documento ")],-1)),o("div",{class:ae(["file-upload",{"has-file":t.selectedFile}]),onClick:e[23]||(e[23]=r=>{var c;return(c=t.docInput)==null?void 0:c.click()})},[o("input",{ref:"docInput",type:"file",onChange:e[21]||(e[21]=(...r)=>t.handleFileSelect&&t.handleFileSelect(...r)),hidden:""},null,544),t.selectedFile?(b(),w("div",w6,[e[63]||(e[63]=o("svg",{viewBox:"0 0 24 24",width:"32",height:"32",fill:"currentColor"},[o("path",{d:"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"})],-1)),o("div",_6,[o("span",C6,A(t.selectedFile.name),1),o("span",k6,A(t.formatFileSize(t.selectedFile.size)),1)]),o("button",{type:"button",onClick:e[22]||(e[22]=kt((...r)=>t.clearFile&&t.clearFile(...r),["stop"])),class:"file-remove"},"✕")])):(b(),w("div",y6,[...e[62]||(e[62]=[o("svg",{viewBox:"0 0 24 24",width:"40",height:"40",fill:"currentColor"},[o("path",{d:"M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"})],-1),o("span",null,"Clique para selecionar um documento",-1),o("span",{class:"file-hint"},"PDF, DOC, XLS, etc - Máx 100MB",-1)])]))],2)])):U("",!0),t.msgType==="document"&&t.mediaSource==="url"?(b(),w("div",S6,[e[65]||(e[65]=o("label",{for:"attachmentUrl"},[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"})]),L(" URL do Documento ")],-1)),Be(o("input",{id:"attachmentUrl","onUpdate:modelValue":e[24]||(e[24]=r=>t.attachmentUrl=r),type:"url",class:"form-input",placeholder:"https://exemplo.com/documento.pdf"},null,512),[[at,t.attachmentUrl]])])):U("",!0),t.msgType==="document"?(b(),w("div",E6,[e[66]||(e[66]=o("label",{for:"filename"},[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6z"})]),L(" Nome do Arquivo (opcional) ")],-1)),Be(o("input",{id:"filename","onUpdate:modelValue":e[25]||(e[25]=r=>t.filename=r),type:"text",class:"form-input",placeholder:"documento.pdf"},null,512),[[at,t.filename]])])):U("",!0),t.msgType==="audio"?(b(),w("div",$6,[e[70]||(e[70]=o("label",null,"Origem do Áudio",-1)),o("div",T6,[o("button",{type:"button",onClick:e[26]||(e[26]=r=>t.mediaSource="record"),class:ae({active:t.mediaSource==="record"})},[...e[67]||(e[67]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"})],-1),L(" Gravar Áudio ",-1)])],2),o("button",{type:"button",onClick:e[27]||(e[27]=r=>t.mediaSource="file"),class:ae({active:t.mediaSource==="file"})},[...e[68]||(e[68]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M9 16h6v-6h4l-7-7-7 7h4v6zm-4 2h14v2H5v-2z"})],-1),L(" Upload de Arquivo ",-1)])],2),o("button",{type:"button",onClick:e[28]||(e[28]=r=>t.mediaSource="url"),class:ae({active:t.mediaSource==="url"})},[...e[69]||(e[69]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"})],-1),L(" URL ",-1)])],2)])])):U("",!0),t.msgType==="audio"&&t.mediaSource==="record"?(b(),w("div",A6,[o("div",{class:ae(["audio-recorder",{recording:t.isRecording}])},[!t.isRecording&&!t.audioBlob?(b(),w("div",R6,[o("button",{type:"button",onClick:e[29]||(e[29]=(...r)=>t.startRecording&&t.startRecording(...r)),class:"btn-record"},[...e[71]||(e[71]=[o("svg",{viewBox:"0 0 24 24",width:"32",height:"32",fill:"currentColor"},[o("path",{d:"M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z"})],-1)])]),e[72]||(e[72]=o("span",null,"Clique para gravar",-1))])):t.isRecording?(b(),w("div",P6,[o("div",I6,[e[73]||(e[73]=o("span",{class:"recording-dot"},null,-1)),o("span",O6,A(t.recordingTime),1)]),o("button",{type:"button",onClick:e[30]||(e[30]=(...r)=>t.stopRecording&&t.stopRecording(...r)),class:"btn-stop"},[...e[74]||(e[74]=[o("svg",{viewBox:"0 0 24 24",width:"24",height:"24",fill:"currentColor"},[o("path",{d:"M6 6h12v12H6z"})],-1),L(" Parar ",-1)])])])):(b(),w("div",M6,[o("audio",{src:t.audioUrl,controls:"",class:"audio-preview"},null,8,D6),o("button",{type:"button",onClick:e[31]||(e[31]=(...r)=>t.clearAudio&&t.clearAudio(...r)),class:"btn-clear"},[...e[75]||(e[75]=[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"})],-1),L(" Limpar ",-1)])])]))],2)])):U("",!0),t.msgType==="audio"&&t.mediaSource==="file"?(b(),w("div",L6,[e[78]||(e[78]=o("label",null,[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"})]),L(" Selecionar Áudio ")],-1)),o("div",{class:ae(["file-upload",{"has-file":t.selectedFile}]),onClick:e[34]||(e[34]=r=>{var c;return(c=t.audioInput)==null?void 0:c.click()})},[o("input",{ref:"audioInput",type:"file",accept:"audio/*",onChange:e[32]||(e[32]=(...r)=>t.handleFileSelect&&t.handleFileSelect(...r)),hidden:""},null,544),t.selectedFile?(b(),w("div",F6,[e[77]||(e[77]=o("svg",{viewBox:"0 0 24 24",width:"32",height:"32",fill:"currentColor"},[o("path",{d:"M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"})],-1)),o("div",x6,[o("span",B6,A(t.selectedFile.name),1),o("span",z6,A(t.formatFileSize(t.selectedFile.size)),1)]),o("button",{type:"button",onClick:e[33]||(e[33]=kt((...r)=>t.clearFile&&t.clearFile(...r),["stop"])),class:"file-remove"},"✕")])):(b(),w("div",N6,[...e[76]||(e[76]=[o("svg",{viewBox:"0 0 24 24",width:"40",height:"40",fill:"currentColor"},[o("path",{d:"M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"})],-1),o("span",null,"Clique para selecionar um áudio",-1),o("span",{class:"file-hint"},"MP3, OGG, WAV - Máx 16MB",-1)])]))],2)])):U("",!0),t.msgType==="audio"&&t.mediaSource==="url"?(b(),w("div",H6,[e[79]||(e[79]=o("label",{for:"attachmentUrl"},[o("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"currentColor"},[o("path",{d:"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"})]),L(" URL do Áudio ")],-1)),Be(o("input",{id:"attachmentUrl","onUpdate:modelValue":e[35]||(e[35]=r=>t.attachmentUrl=r),type:"url",class:"form-input",placeholder:"https://exemplo.com/audio.mp3"},null,512),[[at,t.attachmentUrl]])])):U("",!0),o("button",{type:"submit",class:"btn-send",disabled:t.sending},[t.sending?(b(),w("span",V6)):(b(),w("svg",j6,[...e[80]||(e[80]=[o("path",{d:"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"},null,-1)])])),L(" "+A(t.sending?"Enviando...":"Enviar Mensagem"),1)],8,U6)],32)]),o("div",q6,[e[84]||(e[84]=o("h3",null,[o("svg",{viewBox:"0 0 24 24",width:"20",height:"20",fill:"currentColor"},[o("path",{d:"M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"})]),L(" Preview ")],-1)),o("div",W6,[o("div",K6,[o("div",G6,[o("div",Q6,A(t.getInitial(t.recipient)),1),o("span",null,"+"+A(t.recipient||"..."),1)])]),o("div",J6,[o("div",X6,[t.msgType==="text"?(b(),w("div",Y6,A(t.text||"Sua mensagem aparecerá aqui..."),1)):t.msgType==="image"?(b(),w("div",Z6,[e[81]||(e[81]=o("div",{class:"media-placeholder"},[o("svg",{viewBox:"0 0 24 24",width:"32",height:"32",fill:"currentColor"},[o("path",{d:"M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"})])],-1)),t.text?(b(),w("div",e9,A(t.text),1)):U("",!0)])):(b(),w("div",t9,[o("div",n9,[e[82]||(e[82]=o("svg",{viewBox:"0 0 24 24",width:"32",height:"32",fill:"currentColor"},[o("path",{d:"M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6z"})],-1)),o("span",null,A(t.filename||"arquivo"),1)])])),o("div",s9,A(t.currentTime),1)])])]),t.recentSends.length>0?(b(),w("div",o9,[e[83]||(e[83]=o("h4",null,"Envios Recentes",-1)),o("div",i9,[(b(!0),w(Xe,null,Yt(t.recentSends,(r,c)=>(b(),w("div",{key:c,class:ae(["recent-item",{failed:r.error}])},[o("span",r9,"+"+A(r.to),1),o("span",a9,A(r.error?"Falha":"Enviado"),1)],2))),128))])])):U("",!0)])])])}const c9=It(B$,[["render",l9],["__scopeId","data-v-f1e3bd8f"]]),Jf=Av({history:lv(),routes:[{path:"/",name:"home",component:B0,meta:{requiresAuth:!0}},{path:"/account",name:"account",component:bw,meta:{requiresAuth:!0}},{path:"/webhooks",name:"webhooks",component:Ju,meta:{requiresAuth:!0}},{path:"/dispatching",name:"dispatching",component:Ju,meta:{requiresAuth:!0}},{path:"/rabbitmq",name:"rabbitmq",component:uC,meta:{requiresAuth:!0}},{path:"/connect",name:"connect",component:I3,meta:{requiresAuth:!0}},{path:"/server/:token",name:"server",component:e3,meta:{requiresAuth:!0}},{path:"/server/:token/qrcode",name:"server.qrcode",component:Yk,meta:{requiresAuth:!0}},{path:"/server/:token/paircode",name:"server.paircode",component:TS,meta:{requiresAuth:!0}},{path:"/server/:token/messages",name:"server.messages",component:x$,meta:{requiresAuth:!0}},{path:"/server/:token/send",name:"server.send",component:c9,meta:{requiresAuth:!0}},{path:"/server/:token/groups",name:"server.groups",component:()=>Qu(()=>import("./groups.js"),__vite__mapDeps([0,1])),meta:{requiresAuth:!0}},{path:"/server/:token/groups/:id",name:"server.groups.detail",component:()=>Qu(()=>import("./groupdetail.js"),__vite__mapDeps([2,3])),meta:{requiresAuth:!0}},{path:"/setup",name:"setup",component:k3,meta:{requiresAuth:!0}},{path:"/users",name:"users",component:X3,meta:{requiresAuth:!0}},{path:"/users/create",name:"users.create",component:mk,meta:{requiresAuth:!0}},{path:"/environment",name:"environment",component:Lk,meta:{requiresAuth:!0}},{path:"/login",name:"login",component:qw}]});Jf.beforeEach(async t=>{const e=il();return e.loading.value&&await e.loadSession(),t.meta.requiresAuth&&!e.user.value?{name:"login",query:{redirect:t.fullPath}}:t.name==="login"&&e.user.value?{name:"home"}:!0});var u9=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},d9={exports:{}};/*! + * Bootstrap v5.3.8 (https://getbootstrap.com/) + * Copyright 2011-2025 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */(function(t,e){(function(n,s){t.exports=s()})(u9,function(){const n=new Map,s={set(p,a,d){n.has(p)||n.set(p,new Map);const m=n.get(p);m.has(a)||m.size===0?m.set(a,d):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(m.keys())[0]}.`)},get:(p,a)=>n.has(p)&&n.get(p).get(a)||null,remove(p,a){if(!n.has(p))return;const d=n.get(p);d.delete(a),d.size===0&&n.delete(p)}},i="transitionend",l=p=>(p&&window.CSS&&window.CSS.escape&&(p=p.replace(/#([^\s"#']+)/g,(a,d)=>`#${CSS.escape(d)}`)),p),r=p=>p==null?`${p}`:Object.prototype.toString.call(p).match(/\s([a-z]+)/i)[1].toLowerCase(),c=p=>{p.dispatchEvent(new Event(i))},u=p=>!(!p||typeof p!="object")&&(p.jquery!==void 0&&(p=p[0]),p.nodeType!==void 0),h=p=>u(p)?p.jquery?p[0]:p:typeof p=="string"&&p.length>0?document.querySelector(l(p)):null,f=p=>{if(!u(p)||p.getClientRects().length===0)return!1;const a=getComputedStyle(p).getPropertyValue("visibility")==="visible",d=p.closest("details:not([open])");if(!d)return a;if(d!==p){const m=p.closest("summary");if(m&&m.parentNode!==d||m===null)return!1}return a},g=p=>!p||p.nodeType!==Node.ELEMENT_NODE||!!p.classList.contains("disabled")||(p.disabled!==void 0?p.disabled:p.hasAttribute("disabled")&&p.getAttribute("disabled")!=="false"),C=p=>{if(!document.documentElement.attachShadow)return null;if(typeof p.getRootNode=="function"){const a=p.getRootNode();return a instanceof ShadowRoot?a:null}return p instanceof ShadowRoot?p:p.parentNode?C(p.parentNode):null},_=()=>{},y=p=>{p.offsetHeight},P=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,I=[],H=()=>document.documentElement.dir==="rtl",W=p=>{var a;a=()=>{const d=P();if(d){const m=p.NAME,$=d.fn[m];d.fn[m]=p.jQueryInterface,d.fn[m].Constructor=p,d.fn[m].noConflict=()=>(d.fn[m]=$,p.jQueryInterface)}},document.readyState==="loading"?(I.length||document.addEventListener("DOMContentLoaded",()=>{for(const d of I)d()}),I.push(a)):a()},G=(p,a=[],d=p)=>typeof p=="function"?p.call(...a):d,F=(p,a,d=!0)=>{if(!d)return void G(p);const m=(B=>{if(!B)return 0;let{transitionDuration:J,transitionDelay:re}=window.getComputedStyle(B);const pe=Number.parseFloat(J),ge=Number.parseFloat(re);return pe||ge?(J=J.split(",")[0],re=re.split(",")[0],1e3*(Number.parseFloat(J)+Number.parseFloat(re))):0})(a)+5;let $=!1;const T=({target:B})=>{B===a&&($=!0,a.removeEventListener(i,T),G(p))};a.addEventListener(i,T),setTimeout(()=>{$||c(a)},m)},ne=(p,a,d,m)=>{const $=p.length;let T=p.indexOf(a);return T===-1?!d&&m?p[$-1]:p[0]:(T+=d?1:-1,m&&(T=(T+$)%$),p[Math.max(0,Math.min(T,$-1))])},he=/[^.]*(?=\..*)\.|.*/,ce=/\..*/,Ee=/::\d+$/,Se={};let _e=1;const ye={mouseenter:"mouseover",mouseleave:"mouseout"},Me=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function ve(p,a){return a&&`${a}::${_e++}`||p.uidEvent||_e++}function te(p){const a=ve(p);return p.uidEvent=a,Se[a]=Se[a]||{},Se[a]}function Le(p,a,d=null){return Object.values(p).find(m=>m.callable===a&&m.delegationSelector===d)}function Y(p,a,d){const m=typeof a=="string",$=m?d:a||d;let T=He(p);return Me.has(T)||(T=p),[m,$,T]}function oe(p,a,d,m,$){if(typeof a!="string"||!p)return;let[T,B,J]=Y(a,d,m);a in ye&&(B=(Ne=>function(De){if(!De.relatedTarget||De.relatedTarget!==De.delegateTarget&&!De.delegateTarget.contains(De.relatedTarget))return Ne.call(this,De)})(B));const re=te(p),pe=re[J]||(re[J]={}),ge=Le(pe,B,T?d:null);if(ge)return void(ge.oneOff=ge.oneOff&&$);const fe=ve(B,a.replace(he,"")),Ve=T?function(Pe,Ne,De){return function Fe(lt){const vt=Pe.querySelectorAll(Ne);for(let{target:We}=lt;We&&We!==this;We=We.parentNode)for(const tt of vt)if(tt===We)return Qe(lt,{delegateTarget:We}),Fe.oneOff&&z.off(Pe,lt.type,Ne,De),De.apply(We,[lt])}}(p,d,B):function(Pe,Ne){return function De(Fe){return Qe(Fe,{delegateTarget:Pe}),De.oneOff&&z.off(Pe,Fe.type,Ne),Ne.apply(Pe,[Fe])}}(p,B);Ve.delegationSelector=T?d:null,Ve.callable=B,Ve.oneOff=$,Ve.uidEvent=fe,pe[fe]=Ve,p.addEventListener(J,Ve,T)}function Q(p,a,d,m,$){const T=Le(a[d],m,$);T&&(p.removeEventListener(d,T,!!$),delete a[d][T.uidEvent])}function Re(p,a,d,m){const $=a[d]||{};for(const[T,B]of Object.entries($))T.includes(m)&&Q(p,a,d,B.callable,B.delegationSelector)}function He(p){return p=p.replace(ce,""),ye[p]||p}const z={on(p,a,d,m){oe(p,a,d,m,!1)},one(p,a,d,m){oe(p,a,d,m,!0)},off(p,a,d,m){if(typeof a!="string"||!p)return;const[$,T,B]=Y(a,d,m),J=B!==a,re=te(p),pe=re[B]||{},ge=a.startsWith(".");if(T===void 0){if(ge)for(const fe of Object.keys(re))Re(p,re,fe,a.slice(1));for(const[fe,Ve]of Object.entries(pe)){const Pe=fe.replace(Ee,"");J&&!a.includes(Pe)||Q(p,re,B,Ve.callable,Ve.delegationSelector)}}else{if(!Object.keys(pe).length)return;Q(p,re,B,T,$?d:null)}},trigger(p,a,d){if(typeof a!="string"||!p)return null;const m=P();let $=null,T=!0,B=!0,J=!1;a!==He(a)&&m&&($=m.Event(a,d),m(p).trigger($),T=!$.isPropagationStopped(),B=!$.isImmediatePropagationStopped(),J=$.isDefaultPrevented());const re=Qe(new Event(a,{bubbles:T,cancelable:!0}),d);return J&&re.preventDefault(),B&&p.dispatchEvent(re),re.defaultPrevented&&$&&$.preventDefault(),re}};function Qe(p,a={}){for(const[d,m]of Object.entries(a))try{p[d]=m}catch{Object.defineProperty(p,d,{configurable:!0,get:()=>m})}return p}function Ke(p){if(p==="true")return!0;if(p==="false")return!1;if(p===Number(p).toString())return Number(p);if(p===""||p==="null")return null;if(typeof p!="string")return p;try{return JSON.parse(decodeURIComponent(p))}catch{return p}}function yt(p){return p.replace(/[A-Z]/g,a=>`-${a.toLowerCase()}`)}const gt={setDataAttribute(p,a,d){p.setAttribute(`data-bs-${yt(a)}`,d)},removeDataAttribute(p,a){p.removeAttribute(`data-bs-${yt(a)}`)},getDataAttributes(p){if(!p)return{};const a={},d=Object.keys(p.dataset).filter(m=>m.startsWith("bs")&&!m.startsWith("bsConfig"));for(const m of d){let $=m.replace(/^bs/,"");$=$.charAt(0).toLowerCase()+$.slice(1),a[$]=Ke(p.dataset[m])}return a},getDataAttribute:(p,a)=>Ke(p.getAttribute(`data-bs-${yt(a)}`))};class Ae{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(a){return a=this._mergeConfigObj(a),a=this._configAfterMerge(a),this._typeCheckConfig(a),a}_configAfterMerge(a){return a}_mergeConfigObj(a,d){const m=u(d)?gt.getDataAttribute(d,"config"):{};return{...this.constructor.Default,...typeof m=="object"?m:{},...u(d)?gt.getDataAttributes(d):{},...typeof a=="object"?a:{}}}_typeCheckConfig(a,d=this.constructor.DefaultType){for(const[m,$]of Object.entries(d)){const T=a[m],B=u(T)?"element":r(T);if(!new RegExp($).test(B))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${m}" provided type "${B}" but expected type "${$}".`)}}}class M extends Ae{constructor(a,d){super(),(a=h(a))&&(this._element=a,this._config=this._getConfig(d),s.set(this._element,this.constructor.DATA_KEY,this))}dispose(){s.remove(this._element,this.constructor.DATA_KEY),z.off(this._element,this.constructor.EVENT_KEY);for(const a of Object.getOwnPropertyNames(this))this[a]=null}_queueCallback(a,d,m=!0){F(a,d,m)}_getConfig(a){return a=this._mergeConfigObj(a,this._element),a=this._configAfterMerge(a),this._typeCheckConfig(a),a}static getInstance(a){return s.get(h(a),this.DATA_KEY)}static getOrCreateInstance(a,d={}){return this.getInstance(a)||new this(a,typeof d=="object"?d:null)}static get VERSION(){return"5.3.8"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(a){return`${a}${this.EVENT_KEY}`}}const ee=p=>{let a=p.getAttribute("data-bs-target");if(!a||a==="#"){let d=p.getAttribute("href");if(!d||!d.includes("#")&&!d.startsWith("."))return null;d.includes("#")&&!d.startsWith("#")&&(d=`#${d.split("#")[1]}`),a=d&&d!=="#"?d.trim():null}return a?a.split(",").map(d=>l(d)).join(","):null},S={find:(p,a=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(a,p)),findOne:(p,a=document.documentElement)=>Element.prototype.querySelector.call(a,p),children:(p,a)=>[].concat(...p.children).filter(d=>d.matches(a)),parents(p,a){const d=[];let m=p.parentNode.closest(a);for(;m;)d.push(m),m=m.parentNode.closest(a);return d},prev(p,a){let d=p.previousElementSibling;for(;d;){if(d.matches(a))return[d];d=d.previousElementSibling}return[]},next(p,a){let d=p.nextElementSibling;for(;d;){if(d.matches(a))return[d];d=d.nextElementSibling}return[]},focusableChildren(p){const a=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map(d=>`${d}:not([tabindex^="-"])`).join(",");return this.find(a,p).filter(d=>!g(d)&&f(d))},getSelectorFromElement(p){const a=ee(p);return a&&S.findOne(a)?a:null},getElementFromSelector(p){const a=ee(p);return a?S.findOne(a):null},getMultipleElementsFromSelector(p){const a=ee(p);return a?S.find(a):[]}},x=(p,a="hide")=>{const d=`click.dismiss${p.EVENT_KEY}`,m=p.NAME;z.on(document,d,`[data-bs-dismiss="${m}"]`,function($){if(["A","AREA"].includes(this.tagName)&&$.preventDefault(),g(this))return;const T=S.getElementFromSelector(this)||this.closest(`.${m}`);p.getOrCreateInstance(T)[a]()})},Z=".bs.alert",v=`close${Z}`,E=`closed${Z}`;class R extends M{static get NAME(){return"alert"}close(){if(z.trigger(this._element,v).defaultPrevented)return;this._element.classList.remove("show");const a=this._element.classList.contains("fade");this._queueCallback(()=>this._destroyElement(),this._element,a)}_destroyElement(){this._element.remove(),z.trigger(this._element,E),this.dispose()}static jQueryInterface(a){return this.each(function(){const d=R.getOrCreateInstance(this);if(typeof a=="string"){if(d[a]===void 0||a.startsWith("_")||a==="constructor")throw new TypeError(`No method named "${a}"`);d[a](this)}})}}x(R,"close"),W(R);const j='[data-bs-toggle="button"]';class K extends M{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(a){return this.each(function(){const d=K.getOrCreateInstance(this);a==="toggle"&&d[a]()})}}z.on(document,"click.bs.button.data-api",j,p=>{p.preventDefault();const a=p.target.closest(j);K.getOrCreateInstance(a).toggle()}),W(K);const V=".bs.swipe",le=`touchstart${V}`,ie=`touchmove${V}`,se=`touchend${V}`,X=`pointerdown${V}`,$e=`pointerup${V}`,de={endCallback:null,leftCallback:null,rightCallback:null},Ce={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class Te extends Ae{constructor(a,d){super(),this._element=a,a&&Te.isSupported()&&(this._config=this._getConfig(d),this._deltaX=0,this._supportPointerEvents=!!window.PointerEvent,this._initEvents())}static get Default(){return de}static get DefaultType(){return Ce}static get NAME(){return"swipe"}dispose(){z.off(this._element,V)}_start(a){this._supportPointerEvents?this._eventIsPointerPenTouch(a)&&(this._deltaX=a.clientX):this._deltaX=a.touches[0].clientX}_end(a){this._eventIsPointerPenTouch(a)&&(this._deltaX=a.clientX-this._deltaX),this._handleSwipe(),G(this._config.endCallback)}_move(a){this._deltaX=a.touches&&a.touches.length>1?0:a.touches[0].clientX-this._deltaX}_handleSwipe(){const a=Math.abs(this._deltaX);if(a<=40)return;const d=a/this._deltaX;this._deltaX=0,d&&G(d>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(z.on(this._element,X,a=>this._start(a)),z.on(this._element,$e,a=>this._end(a)),this._element.classList.add("pointer-event")):(z.on(this._element,le,a=>this._start(a)),z.on(this._element,ie,a=>this._move(a)),z.on(this._element,se,a=>this._end(a)))}_eventIsPointerPenTouch(a){return this._supportPointerEvents&&(a.pointerType==="pen"||a.pointerType==="touch")}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const Oe=".bs.carousel",Je=".data-api",k="ArrowLeft",N="ArrowRight",ue="next",me="prev",qe="left",Ot="right",Ut=`slide${Oe}`,mt=`slid${Oe}`,et=`keydown${Oe}`,In=`mouseenter${Oe}`,bn=`mouseleave${Oe}`,ms=`dragstart${Oe}`,dt=`load${Oe}${Je}`,mr=`click${Oe}${Je}`,ss="carousel",ri="active",cl=".active",ul=".carousel-item",Xf=cl+ul,Yf={[k]:Ot,[N]:qe},Zf={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},eh={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class Hs extends M{constructor(a,d){super(a,d),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=S.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===ss&&this.cycle()}static get Default(){return Zf}static get DefaultType(){return eh}static get NAME(){return"carousel"}next(){this._slide(ue)}nextWhenVisible(){!document.hidden&&f(this._element)&&this.next()}prev(){this._slide(me)}pause(){this._isSliding&&c(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval(()=>this.nextWhenVisible(),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?z.one(this._element,mt,()=>this.cycle()):this.cycle())}to(a){const d=this._getItems();if(a>d.length-1||a<0)return;if(this._isSliding)return void z.one(this._element,mt,()=>this.to(a));const m=this._getItemIndex(this._getActive());if(m===a)return;const $=a>m?ue:me;this._slide($,d[a])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(a){return a.defaultInterval=a.interval,a}_addEventListeners(){this._config.keyboard&&z.on(this._element,et,a=>this._keydown(a)),this._config.pause==="hover"&&(z.on(this._element,In,()=>this.pause()),z.on(this._element,bn,()=>this._maybeEnableCycle())),this._config.touch&&Te.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const d of S.find(".carousel-item img",this._element))z.on(d,ms,m=>m.preventDefault());const a={leftCallback:()=>this._slide(this._directionToOrder(qe)),rightCallback:()=>this._slide(this._directionToOrder(Ot)),endCallback:()=>{this._config.pause==="hover"&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout(()=>this._maybeEnableCycle(),500+this._config.interval))}};this._swipeHelper=new Te(this._element,a)}_keydown(a){if(/input|textarea/i.test(a.target.tagName))return;const d=Yf[a.key];d&&(a.preventDefault(),this._slide(this._directionToOrder(d)))}_getItemIndex(a){return this._getItems().indexOf(a)}_setActiveIndicatorElement(a){if(!this._indicatorsElement)return;const d=S.findOne(cl,this._indicatorsElement);d.classList.remove(ri),d.removeAttribute("aria-current");const m=S.findOne(`[data-bs-slide-to="${a}"]`,this._indicatorsElement);m&&(m.classList.add(ri),m.setAttribute("aria-current","true"))}_updateInterval(){const a=this._activeElement||this._getActive();if(!a)return;const d=Number.parseInt(a.getAttribute("data-bs-interval"),10);this._config.interval=d||this._config.defaultInterval}_slide(a,d=null){if(this._isSliding)return;const m=this._getActive(),$=a===ue,T=d||ne(this._getItems(),m,$,this._config.wrap);if(T===m)return;const B=this._getItemIndex(T),J=fe=>z.trigger(this._element,fe,{relatedTarget:T,direction:this._orderToDirection(a),from:this._getItemIndex(m),to:B});if(J(Ut).defaultPrevented||!m||!T)return;const re=!!this._interval;this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(B),this._activeElement=T;const pe=$?"carousel-item-start":"carousel-item-end",ge=$?"carousel-item-next":"carousel-item-prev";T.classList.add(ge),y(T),m.classList.add(pe),T.classList.add(pe),this._queueCallback(()=>{T.classList.remove(pe,ge),T.classList.add(ri),m.classList.remove(ri,ge,pe),this._isSliding=!1,J(mt)},m,this._isAnimated()),re&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return S.findOne(Xf,this._element)}_getItems(){return S.find(ul,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(a){return H()?a===qe?me:ue:a===qe?ue:me}_orderToDirection(a){return H()?a===me?qe:Ot:a===me?Ot:qe}static jQueryInterface(a){return this.each(function(){const d=Hs.getOrCreateInstance(this,a);if(typeof a!="number"){if(typeof a=="string"){if(d[a]===void 0||a.startsWith("_")||a==="constructor")throw new TypeError(`No method named "${a}"`);d[a]()}}else d.to(a)})}}z.on(document,mr,"[data-bs-slide], [data-bs-slide-to]",function(p){const a=S.getElementFromSelector(this);if(!a||!a.classList.contains(ss))return;p.preventDefault();const d=Hs.getOrCreateInstance(a),m=this.getAttribute("data-bs-slide-to");return m?(d.to(m),void d._maybeEnableCycle()):gt.getDataAttribute(this,"slide")==="next"?(d.next(),void d._maybeEnableCycle()):(d.prev(),void d._maybeEnableCycle())}),z.on(window,dt,()=>{const p=S.find('[data-bs-ride="carousel"]');for(const a of p)Hs.getOrCreateInstance(a)}),W(Hs);const _o=".bs.collapse",th=`show${_o}`,nh=`shown${_o}`,sh=`hide${_o}`,oh=`hidden${_o}`,ih=`click${_o}.data-api`,vr="show",Us="collapse",ai="collapsing",rh=`:scope .${Us} .${Us}`,br='[data-bs-toggle="collapse"]',ah={parent:null,toggle:!0},lh={parent:"(null|element)",toggle:"boolean"};class Vs extends M{constructor(a,d){super(a,d),this._isTransitioning=!1,this._triggerArray=[];const m=S.find(br);for(const $ of m){const T=S.getSelectorFromElement($),B=S.find(T).filter(J=>J===this._element);T!==null&&B.length&&this._triggerArray.push($)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return ah}static get DefaultType(){return lh}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let a=[];if(this._config.parent&&(a=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter($=>$!==this._element).map($=>Vs.getOrCreateInstance($,{toggle:!1}))),a.length&&a[0]._isTransitioning||z.trigger(this._element,th).defaultPrevented)return;for(const $ of a)$.hide();const d=this._getDimension();this._element.classList.remove(Us),this._element.classList.add(ai),this._element.style[d]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const m=`scroll${d[0].toUpperCase()+d.slice(1)}`;this._queueCallback(()=>{this._isTransitioning=!1,this._element.classList.remove(ai),this._element.classList.add(Us,vr),this._element.style[d]="",z.trigger(this._element,nh)},this._element,!0),this._element.style[d]=`${this._element[m]}px`}hide(){if(this._isTransitioning||!this._isShown()||z.trigger(this._element,sh).defaultPrevented)return;const a=this._getDimension();this._element.style[a]=`${this._element.getBoundingClientRect()[a]}px`,y(this._element),this._element.classList.add(ai),this._element.classList.remove(Us,vr);for(const d of this._triggerArray){const m=S.getElementFromSelector(d);m&&!this._isShown(m)&&this._addAriaAndCollapsedClass([d],!1)}this._isTransitioning=!0,this._element.style[a]="",this._queueCallback(()=>{this._isTransitioning=!1,this._element.classList.remove(ai),this._element.classList.add(Us),z.trigger(this._element,oh)},this._element,!0)}_isShown(a=this._element){return a.classList.contains(vr)}_configAfterMerge(a){return a.toggle=!!a.toggle,a.parent=h(a.parent),a}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const a=this._getFirstLevelChildren(br);for(const d of a){const m=S.getElementFromSelector(d);m&&this._addAriaAndCollapsedClass([d],this._isShown(m))}}_getFirstLevelChildren(a){const d=S.find(rh,this._config.parent);return S.find(a,this._config.parent).filter(m=>!d.includes(m))}_addAriaAndCollapsedClass(a,d){if(a.length)for(const m of a)m.classList.toggle("collapsed",!d),m.setAttribute("aria-expanded",d)}static jQueryInterface(a){const d={};return typeof a=="string"&&/show|hide/.test(a)&&(d.toggle=!1),this.each(function(){const m=Vs.getOrCreateInstance(this,d);if(typeof a=="string"){if(m[a]===void 0)throw new TypeError(`No method named "${a}"`);m[a]()}})}}z.on(document,ih,br,function(p){(p.target.tagName==="A"||p.delegateTarget&&p.delegateTarget.tagName==="A")&&p.preventDefault();for(const a of S.getMultipleElementsFromSelector(this))Vs.getOrCreateInstance(a,{toggle:!1}).toggle()}),W(Vs);var Vt="top",tn="bottom",nn="right",jt="left",li="auto",js=[Vt,tn,nn,jt],vs="start",qs="end",dl="clippingParents",yr="viewport",Ws="popper",fl="reference",wr=js.reduce(function(p,a){return p.concat([a+"-"+vs,a+"-"+qs])},[]),_r=[].concat(js,[li]).reduce(function(p,a){return p.concat([a,a+"-"+vs,a+"-"+qs])},[]),hl="beforeRead",pl="read",gl="afterRead",ml="beforeMain",vl="main",bl="afterMain",yl="beforeWrite",wl="write",_l="afterWrite",Cl=[hl,pl,gl,ml,vl,bl,yl,wl,_l];function On(p){return p?(p.nodeName||"").toLowerCase():null}function sn(p){if(p==null)return window;if(p.toString()!=="[object Window]"){var a=p.ownerDocument;return a&&a.defaultView||window}return p}function bs(p){return p instanceof sn(p).Element||p instanceof Element}function un(p){return p instanceof sn(p).HTMLElement||p instanceof HTMLElement}function Cr(p){return typeof ShadowRoot<"u"&&(p instanceof sn(p).ShadowRoot||p instanceof ShadowRoot)}const kr={name:"applyStyles",enabled:!0,phase:"write",fn:function(p){var a=p.state;Object.keys(a.elements).forEach(function(d){var m=a.styles[d]||{},$=a.attributes[d]||{},T=a.elements[d];un(T)&&On(T)&&(Object.assign(T.style,m),Object.keys($).forEach(function(B){var J=$[B];J===!1?T.removeAttribute(B):T.setAttribute(B,J===!0?"":J)}))})},effect:function(p){var a=p.state,d={popper:{position:a.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(a.elements.popper.style,d.popper),a.styles=d,a.elements.arrow&&Object.assign(a.elements.arrow.style,d.arrow),function(){Object.keys(a.elements).forEach(function(m){var $=a.elements[m],T=a.attributes[m]||{},B=Object.keys(a.styles.hasOwnProperty(m)?a.styles[m]:d[m]).reduce(function(J,re){return J[re]="",J},{});un($)&&On($)&&(Object.assign($.style,B),Object.keys(T).forEach(function(J){$.removeAttribute(J)}))})}},requires:["computeStyles"]};function Mn(p){return p.split("-")[0]}var ys=Math.max,ci=Math.min,Ks=Math.round;function Sr(){var p=navigator.userAgentData;return p!=null&&p.brands&&Array.isArray(p.brands)?p.brands.map(function(a){return a.brand+"/"+a.version}).join(" "):navigator.userAgent}function kl(){return!/^((?!chrome|android).)*safari/i.test(Sr())}function Gs(p,a,d){a===void 0&&(a=!1),d===void 0&&(d=!1);var m=p.getBoundingClientRect(),$=1,T=1;a&&un(p)&&($=p.offsetWidth>0&&Ks(m.width)/p.offsetWidth||1,T=p.offsetHeight>0&&Ks(m.height)/p.offsetHeight||1);var B=(bs(p)?sn(p):window).visualViewport,J=!kl()&&d,re=(m.left+(J&&B?B.offsetLeft:0))/$,pe=(m.top+(J&&B?B.offsetTop:0))/T,ge=m.width/$,fe=m.height/T;return{width:ge,height:fe,top:pe,right:re+ge,bottom:pe+fe,left:re,x:re,y:pe}}function Er(p){var a=Gs(p),d=p.offsetWidth,m=p.offsetHeight;return Math.abs(a.width-d)<=1&&(d=a.width),Math.abs(a.height-m)<=1&&(m=a.height),{x:p.offsetLeft,y:p.offsetTop,width:d,height:m}}function Sl(p,a){var d=a.getRootNode&&a.getRootNode();if(p.contains(a))return!0;if(d&&Cr(d)){var m=a;do{if(m&&p.isSameNode(m))return!0;m=m.parentNode||m.host}while(m)}return!1}function Un(p){return sn(p).getComputedStyle(p)}function ch(p){return["table","td","th"].indexOf(On(p))>=0}function os(p){return((bs(p)?p.ownerDocument:p.document)||window.document).documentElement}function ui(p){return On(p)==="html"?p:p.assignedSlot||p.parentNode||(Cr(p)?p.host:null)||os(p)}function El(p){return un(p)&&Un(p).position!=="fixed"?p.offsetParent:null}function Co(p){for(var a=sn(p),d=El(p);d&&ch(d)&&Un(d).position==="static";)d=El(d);return d&&(On(d)==="html"||On(d)==="body"&&Un(d).position==="static")?a:d||function(m){var $=/firefox/i.test(Sr());if(/Trident/i.test(Sr())&&un(m)&&Un(m).position==="fixed")return null;var T=ui(m);for(Cr(T)&&(T=T.host);un(T)&&["html","body"].indexOf(On(T))<0;){var B=Un(T);if(B.transform!=="none"||B.perspective!=="none"||B.contain==="paint"||["transform","perspective"].indexOf(B.willChange)!==-1||$&&B.willChange==="filter"||$&&B.filter&&B.filter!=="none")return T;T=T.parentNode}return null}(p)||a}function $r(p){return["top","bottom"].indexOf(p)>=0?"x":"y"}function ko(p,a,d){return ys(p,ci(a,d))}function $l(p){return Object.assign({},{top:0,right:0,bottom:0,left:0},p)}function Tl(p,a){return a.reduce(function(d,m){return d[m]=p,d},{})}const Al={name:"arrow",enabled:!0,phase:"main",fn:function(p){var a,d=p.state,m=p.name,$=p.options,T=d.elements.arrow,B=d.modifiersData.popperOffsets,J=Mn(d.placement),re=$r(J),pe=[jt,nn].indexOf(J)>=0?"height":"width";if(T&&B){var ge=function(ct,rt){return $l(typeof(ct=typeof ct=="function"?ct(Object.assign({},rt.rects,{placement:rt.placement})):ct)!="number"?ct:Tl(ct,js))}($.padding,d),fe=Er(T),Ve=re==="y"?Vt:jt,Pe=re==="y"?tn:nn,Ne=d.rects.reference[pe]+d.rects.reference[re]-B[re]-d.rects.popper[pe],De=B[re]-d.rects.reference[re],Fe=Co(T),lt=Fe?re==="y"?Fe.clientHeight||0:Fe.clientWidth||0:0,vt=Ne/2-De/2,We=ge[Ve],tt=lt-fe[pe]-ge[Pe],je=lt/2-fe[pe]/2+vt,Ge=ko(We,je,tt),it=re;d.modifiersData[m]=((a={})[it]=Ge,a.centerOffset=Ge-je,a)}},effect:function(p){var a=p.state,d=p.options.element,m=d===void 0?"[data-popper-arrow]":d;m!=null&&(typeof m!="string"||(m=a.elements.popper.querySelector(m)))&&Sl(a.elements.popper,m)&&(a.elements.arrow=m)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Qs(p){return p.split("-")[1]}var uh={top:"auto",right:"auto",bottom:"auto",left:"auto"};function Rl(p){var a,d=p.popper,m=p.popperRect,$=p.placement,T=p.variation,B=p.offsets,J=p.position,re=p.gpuAcceleration,pe=p.adaptive,ge=p.roundOffsets,fe=p.isFixed,Ve=B.x,Pe=Ve===void 0?0:Ve,Ne=B.y,De=Ne===void 0?0:Ne,Fe=typeof ge=="function"?ge({x:Pe,y:De}):{x:Pe,y:De};Pe=Fe.x,De=Fe.y;var lt=B.hasOwnProperty("x"),vt=B.hasOwnProperty("y"),We=jt,tt=Vt,je=window;if(pe){var Ge=Co(d),it="clientHeight",ct="clientWidth";Ge===sn(d)&&Un(Ge=os(d)).position!=="static"&&J==="absolute"&&(it="scrollHeight",ct="scrollWidth"),($===Vt||($===jt||$===nn)&&T===qs)&&(tt=tn,De-=(fe&&Ge===je&&je.visualViewport?je.visualViewport.height:Ge[it])-m.height,De*=re?1:-1),$!==jt&&($!==Vt&&$!==tn||T!==qs)||(We=nn,Pe-=(fe&&Ge===je&&je.visualViewport?je.visualViewport.width:Ge[ct])-m.width,Pe*=re?1:-1)}var rt,St=Object.assign({position:J},pe&&uh),on=ge===!0?function(wn,qt){var fn=wn.x,hn=wn.y,_t=qt.devicePixelRatio||1;return{x:Ks(fn*_t)/_t||0,y:Ks(hn*_t)/_t||0}}({x:Pe,y:De},sn(d)):{x:Pe,y:De};return Pe=on.x,De=on.y,re?Object.assign({},St,((rt={})[tt]=vt?"0":"",rt[We]=lt?"0":"",rt.transform=(je.devicePixelRatio||1)<=1?"translate("+Pe+"px, "+De+"px)":"translate3d("+Pe+"px, "+De+"px, 0)",rt)):Object.assign({},St,((a={})[tt]=vt?De+"px":"",a[We]=lt?Pe+"px":"",a.transform="",a))}const Tr={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(p){var a=p.state,d=p.options,m=d.gpuAcceleration,$=m===void 0||m,T=d.adaptive,B=T===void 0||T,J=d.roundOffsets,re=J===void 0||J,pe={placement:Mn(a.placement),variation:Qs(a.placement),popper:a.elements.popper,popperRect:a.rects.popper,gpuAcceleration:$,isFixed:a.options.strategy==="fixed"};a.modifiersData.popperOffsets!=null&&(a.styles.popper=Object.assign({},a.styles.popper,Rl(Object.assign({},pe,{offsets:a.modifiersData.popperOffsets,position:a.options.strategy,adaptive:B,roundOffsets:re})))),a.modifiersData.arrow!=null&&(a.styles.arrow=Object.assign({},a.styles.arrow,Rl(Object.assign({},pe,{offsets:a.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:re})))),a.attributes.popper=Object.assign({},a.attributes.popper,{"data-popper-placement":a.placement})},data:{}};var di={passive:!0};const Ar={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(p){var a=p.state,d=p.instance,m=p.options,$=m.scroll,T=$===void 0||$,B=m.resize,J=B===void 0||B,re=sn(a.elements.popper),pe=[].concat(a.scrollParents.reference,a.scrollParents.popper);return T&&pe.forEach(function(ge){ge.addEventListener("scroll",d.update,di)}),J&&re.addEventListener("resize",d.update,di),function(){T&&pe.forEach(function(ge){ge.removeEventListener("scroll",d.update,di)}),J&&re.removeEventListener("resize",d.update,di)}},data:{}};var dh={left:"right",right:"left",bottom:"top",top:"bottom"};function fi(p){return p.replace(/left|right|bottom|top/g,function(a){return dh[a]})}var fh={start:"end",end:"start"};function Pl(p){return p.replace(/start|end/g,function(a){return fh[a]})}function Rr(p){var a=sn(p);return{scrollLeft:a.pageXOffset,scrollTop:a.pageYOffset}}function Pr(p){return Gs(os(p)).left+Rr(p).scrollLeft}function Ir(p){var a=Un(p),d=a.overflow,m=a.overflowX,$=a.overflowY;return/auto|scroll|overlay|hidden/.test(d+$+m)}function Il(p){return["html","body","#document"].indexOf(On(p))>=0?p.ownerDocument.body:un(p)&&Ir(p)?p:Il(ui(p))}function So(p,a){var d;a===void 0&&(a=[]);var m=Il(p),$=m===((d=p.ownerDocument)==null?void 0:d.body),T=sn(m),B=$?[T].concat(T.visualViewport||[],Ir(m)?m:[]):m,J=a.concat(B);return $?J:J.concat(So(ui(B)))}function Or(p){return Object.assign({},p,{left:p.x,top:p.y,right:p.x+p.width,bottom:p.y+p.height})}function Ol(p,a,d){return a===yr?Or(function(m,$){var T=sn(m),B=os(m),J=T.visualViewport,re=B.clientWidth,pe=B.clientHeight,ge=0,fe=0;if(J){re=J.width,pe=J.height;var Ve=kl();(Ve||!Ve&&$==="fixed")&&(ge=J.offsetLeft,fe=J.offsetTop)}return{width:re,height:pe,x:ge+Pr(m),y:fe}}(p,d)):bs(a)?function(m,$){var T=Gs(m,!1,$==="fixed");return T.top=T.top+m.clientTop,T.left=T.left+m.clientLeft,T.bottom=T.top+m.clientHeight,T.right=T.left+m.clientWidth,T.width=m.clientWidth,T.height=m.clientHeight,T.x=T.left,T.y=T.top,T}(a,d):Or(function(m){var $,T=os(m),B=Rr(m),J=($=m.ownerDocument)==null?void 0:$.body,re=ys(T.scrollWidth,T.clientWidth,J?J.scrollWidth:0,J?J.clientWidth:0),pe=ys(T.scrollHeight,T.clientHeight,J?J.scrollHeight:0,J?J.clientHeight:0),ge=-B.scrollLeft+Pr(m),fe=-B.scrollTop;return Un(J||T).direction==="rtl"&&(ge+=ys(T.clientWidth,J?J.clientWidth:0)-re),{width:re,height:pe,x:ge,y:fe}}(os(p)))}function Ml(p){var a,d=p.reference,m=p.element,$=p.placement,T=$?Mn($):null,B=$?Qs($):null,J=d.x+d.width/2-m.width/2,re=d.y+d.height/2-m.height/2;switch(T){case Vt:a={x:J,y:d.y-m.height};break;case tn:a={x:J,y:d.y+d.height};break;case nn:a={x:d.x+d.width,y:re};break;case jt:a={x:d.x-m.width,y:re};break;default:a={x:d.x,y:d.y}}var pe=T?$r(T):null;if(pe!=null){var ge=pe==="y"?"height":"width";switch(B){case vs:a[pe]=a[pe]-(d[ge]/2-m[ge]/2);break;case qs:a[pe]=a[pe]+(d[ge]/2-m[ge]/2)}}return a}function Js(p,a){a===void 0&&(a={});var d=a,m=d.placement,$=m===void 0?p.placement:m,T=d.strategy,B=T===void 0?p.strategy:T,J=d.boundary,re=J===void 0?dl:J,pe=d.rootBoundary,ge=pe===void 0?yr:pe,fe=d.elementContext,Ve=fe===void 0?Ws:fe,Pe=d.altBoundary,Ne=Pe!==void 0&&Pe,De=d.padding,Fe=De===void 0?0:De,lt=$l(typeof Fe!="number"?Fe:Tl(Fe,js)),vt=Ve===Ws?fl:Ws,We=p.rects.popper,tt=p.elements[Ne?vt:Ve],je=function(qt,fn,hn,_t){var Dn=fn==="clippingParents"?function(ft){var Wt=So(ui(ft)),pn=["absolute","fixed"].indexOf(Un(ft).position)>=0&&un(ft)?Co(ft):ft;return bs(pn)?Wt.filter(function(rs){return bs(rs)&&Sl(rs,pn)&&On(rs)!=="body"}):[]}(qt):[].concat(fn),Ln=[].concat(Dn,[hn]),Zs=Ln[0],Mt=Ln.reduce(function(ft,Wt){var pn=Ol(qt,Wt,_t);return ft.top=ys(pn.top,ft.top),ft.right=ci(pn.right,ft.right),ft.bottom=ci(pn.bottom,ft.bottom),ft.left=ys(pn.left,ft.left),ft},Ol(qt,Zs,_t));return Mt.width=Mt.right-Mt.left,Mt.height=Mt.bottom-Mt.top,Mt.x=Mt.left,Mt.y=Mt.top,Mt}(bs(tt)?tt:tt.contextElement||os(p.elements.popper),re,ge,B),Ge=Gs(p.elements.reference),it=Ml({reference:Ge,element:We,placement:$}),ct=Or(Object.assign({},We,it)),rt=Ve===Ws?ct:Ge,St={top:je.top-rt.top+lt.top,bottom:rt.bottom-je.bottom+lt.bottom,left:je.left-rt.left+lt.left,right:rt.right-je.right+lt.right},on=p.modifiersData.offset;if(Ve===Ws&&on){var wn=on[$];Object.keys(St).forEach(function(qt){var fn=[nn,tn].indexOf(qt)>=0?1:-1,hn=[Vt,tn].indexOf(qt)>=0?"y":"x";St[qt]+=wn[hn]*fn})}return St}function hh(p,a){a===void 0&&(a={});var d=a,m=d.placement,$=d.boundary,T=d.rootBoundary,B=d.padding,J=d.flipVariations,re=d.allowedAutoPlacements,pe=re===void 0?_r:re,ge=Qs(m),fe=ge?J?wr:wr.filter(function(Ne){return Qs(Ne)===ge}):js,Ve=fe.filter(function(Ne){return pe.indexOf(Ne)>=0});Ve.length===0&&(Ve=fe);var Pe=Ve.reduce(function(Ne,De){return Ne[De]=Js(p,{placement:De,boundary:$,rootBoundary:T,padding:B})[Mn(De)],Ne},{});return Object.keys(Pe).sort(function(Ne,De){return Pe[Ne]-Pe[De]})}const Dl={name:"flip",enabled:!0,phase:"main",fn:function(p){var a=p.state,d=p.options,m=p.name;if(!a.modifiersData[m]._skip){for(var $=d.mainAxis,T=$===void 0||$,B=d.altAxis,J=B===void 0||B,re=d.fallbackPlacements,pe=d.padding,ge=d.boundary,fe=d.rootBoundary,Ve=d.altBoundary,Pe=d.flipVariations,Ne=Pe===void 0||Pe,De=d.allowedAutoPlacements,Fe=a.options.placement,lt=Mn(Fe),vt=re||(lt!==Fe&&Ne?function(ft){if(Mn(ft)===li)return[];var Wt=fi(ft);return[Pl(ft),Wt,Pl(Wt)]}(Fe):[fi(Fe)]),We=[Fe].concat(vt).reduce(function(ft,Wt){return ft.concat(Mn(Wt)===li?hh(a,{placement:Wt,boundary:ge,rootBoundary:fe,padding:pe,flipVariations:Ne,allowedAutoPlacements:De}):Wt)},[]),tt=a.rects.reference,je=a.rects.popper,Ge=new Map,it=!0,ct=We[0],rt=0;rt=0,fn=qt?"width":"height",hn=Js(a,{placement:St,boundary:ge,rootBoundary:fe,altBoundary:Ve,padding:pe}),_t=qt?wn?nn:jt:wn?tn:Vt;tt[fn]>je[fn]&&(_t=fi(_t));var Dn=fi(_t),Ln=[];if(T&&Ln.push(hn[on]<=0),J&&Ln.push(hn[_t]<=0,hn[Dn]<=0),Ln.every(function(ft){return ft})){ct=St,it=!1;break}Ge.set(St,Ln)}if(it)for(var Zs=function(ft){var Wt=We.find(function(pn){var rs=Ge.get(pn);if(rs)return rs.slice(0,ft).every(function(_i){return _i})});if(Wt)return ct=Wt,"break"},Mt=Ne?3:1;Mt>0&&Zs(Mt)!=="break";Mt--);a.placement!==ct&&(a.modifiersData[m]._skip=!0,a.placement=ct,a.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function Ll(p,a,d){return d===void 0&&(d={x:0,y:0}),{top:p.top-a.height-d.y,right:p.right-a.width+d.x,bottom:p.bottom-a.height+d.y,left:p.left-a.width-d.x}}function Nl(p){return[Vt,nn,tn,jt].some(function(a){return p[a]>=0})}const Fl={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(p){var a=p.state,d=p.name,m=a.rects.reference,$=a.rects.popper,T=a.modifiersData.preventOverflow,B=Js(a,{elementContext:"reference"}),J=Js(a,{altBoundary:!0}),re=Ll(B,m),pe=Ll(J,$,T),ge=Nl(re),fe=Nl(pe);a.modifiersData[d]={referenceClippingOffsets:re,popperEscapeOffsets:pe,isReferenceHidden:ge,hasPopperEscaped:fe},a.attributes.popper=Object.assign({},a.attributes.popper,{"data-popper-reference-hidden":ge,"data-popper-escaped":fe})}},xl={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(p){var a=p.state,d=p.options,m=p.name,$=d.offset,T=$===void 0?[0,0]:$,B=_r.reduce(function(ge,fe){return ge[fe]=function(Ve,Pe,Ne){var De=Mn(Ve),Fe=[jt,Vt].indexOf(De)>=0?-1:1,lt=typeof Ne=="function"?Ne(Object.assign({},Pe,{placement:Ve})):Ne,vt=lt[0],We=lt[1];return vt=vt||0,We=(We||0)*Fe,[jt,nn].indexOf(De)>=0?{x:We,y:vt}:{x:vt,y:We}}(fe,a.rects,T),ge},{}),J=B[a.placement],re=J.x,pe=J.y;a.modifiersData.popperOffsets!=null&&(a.modifiersData.popperOffsets.x+=re,a.modifiersData.popperOffsets.y+=pe),a.modifiersData[m]=B}},Mr={name:"popperOffsets",enabled:!0,phase:"read",fn:function(p){var a=p.state,d=p.name;a.modifiersData[d]=Ml({reference:a.rects.reference,element:a.rects.popper,placement:a.placement})},data:{}},Bl={name:"preventOverflow",enabled:!0,phase:"main",fn:function(p){var a=p.state,d=p.options,m=p.name,$=d.mainAxis,T=$===void 0||$,B=d.altAxis,J=B!==void 0&&B,re=d.boundary,pe=d.rootBoundary,ge=d.altBoundary,fe=d.padding,Ve=d.tether,Pe=Ve===void 0||Ve,Ne=d.tetherOffset,De=Ne===void 0?0:Ne,Fe=Js(a,{boundary:re,rootBoundary:pe,padding:fe,altBoundary:ge}),lt=Mn(a.placement),vt=Qs(a.placement),We=!vt,tt=$r(lt),je=tt==="x"?"y":"x",Ge=a.modifiersData.popperOffsets,it=a.rects.reference,ct=a.rects.popper,rt=typeof De=="function"?De(Object.assign({},a.rects,{placement:a.placement})):De,St=typeof rt=="number"?{mainAxis:rt,altAxis:rt}:Object.assign({mainAxis:0,altAxis:0},rt),on=a.modifiersData.offset?a.modifiersData.offset[a.placement]:null,wn={x:0,y:0};if(Ge){if(T){var qt,fn=tt==="y"?Vt:jt,hn=tt==="y"?tn:nn,_t=tt==="y"?"height":"width",Dn=Ge[tt],Ln=Dn+Fe[fn],Zs=Dn-Fe[hn],Mt=Pe?-ct[_t]/2:0,ft=vt===vs?it[_t]:ct[_t],Wt=vt===vs?-ct[_t]:-it[_t],pn=a.elements.arrow,rs=Pe&&pn?Er(pn):{width:0,height:0},_i=a.modifiersData["arrow#persistent"]?a.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},Ec=_i[fn],$c=_i[hn],Ci=ko(0,it[_t],rs[_t]),qp=We?it[_t]/2-Mt-Ci-Ec-St.mainAxis:ft-Ci-Ec-St.mainAxis,Wp=We?-it[_t]/2+Mt+Ci+$c+St.mainAxis:Wt+Ci+$c+St.mainAxis,Kr=a.elements.arrow&&Co(a.elements.arrow),Kp=Kr?tt==="y"?Kr.clientTop||0:Kr.clientLeft||0:0,Tc=(qt=on==null?void 0:on[tt])!=null?qt:0,Gp=Dn+Wp-Tc,Ac=ko(Pe?ci(Ln,Dn+qp-Tc-Kp):Ln,Dn,Pe?ys(Zs,Gp):Zs);Ge[tt]=Ac,wn[tt]=Ac-Dn}if(J){var Rc,Qp=tt==="x"?Vt:jt,Jp=tt==="x"?tn:nn,Ts=Ge[je],ki=je==="y"?"height":"width",Pc=Ts+Fe[Qp],Ic=Ts-Fe[Jp],Gr=[Vt,jt].indexOf(lt)!==-1,Oc=(Rc=on==null?void 0:on[je])!=null?Rc:0,Mc=Gr?Pc:Ts-it[ki]-ct[ki]-Oc+St.altAxis,Dc=Gr?Ts+it[ki]+ct[ki]-Oc-St.altAxis:Ic,Lc=Pe&&Gr?function(Xp,Yp,Qr){var Nc=ko(Xp,Yp,Qr);return Nc>Qr?Qr:Nc}(Mc,Ts,Dc):ko(Pe?Mc:Pc,Ts,Pe?Dc:Ic);Ge[je]=Lc,wn[je]=Lc-Ts}a.modifiersData[m]=wn}},requiresIfExists:["offset"]};function ph(p,a,d){d===void 0&&(d=!1);var m,$,T=un(a),B=un(a)&&function(fe){var Ve=fe.getBoundingClientRect(),Pe=Ks(Ve.width)/fe.offsetWidth||1,Ne=Ks(Ve.height)/fe.offsetHeight||1;return Pe!==1||Ne!==1}(a),J=os(a),re=Gs(p,B,d),pe={scrollLeft:0,scrollTop:0},ge={x:0,y:0};return(T||!T&&!d)&&((On(a)!=="body"||Ir(J))&&(pe=(m=a)!==sn(m)&&un(m)?{scrollLeft:($=m).scrollLeft,scrollTop:$.scrollTop}:Rr(m)),un(a)?((ge=Gs(a,!0)).x+=a.clientLeft,ge.y+=a.clientTop):J&&(ge.x=Pr(J))),{x:re.left+pe.scrollLeft-ge.x,y:re.top+pe.scrollTop-ge.y,width:re.width,height:re.height}}function gh(p){var a=new Map,d=new Set,m=[];function $(T){d.add(T.name),[].concat(T.requires||[],T.requiresIfExists||[]).forEach(function(B){if(!d.has(B)){var J=a.get(B);J&&$(J)}}),m.push(T)}return p.forEach(function(T){a.set(T.name,T)}),p.forEach(function(T){d.has(T.name)||$(T)}),m}var zl={placement:"bottom",modifiers:[],strategy:"absolute"};function Hl(){for(var p=arguments.length,a=new Array(p),d=0;dNumber.parseInt(d,10)):typeof a=="function"?d=>a(d,this._element):a}_getPopperConfig(){const a={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||this._config.display==="static")&&(gt.setDataAttribute(this._menu,"popper","static"),a.modifiers=[{name:"applyStyles",enabled:!1}]),{...a,...G(this._config.popperConfig,[void 0,a])}}_selectMenuItem({key:a,target:d}){const m=S.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter($=>f($));m.length&&ne(m,d,a===jl,!m.includes(d)).focus()}static jQueryInterface(a){return this.each(function(){const d=yn.getOrCreateInstance(this,a);if(typeof a=="string"){if(d[a]===void 0)throw new TypeError(`No method named "${a}"`);d[a]()}})}static clearMenus(a){if(a.button===2||a.type==="keyup"&&a.key!=="Tab")return;const d=S.find(Sh);for(const m of d){const $=yn.getInstance(m);if(!$||$._config.autoClose===!1)continue;const T=a.composedPath(),B=T.includes($._menu);if(T.includes($._element)||$._config.autoClose==="inside"&&!B||$._config.autoClose==="outside"&&B||$._menu.contains(a.target)&&(a.type==="keyup"&&a.key==="Tab"||/input|select|option|textarea|form/i.test(a.target.tagName)))continue;const J={relatedTarget:$._element};a.type==="click"&&(J.clickEvent=a),$._completeHide(J)}}static dataApiKeydownHandler(a){const d=/input|textarea/i.test(a.target.tagName),m=a.key==="Escape",$=[bh,jl].includes(a.key);if(!$&&!m||d&&!m)return;a.preventDefault();const T=this.matches(_s)?this:S.prev(this,_s)[0]||S.next(this,_s)[0]||S.findOne(_s,a.delegateTarget.parentNode),B=yn.getOrCreateInstance(T);if($)return a.stopPropagation(),B.show(),void B._selectMenuItem(a);B._isShown()&&(a.stopPropagation(),B.hide(),T.focus())}}z.on(document,Wl,_s,yn.dataApiKeydownHandler),z.on(document,Wl,pi,yn.dataApiKeydownHandler),z.on(document,ql,yn.clearMenus),z.on(document,kh,yn.clearMenus),z.on(document,ql,_s,function(p){p.preventDefault(),yn.getOrCreateInstance(this).toggle()}),W(yn);const Kl="backdrop",Gl="show",Ql=`mousedown.bs.${Kl}`,Mh={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Dh={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Jl extends Ae{constructor(a){super(),this._config=this._getConfig(a),this._isAppended=!1,this._element=null}static get Default(){return Mh}static get DefaultType(){return Dh}static get NAME(){return Kl}show(a){if(!this._config.isVisible)return void G(a);this._append();const d=this._getElement();this._config.isAnimated&&y(d),d.classList.add(Gl),this._emulateAnimation(()=>{G(a)})}hide(a){this._config.isVisible?(this._getElement().classList.remove(Gl),this._emulateAnimation(()=>{this.dispose(),G(a)})):G(a)}dispose(){this._isAppended&&(z.off(this._element,Ql),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const a=document.createElement("div");a.className=this._config.className,this._config.isAnimated&&a.classList.add("fade"),this._element=a}return this._element}_configAfterMerge(a){return a.rootElement=h(a.rootElement),a}_append(){if(this._isAppended)return;const a=this._getElement();this._config.rootElement.append(a),z.on(a,Ql,()=>{G(this._config.clickCallback)}),this._isAppended=!0}_emulateAnimation(a){F(a,this._getElement(),this._config.isAnimated)}}const gi=".bs.focustrap",Lh=`focusin${gi}`,Nh=`keydown.tab${gi}`,Xl="backward",Fh={autofocus:!0,trapElement:null},xh={autofocus:"boolean",trapElement:"element"};class Yl extends Ae{constructor(a){super(),this._config=this._getConfig(a),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return Fh}static get DefaultType(){return xh}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),z.off(document,gi),z.on(document,Lh,a=>this._handleFocusin(a)),z.on(document,Nh,a=>this._handleKeydown(a)),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,z.off(document,gi))}_handleFocusin(a){const{trapElement:d}=this._config;if(a.target===document||a.target===d||d.contains(a.target))return;const m=S.focusableChildren(d);m.length===0?d.focus():this._lastTabNavDirection===Xl?m[m.length-1].focus():m[0].focus()}_handleKeydown(a){a.key==="Tab"&&(this._lastTabNavDirection=a.shiftKey?Xl:"forward")}}const Zl=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",ec=".sticky-top",mi="padding-right",tc="margin-right";class Nr{constructor(){this._element=document.body}getWidth(){const a=document.documentElement.clientWidth;return Math.abs(window.innerWidth-a)}hide(){const a=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,mi,d=>d+a),this._setElementAttributes(Zl,mi,d=>d+a),this._setElementAttributes(ec,tc,d=>d-a)}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,mi),this._resetElementAttributes(Zl,mi),this._resetElementAttributes(ec,tc)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(a,d,m){const $=this.getWidth();this._applyManipulationCallback(a,T=>{if(T!==this._element&&window.innerWidth>T.clientWidth+$)return;this._saveInitialAttribute(T,d);const B=window.getComputedStyle(T).getPropertyValue(d);T.style.setProperty(d,`${m(Number.parseFloat(B))}px`)})}_saveInitialAttribute(a,d){const m=a.style.getPropertyValue(d);m&>.setDataAttribute(a,d,m)}_resetElementAttributes(a,d){this._applyManipulationCallback(a,m=>{const $=gt.getDataAttribute(m,d);$!==null?(gt.removeDataAttribute(m,d),m.style.setProperty(d,$)):m.style.removeProperty(d)})}_applyManipulationCallback(a,d){if(u(a))d(a);else for(const m of S.find(a,this._element))d(m)}}const dn=".bs.modal",Bh=`hide${dn}`,zh=`hidePrevented${dn}`,nc=`hidden${dn}`,sc=`show${dn}`,Hh=`shown${dn}`,Uh=`resize${dn}`,Vh=`click.dismiss${dn}`,jh=`mousedown.dismiss${dn}`,qh=`keydown.dismiss${dn}`,Wh=`click${dn}.data-api`,oc="modal-open",ic="show",Fr="modal-static",Kh={backdrop:!0,focus:!0,keyboard:!0},Gh={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class Cs extends M{constructor(a,d){super(a,d),this._dialog=S.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new Nr,this._addEventListeners()}static get Default(){return Kh}static get DefaultType(){return Gh}static get NAME(){return"modal"}toggle(a){return this._isShown?this.hide():this.show(a)}show(a){this._isShown||this._isTransitioning||z.trigger(this._element,sc,{relatedTarget:a}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(oc),this._adjustDialog(),this._backdrop.show(()=>this._showElement(a)))}hide(){this._isShown&&!this._isTransitioning&&(z.trigger(this._element,Bh).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(ic),this._queueCallback(()=>this._hideModal(),this._element,this._isAnimated())))}dispose(){z.off(window,dn),z.off(this._dialog,dn),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Jl({isVisible:!!this._config.backdrop,isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new Yl({trapElement:this._element})}_showElement(a){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const d=S.findOne(".modal-body",this._dialog);d&&(d.scrollTop=0),y(this._element),this._element.classList.add(ic),this._queueCallback(()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,z.trigger(this._element,Hh,{relatedTarget:a})},this._dialog,this._isAnimated())}_addEventListeners(){z.on(this._element,qh,a=>{a.key==="Escape"&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())}),z.on(window,Uh,()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()}),z.on(this._element,jh,a=>{z.one(this._element,Vh,d=>{this._element===a.target&&this._element===d.target&&(this._config.backdrop!=="static"?this._config.backdrop&&this.hide():this._triggerBackdropTransition())})})}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide(()=>{document.body.classList.remove(oc),this._resetAdjustments(),this._scrollBar.reset(),z.trigger(this._element,nc)})}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(z.trigger(this._element,zh).defaultPrevented)return;const a=this._element.scrollHeight>document.documentElement.clientHeight,d=this._element.style.overflowY;d==="hidden"||this._element.classList.contains(Fr)||(a||(this._element.style.overflowY="hidden"),this._element.classList.add(Fr),this._queueCallback(()=>{this._element.classList.remove(Fr),this._queueCallback(()=>{this._element.style.overflowY=d},this._dialog)},this._dialog),this._element.focus())}_adjustDialog(){const a=this._element.scrollHeight>document.documentElement.clientHeight,d=this._scrollBar.getWidth(),m=d>0;if(m&&!a){const $=H()?"paddingLeft":"paddingRight";this._element.style[$]=`${d}px`}if(!m&&a){const $=H()?"paddingRight":"paddingLeft";this._element.style[$]=`${d}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(a,d){return this.each(function(){const m=Cs.getOrCreateInstance(this,a);if(typeof a=="string"){if(m[a]===void 0)throw new TypeError(`No method named "${a}"`);m[a](d)}})}}z.on(document,Wh,'[data-bs-toggle="modal"]',function(p){const a=S.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&p.preventDefault(),z.one(a,sc,m=>{m.defaultPrevented||z.one(a,nc,()=>{f(this)&&this.focus()})});const d=S.findOne(".modal.show");d&&Cs.getInstance(d).hide(),Cs.getOrCreateInstance(a).toggle(this)}),x(Cs),W(Cs);const Vn=".bs.offcanvas",rc=".data-api",Qh=`load${Vn}${rc}`,ac="show",lc="showing",cc="hiding",uc=".offcanvas.show",Jh=`show${Vn}`,Xh=`shown${Vn}`,Yh=`hide${Vn}`,dc=`hidePrevented${Vn}`,fc=`hidden${Vn}`,Zh=`resize${Vn}`,ep=`click${Vn}${rc}`,tp=`keydown.dismiss${Vn}`,np={backdrop:!0,keyboard:!0,scroll:!1},sp={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class jn extends M{constructor(a,d){super(a,d),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return np}static get DefaultType(){return sp}static get NAME(){return"offcanvas"}toggle(a){return this._isShown?this.hide():this.show(a)}show(a){this._isShown||z.trigger(this._element,Jh,{relatedTarget:a}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||new Nr().hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(lc),this._queueCallback(()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(ac),this._element.classList.remove(lc),z.trigger(this._element,Xh,{relatedTarget:a})},this._element,!0))}hide(){this._isShown&&(z.trigger(this._element,Yh).defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add(cc),this._backdrop.hide(),this._queueCallback(()=>{this._element.classList.remove(ac,cc),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||new Nr().reset(),z.trigger(this._element,fc)},this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const a=!!this._config.backdrop;return new Jl({className:"offcanvas-backdrop",isVisible:a,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:a?()=>{this._config.backdrop!=="static"?this.hide():z.trigger(this._element,dc)}:null})}_initializeFocusTrap(){return new Yl({trapElement:this._element})}_addEventListeners(){z.on(this._element,tp,a=>{a.key==="Escape"&&(this._config.keyboard?this.hide():z.trigger(this._element,dc))})}static jQueryInterface(a){return this.each(function(){const d=jn.getOrCreateInstance(this,a);if(typeof a=="string"){if(d[a]===void 0||a.startsWith("_")||a==="constructor")throw new TypeError(`No method named "${a}"`);d[a](this)}})}}z.on(document,ep,'[data-bs-toggle="offcanvas"]',function(p){const a=S.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&p.preventDefault(),g(this))return;z.one(a,fc,()=>{f(this)&&this.focus()});const d=S.findOne(uc);d&&d!==a&&jn.getInstance(d).hide(),jn.getOrCreateInstance(a).toggle(this)}),z.on(window,Qh,()=>{for(const p of S.find(uc))jn.getOrCreateInstance(p).show()}),z.on(window,Zh,()=>{for(const p of S.find("[aria-modal][class*=show][class*=offcanvas-]"))getComputedStyle(p).position!=="fixed"&&jn.getOrCreateInstance(p).hide()}),x(jn),W(jn);const hc={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],dd:[],div:[],dl:[],dt:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},op=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),ip=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,rp=(p,a)=>{const d=p.nodeName.toLowerCase();return a.includes(d)?!op.has(d)||!!ip.test(p.nodeValue):a.filter(m=>m instanceof RegExp).some(m=>m.test(d))},ap={allowList:hc,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},lp={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},cp={entry:"(string|element|function|null)",selector:"(string|element)"};class up extends Ae{constructor(a){super(),this._config=this._getConfig(a)}static get Default(){return ap}static get DefaultType(){return lp}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map(a=>this._resolvePossibleFunction(a)).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(a){return this._checkContent(a),this._config.content={...this._config.content,...a},this}toHtml(){const a=document.createElement("div");a.innerHTML=this._maybeSanitize(this._config.template);for(const[$,T]of Object.entries(this._config.content))this._setContent(a,T,$);const d=a.children[0],m=this._resolvePossibleFunction(this._config.extraClass);return m&&d.classList.add(...m.split(" ")),d}_typeCheckConfig(a){super._typeCheckConfig(a),this._checkContent(a.content)}_checkContent(a){for(const[d,m]of Object.entries(a))super._typeCheckConfig({selector:d,entry:m},cp)}_setContent(a,d,m){const $=S.findOne(m,a);$&&((d=this._resolvePossibleFunction(d))?u(d)?this._putElementInTemplate(h(d),$):this._config.html?$.innerHTML=this._maybeSanitize(d):$.textContent=d:$.remove())}_maybeSanitize(a){return this._config.sanitize?function(d,m,$){if(!d.length)return d;if($&&typeof $=="function")return $(d);const T=new window.DOMParser().parseFromString(d,"text/html"),B=[].concat(...T.body.querySelectorAll("*"));for(const J of B){const re=J.nodeName.toLowerCase();if(!Object.keys(m).includes(re)){J.remove();continue}const pe=[].concat(...J.attributes),ge=[].concat(m["*"]||[],m[re]||[]);for(const fe of pe)rp(fe,ge)||J.removeAttribute(fe.nodeName)}return T.body.innerHTML}(a,this._config.allowList,this._config.sanitizeFn):a}_resolvePossibleFunction(a){return G(a,[void 0,this])}_putElementInTemplate(a,d){if(this._config.html)return d.innerHTML="",void d.append(a);d.textContent=a.textContent}}const dp=new Set(["sanitize","allowList","sanitizeFn"]),xr="fade",vi="show",fp=".tooltip-inner",pc=".modal",gc="hide.bs.modal",Eo="hover",Br="focus",zr="click",hp={AUTO:"auto",TOP:"top",RIGHT:H()?"left":"right",BOTTOM:"bottom",LEFT:H()?"right":"left"},pp={allowList:hc,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},gp={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class ks extends M{constructor(a,d){if(Ul===void 0)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org/docs/v2/)");super(a,d),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return pp}static get DefaultType(){return gp}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),z.off(this._element.closest(pc),gc,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if(this._element.style.display==="none")throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const a=z.trigger(this._element,this.constructor.eventName("show")),d=(C(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(a.defaultPrevented||!d)return;this._disposePopper();const m=this._getTipElement();this._element.setAttribute("aria-describedby",m.getAttribute("id"));const{container:$}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||($.append(m),z.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(m),m.classList.add(vi),"ontouchstart"in document.documentElement)for(const T of[].concat(...document.body.children))z.on(T,"mouseover",_);this._queueCallback(()=>{z.trigger(this._element,this.constructor.eventName("shown")),this._isHovered===!1&&this._leave(),this._isHovered=!1},this.tip,this._isAnimated())}hide(){if(this._isShown()&&!z.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(vi),"ontouchstart"in document.documentElement)for(const a of[].concat(...document.body.children))z.off(a,"mouseover",_);this._activeTrigger[zr]=!1,this._activeTrigger[Br]=!1,this._activeTrigger[Eo]=!1,this._isHovered=null,this._queueCallback(()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),z.trigger(this._element,this.constructor.eventName("hidden")))},this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return!!this._getTitle()}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(a){const d=this._getTemplateFactory(a).toHtml();if(!d)return null;d.classList.remove(xr,vi),d.classList.add(`bs-${this.constructor.NAME}-auto`);const m=($=>{do $+=Math.floor(1e6*Math.random());while(document.getElementById($));return $})(this.constructor.NAME).toString();return d.setAttribute("id",m),this._isAnimated()&&d.classList.add(xr),d}setContent(a){this._newContent=a,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(a){return this._templateFactory?this._templateFactory.changeContent(a):this._templateFactory=new up({...this._config,content:a,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{[fp]:this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(a){return this.constructor.getOrCreateInstance(a.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(xr)}_isShown(){return this.tip&&this.tip.classList.contains(vi)}_createPopper(a){const d=G(this._config.placement,[this,a,this._element]),m=hp[d.toUpperCase()];return Dr(this._element,a,this._getPopperConfig(m))}_getOffset(){const{offset:a}=this._config;return typeof a=="string"?a.split(",").map(d=>Number.parseInt(d,10)):typeof a=="function"?d=>a(d,this._element):a}_resolvePossibleFunction(a){return G(a,[this._element,this._element])}_getPopperConfig(a){const d={placement:a,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:m=>{this._getTipElement().setAttribute("data-popper-placement",m.state.placement)}}]};return{...d,...G(this._config.popperConfig,[void 0,d])}}_setListeners(){const a=this._config.trigger.split(" ");for(const d of a)if(d==="click")z.on(this._element,this.constructor.eventName("click"),this._config.selector,m=>{const $=this._initializeOnDelegatedTarget(m);$._activeTrigger[zr]=!($._isShown()&&$._activeTrigger[zr]),$.toggle()});else if(d!=="manual"){const m=d===Eo?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),$=d===Eo?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");z.on(this._element,m,this._config.selector,T=>{const B=this._initializeOnDelegatedTarget(T);B._activeTrigger[T.type==="focusin"?Br:Eo]=!0,B._enter()}),z.on(this._element,$,this._config.selector,T=>{const B=this._initializeOnDelegatedTarget(T);B._activeTrigger[T.type==="focusout"?Br:Eo]=B._element.contains(T.relatedTarget),B._leave()})}this._hideModalHandler=()=>{this._element&&this.hide()},z.on(this._element.closest(pc),gc,this._hideModalHandler)}_fixTitle(){const a=this._element.getAttribute("title");a&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",a),this._element.setAttribute("data-bs-original-title",a),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout(()=>{this._isHovered&&this.show()},this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout(()=>{this._isHovered||this.hide()},this._config.delay.hide))}_setTimeout(a,d){clearTimeout(this._timeout),this._timeout=setTimeout(a,d)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(a){const d=gt.getDataAttributes(this._element);for(const m of Object.keys(d))dp.has(m)&&delete d[m];return a={...d,...typeof a=="object"&&a?a:{}},a=this._mergeConfigObj(a),a=this._configAfterMerge(a),this._typeCheckConfig(a),a}_configAfterMerge(a){return a.container=a.container===!1?document.body:h(a.container),typeof a.delay=="number"&&(a.delay={show:a.delay,hide:a.delay}),typeof a.title=="number"&&(a.title=a.title.toString()),typeof a.content=="number"&&(a.content=a.content.toString()),a}_getDelegateConfig(){const a={};for(const[d,m]of Object.entries(this._config))this.constructor.Default[d]!==m&&(a[d]=m);return a.selector=!1,a.trigger="manual",a}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(a){return this.each(function(){const d=ks.getOrCreateInstance(this,a);if(typeof a=="string"){if(d[a]===void 0)throw new TypeError(`No method named "${a}"`);d[a]()}})}}W(ks);const mp=".popover-header",vp=".popover-body",bp={...ks.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},yp={...ks.DefaultType,content:"(null|string|element|function)"};class bi extends ks{static get Default(){return bp}static get DefaultType(){return yp}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{[mp]:this._getTitle(),[vp]:this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(a){return this.each(function(){const d=bi.getOrCreateInstance(this,a);if(typeof a=="string"){if(d[a]===void 0)throw new TypeError(`No method named "${a}"`);d[a]()}})}}W(bi);const Hr=".bs.scrollspy",wp=`activate${Hr}`,mc=`click${Hr}`,_p=`load${Hr}.data-api`,Ys="active",Ur="[href]",vc=".nav-link",Cp=`${vc}, .nav-item > ${vc}, .list-group-item`,kp={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},Sp={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class $o extends M{constructor(a,d){super(a,d),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement=getComputedStyle(this._element).overflowY==="visible"?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return kp}static get DefaultType(){return Sp}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const a of this._observableSections.values())this._observer.observe(a)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(a){return a.target=h(a.target)||document.body,a.rootMargin=a.offset?`${a.offset}px 0px -30%`:a.rootMargin,typeof a.threshold=="string"&&(a.threshold=a.threshold.split(",").map(d=>Number.parseFloat(d))),a}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(z.off(this._config.target,mc),z.on(this._config.target,mc,Ur,a=>{const d=this._observableSections.get(a.target.hash);if(d){a.preventDefault();const m=this._rootElement||window,$=d.offsetTop-this._element.offsetTop;if(m.scrollTo)return void m.scrollTo({top:$,behavior:"smooth"});m.scrollTop=$}}))}_getNewObserver(){const a={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver(d=>this._observerCallback(d),a)}_observerCallback(a){const d=B=>this._targetLinks.get(`#${B.target.id}`),m=B=>{this._previousScrollData.visibleEntryTop=B.target.offsetTop,this._process(d(B))},$=(this._rootElement||document.documentElement).scrollTop,T=$>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=$;for(const B of a){if(!B.isIntersecting){this._activeTarget=null,this._clearActiveClass(d(B));continue}const J=B.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(T&&J){if(m(B),!$)return}else T||J||m(B)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const a=S.find(Ur,this._config.target);for(const d of a){if(!d.hash||g(d))continue;const m=S.findOne(decodeURI(d.hash),this._element);f(m)&&(this._targetLinks.set(decodeURI(d.hash),d),this._observableSections.set(d.hash,m))}}_process(a){this._activeTarget!==a&&(this._clearActiveClass(this._config.target),this._activeTarget=a,a.classList.add(Ys),this._activateParents(a),z.trigger(this._element,wp,{relatedTarget:a}))}_activateParents(a){if(a.classList.contains("dropdown-item"))S.findOne(".dropdown-toggle",a.closest(".dropdown")).classList.add(Ys);else for(const d of S.parents(a,".nav, .list-group"))for(const m of S.prev(d,Cp))m.classList.add(Ys)}_clearActiveClass(a){a.classList.remove(Ys);const d=S.find(`${Ur}.${Ys}`,a);for(const m of d)m.classList.remove(Ys)}static jQueryInterface(a){return this.each(function(){const d=$o.getOrCreateInstance(this,a);if(typeof a=="string"){if(d[a]===void 0||a.startsWith("_")||a==="constructor")throw new TypeError(`No method named "${a}"`);d[a]()}})}}z.on(window,_p,()=>{for(const p of S.find('[data-bs-spy="scroll"]'))$o.getOrCreateInstance(p)}),W($o);const Ss=".bs.tab",Ep=`hide${Ss}`,$p=`hidden${Ss}`,Tp=`show${Ss}`,Ap=`shown${Ss}`,Rp=`click${Ss}`,Pp=`keydown${Ss}`,Ip=`load${Ss}`,Op="ArrowLeft",bc="ArrowRight",Mp="ArrowUp",yc="ArrowDown",Vr="Home",wc="End",Es="active",_c="fade",jr="show",Cc=".dropdown-toggle",qr=`:not(${Cc})`,kc='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',Wr=`.nav-link${qr}, .list-group-item${qr}, [role="tab"]${qr}, ${kc}`,Dp=`.${Es}[data-bs-toggle="tab"], .${Es}[data-bs-toggle="pill"], .${Es}[data-bs-toggle="list"]`;class $s extends M{constructor(a){super(a),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),z.on(this._element,Pp,d=>this._keydown(d)))}static get NAME(){return"tab"}show(){const a=this._element;if(this._elemIsActive(a))return;const d=this._getActiveElem(),m=d?z.trigger(d,Ep,{relatedTarget:a}):null;z.trigger(a,Tp,{relatedTarget:d}).defaultPrevented||m&&m.defaultPrevented||(this._deactivate(d,a),this._activate(a,d))}_activate(a,d){a&&(a.classList.add(Es),this._activate(S.getElementFromSelector(a)),this._queueCallback(()=>{a.getAttribute("role")==="tab"?(a.removeAttribute("tabindex"),a.setAttribute("aria-selected",!0),this._toggleDropDown(a,!0),z.trigger(a,Ap,{relatedTarget:d})):a.classList.add(jr)},a,a.classList.contains(_c)))}_deactivate(a,d){a&&(a.classList.remove(Es),a.blur(),this._deactivate(S.getElementFromSelector(a)),this._queueCallback(()=>{a.getAttribute("role")==="tab"?(a.setAttribute("aria-selected",!1),a.setAttribute("tabindex","-1"),this._toggleDropDown(a,!1),z.trigger(a,$p,{relatedTarget:d})):a.classList.remove(jr)},a,a.classList.contains(_c)))}_keydown(a){if(![Op,bc,Mp,yc,Vr,wc].includes(a.key))return;a.stopPropagation(),a.preventDefault();const d=this._getChildren().filter($=>!g($));let m;if([Vr,wc].includes(a.key))m=d[a.key===Vr?0:d.length-1];else{const $=[bc,yc].includes(a.key);m=ne(d,a.target,$,!0)}m&&(m.focus({preventScroll:!0}),$s.getOrCreateInstance(m).show())}_getChildren(){return S.find(Wr,this._parent)}_getActiveElem(){return this._getChildren().find(a=>this._elemIsActive(a))||null}_setInitialAttributes(a,d){this._setAttributeIfNotExists(a,"role","tablist");for(const m of d)this._setInitialAttributesOnChild(m)}_setInitialAttributesOnChild(a){a=this._getInnerElement(a);const d=this._elemIsActive(a),m=this._getOuterElement(a);a.setAttribute("aria-selected",d),m!==a&&this._setAttributeIfNotExists(m,"role","presentation"),d||a.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(a,"role","tab"),this._setInitialAttributesOnTargetPanel(a)}_setInitialAttributesOnTargetPanel(a){const d=S.getElementFromSelector(a);d&&(this._setAttributeIfNotExists(d,"role","tabpanel"),a.id&&this._setAttributeIfNotExists(d,"aria-labelledby",`${a.id}`))}_toggleDropDown(a,d){const m=this._getOuterElement(a);if(!m.classList.contains("dropdown"))return;const $=(T,B)=>{const J=S.findOne(T,m);J&&J.classList.toggle(B,d)};$(Cc,Es),$(".dropdown-menu",jr),m.setAttribute("aria-expanded",d)}_setAttributeIfNotExists(a,d,m){a.hasAttribute(d)||a.setAttribute(d,m)}_elemIsActive(a){return a.classList.contains(Es)}_getInnerElement(a){return a.matches(Wr)?a:S.findOne(Wr,a)}_getOuterElement(a){return a.closest(".nav-item, .list-group-item")||a}static jQueryInterface(a){return this.each(function(){const d=$s.getOrCreateInstance(this);if(typeof a=="string"){if(d[a]===void 0||a.startsWith("_")||a==="constructor")throw new TypeError(`No method named "${a}"`);d[a]()}})}}z.on(document,Rp,kc,function(p){["A","AREA"].includes(this.tagName)&&p.preventDefault(),g(this)||$s.getOrCreateInstance(this).show()}),z.on(window,Ip,()=>{for(const p of S.find(Dp))$s.getOrCreateInstance(p)}),W($s);const is=".bs.toast",Lp=`mouseover${is}`,Np=`mouseout${is}`,Fp=`focusin${is}`,xp=`focusout${is}`,Bp=`hide${is}`,zp=`hidden${is}`,Hp=`show${is}`,Up=`shown${is}`,Sc="hide",yi="show",wi="showing",Vp={animation:"boolean",autohide:"boolean",delay:"number"},jp={animation:!0,autohide:!0,delay:5e3};class To extends M{constructor(a,d){super(a,d),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return jp}static get DefaultType(){return Vp}static get NAME(){return"toast"}show(){z.trigger(this._element,Hp).defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(Sc),y(this._element),this._element.classList.add(yi,wi),this._queueCallback(()=>{this._element.classList.remove(wi),z.trigger(this._element,Up),this._maybeScheduleHide()},this._element,this._config.animation))}hide(){this.isShown()&&(z.trigger(this._element,Bp).defaultPrevented||(this._element.classList.add(wi),this._queueCallback(()=>{this._element.classList.add(Sc),this._element.classList.remove(wi,yi),z.trigger(this._element,zp)},this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(yi),super.dispose()}isShown(){return this._element.classList.contains(yi)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout(()=>{this.hide()},this._config.delay)))}_onInteraction(a,d){switch(a.type){case"mouseover":case"mouseout":this._hasMouseInteraction=d;break;case"focusin":case"focusout":this._hasKeyboardInteraction=d}if(d)return void this._clearTimeout();const m=a.relatedTarget;this._element===m||this._element.contains(m)||this._maybeScheduleHide()}_setListeners(){z.on(this._element,Lp,a=>this._onInteraction(a,!0)),z.on(this._element,Np,a=>this._onInteraction(a,!1)),z.on(this._element,Fp,a=>this._onInteraction(a,!0)),z.on(this._element,xp,a=>this._onInteraction(a,!1))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(a){return this.each(function(){const d=To.getOrCreateInstance(this,a);if(typeof a=="string"){if(d[a]===void 0)throw new TypeError(`No method named "${a}"`);d[a](this)}})}}return x(To),W(To),{Alert:R,Button:K,Carousel:Hs,Collapse:Vs,Dropdown:yn,Modal:Cs,Offcanvas:jn,Popover:bi,ScrollSpy:$o,Tab:$s,Toast:To,Tooltip:ks}})})(d9);Cm(Jb).use(Jf).mount("#app");export{Xe as F,It as _,be as a,ti as b,Ye as c,$t as d,w as e,o as f,U as g,ke as h,Ze as i,zt as j,L as k,Be as l,zo as m,ae as n,cn as o,we as p,Yt as q,O as r,b as s,A as t,ns as u,at as v,hs as w}; diff --git a/src/assets/frontend/index.html b/src/assets/frontend/index.html new file mode 100644 index 00000000..795ad525 --- /dev/null +++ b/src/assets/frontend/index.html @@ -0,0 +1,15 @@ + + + + + + QuePasa Frontend + + + + + + +
+ + diff --git a/src/environment/api_settings.go b/src/environment/api_settings.go index 45ef726d..4ad79704 100644 --- a/src/environment/api_settings.go +++ b/src/environment/api_settings.go @@ -4,39 +4,42 @@ import "time" // API environment variable names const ( - ENV_WEBSOCKETSSL = "WEBSOCKETSSL" // use SSL for websocket qrcode - ENV_SIGNING_SECRET = "SIGNING_SECRET" // token for hash signing cookies - ENV_MASTER_KEY = "MASTERKEY" // used for manage all instances at all + ENV_WEBAPIPORT = "WEBAPIPORT" // web API port + ENV_WEBAPIHOST = "WEBAPIHOST" // web API host + ENV_HTTPLOGS = "HTTPLOGS" // log HTTP requests + ENV_WEBSOCKETSSL = "WEBSOCKETSSL" // use SSL for websocket qrcode + ENV_SIGNING_SECRET = "SIGNING_SECRET" // token for hash signing cookies + ENV_MASTER_KEY = "MASTERKEY" // used for manage all instances at all ENV_WEBHOOK_TIMEOUT = "WEBHOOK_TIMEOUT" // timeout in milliseconds for webhook requests - ENV_API_PREFIX = "API_PREFIX" // API routes prefix - ENV_API_TIMEOUT = "API_TIMEOUT" // API request timeout in milliseconds - ENV_USER = "USER" // default user for database seeding - ENV_PASSWORD = "PASSWORD" // default password for database seeding + ENV_API_PREFIX = "API_PREFIX" // API routes prefix + ENV_API_TIMEOUT = "API_TIMEOUT" // API request timeout in milliseconds + ENV_USER = "USER" // default user for database seeding + ENV_PASSWORD = "PASSWORD" // default password for database seeding ) // APISettings holds all API configuration loaded from environment type APISettings struct { - UseSSLWebSocket bool `json:"use_ssl_websocket"` - SigningSecret string `json:"signing_secret"` - MasterKey string `json:"master_key"` - WebhookTimeout uint32 `json:"webhook_timeout"` // webhook timeout in milliseconds - Prefix string `json:"prefix"` - Timeout uint32 `json:"timeout"` // API request timeout in milliseconds - User string `json:"user"` // default user for database seeding - Password string `json:"password"` // default password for database seeding + UseSSLWebSocket bool `json:"use_ssl_websocket"` + SigningSecret string `json:"signing_secret"` + MasterKey string `json:"master_key"` + WebhookTimeout uint32 `json:"webhook_timeout"` // webhook timeout in milliseconds + Prefix string `json:"prefix"` + Timeout uint32 `json:"timeout"` // API request timeout in milliseconds + User string `json:"user"` // default user for database seeding + Password string `json:"password"` // default password for database seeding } // NewAPISettings creates a new API settings by loading all values from environment func NewAPISettings() APISettings { return APISettings{ - UseSSLWebSocket: getEnvOrDefaultBool(ENV_WEBSOCKETSSL, false), - SigningSecret: getEnvOrDefaultString(ENV_SIGNING_SECRET, ""), - MasterKey: getEnvOrDefaultString(ENV_MASTER_KEY, ""), - WebhookTimeout: getEnvOrDefaultUint32(ENV_WEBHOOK_TIMEOUT, 10000), - Prefix: getEnvOrDefaultString(ENV_API_PREFIX, ""), - Timeout: getEnvOrDefaultUint32(ENV_API_TIMEOUT, 30000), - User: getEnvOrDefaultString(ENV_USER, ""), - Password: getEnvOrDefaultString(ENV_PASSWORD, ""), + UseSSLWebSocket: getEnvOrDefaultBool(ENV_WEBSOCKETSSL, false), + SigningSecret: getEnvOrDefaultString(ENV_SIGNING_SECRET, ""), + MasterKey: getEnvOrDefaultString(ENV_MASTER_KEY, ""), + WebhookTimeout: getEnvOrDefaultUint32(ENV_WEBHOOK_TIMEOUT, 10000), + Prefix: getEnvOrDefaultString(ENV_API_PREFIX, "api"), + Timeout: getEnvOrDefaultUint32(ENV_API_TIMEOUT, 30000), + User: getEnvOrDefaultString(ENV_USER, ""), + Password: getEnvOrDefaultString(ENV_PASSWORD, ""), } } diff --git a/src/environment/branding_settings.go b/src/environment/branding_settings.go new file mode 100644 index 00000000..a98dc13c --- /dev/null +++ b/src/environment/branding_settings.go @@ -0,0 +1,55 @@ +package environment + +// Branding environment variable names +const ( + ENV_BRANDING_TITLE = "BRANDING_TITLE" // Application title (default: "QuePasa") + ENV_BRANDING_LOGO = "BRANDING_LOGO" // Logo URL (default: QuePasa logo) + ENV_BRANDING_FAVICON = "BRANDING_FAVICON" // Favicon URL (default: QuePasa favicon) + ENV_BRANDING_PRIMARY_COLOR = "BRANDING_PRIMARY_COLOR" // Primary color (default: #7C3AED - QuePasa purple) + ENV_BRANDING_SECONDARY_COLOR = "BRANDING_SECONDARY_COLOR" // Secondary color (default: #5B21B6 - QuePasa dark purple) + ENV_BRANDING_ACCENT_COLOR = "BRANDING_ACCENT_COLOR" // Accent color (default: #8B5CF6 - QuePasa light purple) + ENV_BRANDING_COMPANY_NAME = "BRANDING_COMPANY_NAME" // Company name for footer + ENV_BRANDING_COMPANY_URL = "BRANDING_COMPANY_URL" // Company URL for footer link +) + +// Default QuePasa branding values +const ( + DefaultBrandingTitle = "QuePasa" + DefaultBrandingLogo = "https://raw.githubusercontent.com/nocodeleaks/quepasa/main/src/assets/favicon.png" + DefaultBrandingFavicon = "https://raw.githubusercontent.com/nocodeleaks/quepasa/main/src/assets/favicon.png" + DefaultBrandingPrimaryColor = "#7C3AED" // QuePasa purple + DefaultBrandingSecondaryColor = "#5B21B6" // QuePasa dark purple + DefaultBrandingAccentColor = "#8B5CF6" // QuePasa light purple +) + +// BrandingSettings holds all branding configuration loaded from environment +type BrandingSettings struct { + Title string `json:"title"` + Logo string `json:"logo"` + Favicon string `json:"favicon"` + PrimaryColor string `json:"primaryColor"` + SecondaryColor string `json:"secondaryColor"` + AccentColor string `json:"accentColor"` + CompanyName string `json:"companyName"` + CompanyUrl string `json:"companyUrl"` +} + +// NewBrandingSettings creates new Branding settings by loading all values from environment +func NewBrandingSettings() BrandingSettings { + // Use APP_TITLE as fallback for BRANDING_TITLE (for backwards compatibility) + title := getEnvOrDefaultString(ENV_BRANDING_TITLE, "") + if title == "" { + title = getEnvOrDefaultString(ENV_TITLE, DefaultBrandingTitle) + } + + return BrandingSettings{ + Title: title, + Logo: getEnvOrDefaultString(ENV_BRANDING_LOGO, DefaultBrandingLogo), + Favicon: getEnvOrDefaultString(ENV_BRANDING_FAVICON, DefaultBrandingFavicon), + PrimaryColor: getEnvOrDefaultString(ENV_BRANDING_PRIMARY_COLOR, DefaultBrandingPrimaryColor), + SecondaryColor: getEnvOrDefaultString(ENV_BRANDING_SECONDARY_COLOR, DefaultBrandingSecondaryColor), + AccentColor: getEnvOrDefaultString(ENV_BRANDING_ACCENT_COLOR, DefaultBrandingAccentColor), + CompanyName: getEnvOrDefaultString(ENV_BRANDING_COMPANY_NAME, ""), + CompanyUrl: getEnvOrDefaultString(ENV_BRANDING_COMPANY_URL, ""), + } +} diff --git a/src/environment/environment_settings.go b/src/environment/environment_settings.go index c079c690..d91725e8 100644 --- a/src/environment/environment_settings.go +++ b/src/environment/environment_settings.go @@ -26,11 +26,30 @@ type EnvironmentSettings struct { General GeneralSettings RabbitMQ RabbitMQSettings MCP MCPSettings + Branding BrandingSettings } // Settings is the global singleton instance for accessing all environment configurations. var Settings EnvironmentSettings +// expandEnvVariables expands environment variable references like ${VAR} or $VAR in all environment variables +func expandEnvVariables() { + for _, env := range os.Environ() { + parts := strings.SplitN(env, "=", 2) + if len(parts) != 2 { + continue + } + key := parts[0] + value := parts[1] + + // Expand ${VAR} and $VAR references + expanded := os.ExpandEnv(value) + if expanded != value { + os.Setenv(key, expanded) + } + } +} + // Initialize the global environment manager func init() { logentry := logrus.NewEntry(logrus.StandardLogger()).WithField("package", "environment") @@ -44,6 +63,9 @@ func init() { logentry.Println("Successfully loaded .env file") } + // Expand variable references like ${VAR} after loading .env + expandEnvVariables() + Settings = EnvironmentSettings{ Database: NewDatabaseSettings(), API: NewAPISettings(), @@ -57,6 +79,7 @@ func init() { General: NewGeneralSettings(), RabbitMQ: NewRabbitMQSettings(), MCP: NewMCPSettings(), + Branding: NewBrandingSettings(), } logentry.Println("Environment Manager ready - All configurations loaded!") diff --git a/src/environment/form_settings.go b/src/environment/form_settings.go index e1e25030..cda10e50 100644 --- a/src/environment/form_settings.go +++ b/src/environment/form_settings.go @@ -2,20 +2,23 @@ package environment // Form environment variable names const ( - ENV_FORM = "FORM" // enable/disable form interface - ENV_FORM_PREFIX = "FORM_PREFIX" // form endpoint path prefix (default: "form") + ENV_FORM = "FORM" // enable/disable form interface + ENV_FORM_PREFIX = "FORM_PREFIX" // form endpoint path prefix (default: "form") + ENV_SERVERS_VIEW_MODE = "SERVERS_VIEW_MODE" // servers list view mode: "card" or "table" (default: "card") ) // FormSettings holds all Form configuration loaded from environment type FormSettings struct { - Enabled bool `json:"enabled"` - Prefix string `json:"prefix"` + Enabled bool `json:"enabled"` + Prefix string `json:"prefix"` + ServersViewMode string `json:"serversViewMode"` // "card" or "table" } // NewFormSettings creates a new Form settings by loading all values from environment func NewFormSettings() FormSettings { return FormSettings{ - Enabled: getEnvOrDefaultBool(ENV_FORM, true), - Prefix: getEnvOrDefaultString(ENV_FORM_PREFIX, "form"), + Enabled: getEnvOrDefaultBool(ENV_FORM, true), + Prefix: getEnvOrDefaultString(ENV_FORM_PREFIX, "form"), + ServersViewMode: getEnvOrDefaultString(ENV_SERVERS_VIEW_MODE, "card"), } } diff --git a/src/environment/general_settings.go b/src/environment/general_settings.go index b4806181..d08d1127 100644 --- a/src/environment/general_settings.go +++ b/src/environment/general_settings.go @@ -17,6 +17,16 @@ const ( ENV_TESTING = "TESTING" // testing mode ENV_LOGLEVEL = "LOGLEVEL" // general log level ENV_CONVERT_PNG_TO_JPG = "CONVERT_PNG_TO_JPG" // convert PNG to JPG (not implemented yet) + + // Login customization + ENV_LOGIN_LOGO = "LOGIN_LOGO" // URL for login page logo/icon + ENV_LOGIN_SUBTITLE = "LOGIN_SUBTITLE" // subtitle under logo + ENV_LOGIN_WARNING = "LOGIN_WARNING" // prominent warning text on login + ENV_LOGIN_FOOTER = "LOGIN_FOOTER" // footer text on login + ENV_LOGIN_LAYOUT = "LOGIN_LAYOUT" // layout type: center|split|simple + ENV_LOGIN_CUSTOM_CSS = "LOGIN_CUSTOM_CSS" // URL to custom CSS for login page + ENV_LOGIN_FONT_AWESOME = "LOGIN_FONT_AWESOME" // URL to Font Awesome CSS + ENV_LOGIN_GOOGLE_FONTS = "LOGIN_GOOGLE_FONTS" // URL to Google Fonts stylesheet ) // GeneralConfig holds all general application configuration loaded from environment @@ -34,6 +44,16 @@ type GeneralSettings struct { Testing bool `json:"testing"` LogLevel string `json:"log_level"` ConvertPNGToJPG bool `json:"convert_png_to_jpg"` + + // Login customization + LoginLogo string `json:"login_logo"` + LoginSubtitle string `json:"login_subtitle"` + LoginWarning string `json:"login_warning"` + LoginFooter string `json:"login_footer"` + LoginLayout string `json:"login_layout"` // center|split|simple + LoginCustomCSS string `json:"login_custom_css"` + LoginFontAwesome string `json:"login_font_awesome"` + LoginGoogleFonts string `json:"login_google_fonts"` } // NewGeneralSettings creates a new general settings by loading all values from environment @@ -52,6 +72,15 @@ func NewGeneralSettings() GeneralSettings { Testing: getEnvOrDefaultBool(ENV_TESTING, false), LogLevel: getEnvOrDefaultString(ENV_LOGLEVEL, ""), ConvertPNGToJPG: getEnvOrDefaultBool(ENV_CONVERT_PNG_TO_JPG, false), + // Login customization + LoginLogo: getEnvOrDefaultString(ENV_LOGIN_LOGO, ""), + LoginSubtitle: getEnvOrDefaultString(ENV_LOGIN_SUBTITLE, ""), + LoginWarning: getEnvOrDefaultString(ENV_LOGIN_WARNING, ""), + LoginFooter: getEnvOrDefaultString(ENV_LOGIN_FOOTER, ""), + LoginLayout: getEnvOrDefaultString(ENV_LOGIN_LAYOUT, "center"), + LoginCustomCSS: getEnvOrDefaultString(ENV_LOGIN_CUSTOM_CSS, ""), + LoginFontAwesome: getEnvOrDefaultString(ENV_LOGIN_FONT_AWESOME, ""), + LoginGoogleFonts: getEnvOrDefaultString(ENV_LOGIN_GOOGLE_FONTS, ""), } } diff --git a/src/form/form.go b/src/form/form.go index 1369b29f..c7e1adb9 100644 --- a/src/form/form.go +++ b/src/form/form.go @@ -45,8 +45,10 @@ func Configure(r chi.Router) { func ServeForms(r chi.Router) { - // Static Forms content - ServeStaticContent(r) + // Static Forms content (skip in dev frontend mode - SPA proxy handles assets) + if v := os.Getenv("QUEPASA_DEV_FRONTEND"); v != "1" && v != "true" { + ServeStaticContent(r) + } // setting group r.Group(func(r chi.Router) { diff --git a/src/form/form_handlers.go b/src/form/form_handlers.go index 41a826cd..e8067124 100644 --- a/src/form/form_handlers.go +++ b/src/form/form_handlers.go @@ -12,7 +12,6 @@ import ( api "github.com/nocodeleaks/quepasa/api" environment "github.com/nocodeleaks/quepasa/environment" models "github.com/nocodeleaks/quepasa/models" - log "github.com/sirupsen/logrus" ) var FormLoginEndpoint string = "/login" @@ -22,14 +21,21 @@ var FormDownloadEndpoint string = "/download" func RegisterFormControllers(r chi.Router) { - r.Get("/", IndexHandler) - r.Get(FormLoginEndpoint, LoginFormHandler) + // The SPA replaces server rendered pages. Redirect page GETs to the SPA root + r.Get(FormLoginEndpoint, func(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, "/", http.StatusFound) + }) + // Keep POST /login for API login; LoginHandler will return JSON and set cookie r.Post(FormLoginEndpoint, LoginHandler) r.Get(FormLogoutEndpoint, LogoutHandler) + // Public JSON for login page customization + r.Get(FormEndpointPrefix+"/login/json", FormLoginJSONController) // disable /setup if environment is false if environment.Settings.General.AccountSetup { - r.Get(FormSetupEndpoint, SetupFormHandler) + r.Get(FormSetupEndpoint, func(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, "/", http.StatusFound) + }) r.Post(FormSetupEndpoint, SetupHandler) } } @@ -78,7 +84,9 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) { HttpOnly: true, } - log.Debugf("setting cookie and redirecting to: %v", FormAccountEndpoint) http.SetCookie(w, cookie) - http.Redirect(w, r, FormAccountEndpoint, http.StatusFound) + + // For SPA clients, return a JSON success so frontend can proceed without expecting a redirect + resp := map[string]string{"result": "success"} + api.RespondSuccess(w, resp) } diff --git a/src/form/form_json_handlers.go b/src/form/form_json_handlers.go new file mode 100644 index 00000000..a1048e17 --- /dev/null +++ b/src/form/form_json_handlers.go @@ -0,0 +1,28 @@ +package form + +import ( + "net/http" + + api "github.com/nocodeleaks/quepasa/api" + environment "github.com/nocodeleaks/quepasa/environment" + models "github.com/nocodeleaks/quepasa/models" +) + +// FormLoginJSONController returns login page customization for form clients. +func FormLoginJSONController(w http.ResponseWriter, r *http.Request) { + resp := map[string]interface{}{ + "appTitle": environment.Settings.General.AppTitle, + "loginLogo": environment.Settings.General.LoginLogo, + "loginSubtitle": environment.Settings.General.LoginSubtitle, + "loginWarning": environment.Settings.General.LoginWarning, + "loginFooter": environment.Settings.General.LoginFooter, + "loginLayout": environment.Settings.General.LoginLayout, + "customCss": environment.Settings.General.LoginCustomCSS, + "fontAwesome": environment.Settings.General.LoginFontAwesome, + "googleFonts": environment.Settings.General.LoginGoogleFonts, + "accountSetup": environment.Settings.General.AccountSetup, + "version": models.QpVersion, + } + + api.RespondSuccess(w, resp) +} diff --git a/src/frontend/.gitignore b/src/frontend/.gitignore new file mode 100644 index 00000000..c51df8f0 --- /dev/null +++ b/src/frontend/.gitignore @@ -0,0 +1,36 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# Dependencies +node_modules + +# Build output +dist +dist-ssr + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Local environment +*.local + +# TypeScript +*.tsbuildinfo + +# Go artifacts (should not be in frontend) +bin/ +pkg/ diff --git a/src/frontend/README.md b/src/frontend/README.md new file mode 100644 index 00000000..f3e78e3f --- /dev/null +++ b/src/frontend/README.md @@ -0,0 +1,32 @@ +Vue 3 frontend for QuePasa + +Setup: + cd src/frontend + npm install + npm run dev + +Build: + npm run build # outputs to src/assets/frontend + +Dev notes: + - Vite dev server proxies /api and /form to backend (including websocket upgrades for /form/verify/ws). Configure backend with environment vars: + +- VITE_BACKEND_URL (ex: http://localhost:32000) OR +- VITE_BACKEND_PORT (ex: 32000) — fallback to env WEBAPIPORT or 32000 +- VITE_DEV_PORT (optional) — vite dev port (default 5173) + +Examples: + VITE_BACKEND_PORT=32000 npm run dev + VITE_BACKEND_URL=http://backend.local:32000 npm run dev + - API client is in src/services/api.ts + - WebSocket service is in src/services/ws.ts + +Dev helpers: + Use project scripts to run backend + frontend together (from project root): + + ./scripts/start-dev.sh # builds backend and starts backend + vite + ./scripts/stop-dev.sh # stop both services + +Or let the Go binary spawn the frontend automatically by setting: + + QUEPASA_DEV_FRONTEND=1 ./src/.dist/quepasa diff --git a/src/frontend/index.html b/src/frontend/index.html new file mode 100644 index 00000000..bcacf0f3 --- /dev/null +++ b/src/frontend/index.html @@ -0,0 +1,14 @@ + + + + + + QuePasa Frontend + + + + +
+ + + diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json new file mode 100644 index 00000000..070392b5 --- /dev/null +++ b/src/frontend/package-lock.json @@ -0,0 +1,1854 @@ +{ + "name": "quepasa-frontend", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "quepasa-frontend", + "version": "0.1.0", + "dependencies": { + "@microsoft/signalr": "^10.0.0", + "axios": "^1.4.0", + "bootstrap": "^5.3.0", + "pinia": "^3.0.4", + "vue": "^3.3.4", + "vue-router": "^4.4.0" + }, + "devDependencies": { + "@types/node": "^25.0.3", + "@vitejs/plugin-vue": "^4.2.2", + "typescript": "^5.4.0", + "vite": "^5.2.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@microsoft/signalr": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-10.0.0.tgz", + "integrity": "sha512-0BRqz/uCx3JdrOqiqgFhih/+hfTERaUfCZXFB52uMaZJrKaPRzHzMuqVsJC/V3pt7NozcNXGspjKiQEK+X7P2w==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "eventsource": "^2.0.2", + "fetch-cookie": "^2.0.3", + "node-fetch": "^2.6.7", + "ws": "^7.5.10" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.54.0.tgz", + "integrity": "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.54.0.tgz", + "integrity": "sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.54.0.tgz", + "integrity": "sha512-k43D4qta/+6Fq+nCDhhv9yP2HdeKeP56QrUUTW7E6PhZP1US6NDqpJj4MY0jBHlJivVJD5P8NxrjuobZBJTCRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.54.0.tgz", + "integrity": "sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.54.0.tgz", + "integrity": "sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.54.0.tgz", + "integrity": "sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.54.0.tgz", + "integrity": "sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.54.0.tgz", + "integrity": "sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.54.0.tgz", + "integrity": "sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.54.0.tgz", + "integrity": "sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.54.0.tgz", + "integrity": "sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.54.0.tgz", + "integrity": "sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.54.0.tgz", + "integrity": "sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.54.0.tgz", + "integrity": "sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.54.0.tgz", + "integrity": "sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.54.0.tgz", + "integrity": "sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.54.0.tgz", + "integrity": "sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.54.0.tgz", + "integrity": "sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.54.0.tgz", + "integrity": "sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.54.0.tgz", + "integrity": "sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.54.0.tgz", + "integrity": "sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.54.0.tgz", + "integrity": "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz", + "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz", + "integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0 || ^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.26.tgz", + "integrity": "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.26", + "entities": "^7.0.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz", + "integrity": "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.26", + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz", + "integrity": "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.26", + "@vue/compiler-dom": "3.5.26", + "@vue/compiler-ssr": "3.5.26", + "@vue/shared": "3.5.26", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz", + "integrity": "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.26", + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.26.tgz", + "integrity": "sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.26.tgz", + "integrity": "sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.26", + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.26.tgz", + "integrity": "sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.26", + "@vue/runtime-core": "3.5.26", + "@vue/shared": "3.5.26", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.26.tgz", + "integrity": "sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.26", + "@vue/shared": "3.5.26" + }, + "peerDependencies": { + "vue": "3.5.26" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz", + "integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==", + "license": "MIT" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/bootstrap": { + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz", + "integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/entities": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.0.tgz", + "integrity": "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fetch-cookie": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-2.2.0.tgz", + "integrity": "sha512-h9AgfjURuCgA2+2ISl8GbavpUdR+WGAM2McW/ovn4tVccegp8ZqCKWSBR8uRdM8dDNlx5WdKRWxBYUwteLDCNQ==", + "license": "Unlicense", + "dependencies": { + "set-cookie-parser": "^2.4.8", + "tough-cookie": "^4.0.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/pinia": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.7.7" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.5.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.54.0.tgz", + "integrity": "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.54.0", + "@rollup/rollup-android-arm64": "4.54.0", + "@rollup/rollup-darwin-arm64": "4.54.0", + "@rollup/rollup-darwin-x64": "4.54.0", + "@rollup/rollup-freebsd-arm64": "4.54.0", + "@rollup/rollup-freebsd-x64": "4.54.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", + "@rollup/rollup-linux-arm-musleabihf": "4.54.0", + "@rollup/rollup-linux-arm64-gnu": "4.54.0", + "@rollup/rollup-linux-arm64-musl": "4.54.0", + "@rollup/rollup-linux-loong64-gnu": "4.54.0", + "@rollup/rollup-linux-ppc64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-musl": "4.54.0", + "@rollup/rollup-linux-s390x-gnu": "4.54.0", + "@rollup/rollup-linux-x64-gnu": "4.54.0", + "@rollup/rollup-linux-x64-musl": "4.54.0", + "@rollup/rollup-openharmony-arm64": "4.54.0", + "@rollup/rollup-win32-arm64-msvc": "4.54.0", + "@rollup/rollup-win32-ia32-msvc": "4.54.0", + "@rollup/rollup-win32-x64-gnu": "4.54.0", + "@rollup/rollup-win32-x64-msvc": "4.54.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.26.tgz", + "integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.26", + "@vue/compiler-sfc": "3.5.26", + "@vue/runtime-dom": "3.5.26", + "@vue/server-renderer": "3.5.26", + "@vue/shared": "3.5.26" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/src/frontend/package.json b/src/frontend/package.json new file mode 100644 index 00000000..c7f90e63 --- /dev/null +++ b/src/frontend/package.json @@ -0,0 +1,25 @@ +{ + "name": "quepasa-frontend", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "vite", + "build": "vite build", + "watch": "vite build --watch", + "preview": "vite preview --port 5173" + }, + "dependencies": { + "@microsoft/signalr": "^10.0.0", + "axios": "^1.4.0", + "bootstrap": "^5.3.0", + "pinia": "^3.0.4", + "vue": "^3.3.4", + "vue-router": "^4.4.0" + }, + "devDependencies": { + "@types/node": "^25.0.3", + "@vitejs/plugin-vue": "^4.2.2", + "typescript": "^5.4.0", + "vite": "^5.2.0" + } +} diff --git a/src/frontend/src/App.bak b/src/frontend/src/App.bak new file mode 100644 index 00000000..16356e47 --- /dev/null +++ b/src/frontend/src/App.bak @@ -0,0 +1,80 @@ + + + diff --git a/src/frontend/src/App.vue b/src/frontend/src/App.vue new file mode 100644 index 00000000..a022065d --- /dev/null +++ b/src/frontend/src/App.vue @@ -0,0 +1,353 @@ + + + + + diff --git a/src/frontend/src/components/ConfirmModal.vue b/src/frontend/src/components/ConfirmModal.vue new file mode 100644 index 00000000..5f87108b --- /dev/null +++ b/src/frontend/src/components/ConfirmModal.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/frontend/src/components/Toaster.vue b/src/frontend/src/components/Toaster.vue new file mode 100644 index 00000000..94571ec2 --- /dev/null +++ b/src/frontend/src/components/Toaster.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/src/frontend/src/components/TriStateToggle.vue b/src/frontend/src/components/TriStateToggle.vue new file mode 100644 index 00000000..45293658 --- /dev/null +++ b/src/frontend/src/components/TriStateToggle.vue @@ -0,0 +1,133 @@ + + + + + diff --git a/src/frontend/src/main.ts b/src/frontend/src/main.ts new file mode 100644 index 00000000..addf32dc --- /dev/null +++ b/src/frontend/src/main.ts @@ -0,0 +1,8 @@ +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' +import 'bootstrap/dist/css/bootstrap.min.css' +import 'bootstrap/dist/js/bootstrap.bundle.min.js' +import './styles.css' + +createApp(App).use(router).mount('#app') diff --git a/src/frontend/src/pages/Account.vue b/src/frontend/src/pages/Account.vue new file mode 100644 index 00000000..bdde7efe --- /dev/null +++ b/src/frontend/src/pages/Account.vue @@ -0,0 +1,465 @@ + + + + + diff --git a/src/frontend/src/pages/Connect.vue b/src/frontend/src/pages/Connect.vue new file mode 100644 index 00000000..06cc9d24 --- /dev/null +++ b/src/frontend/src/pages/Connect.vue @@ -0,0 +1,338 @@ + + + + + diff --git a/src/frontend/src/pages/Environment.vue b/src/frontend/src/pages/Environment.vue new file mode 100644 index 00000000..8b07210f --- /dev/null +++ b/src/frontend/src/pages/Environment.vue @@ -0,0 +1,185 @@ + + + + + diff --git a/src/frontend/src/pages/GroupDetail.vue b/src/frontend/src/pages/GroupDetail.vue new file mode 100644 index 00000000..766e0699 --- /dev/null +++ b/src/frontend/src/pages/GroupDetail.vue @@ -0,0 +1,1054 @@ + + + + + diff --git a/src/frontend/src/pages/Groups.vue b/src/frontend/src/pages/Groups.vue new file mode 100644 index 00000000..0a0c1a87 --- /dev/null +++ b/src/frontend/src/pages/Groups.vue @@ -0,0 +1,971 @@ + + + + + diff --git a/src/frontend/src/pages/Home.vue b/src/frontend/src/pages/Home.vue new file mode 100644 index 00000000..ebbc7293 --- /dev/null +++ b/src/frontend/src/pages/Home.vue @@ -0,0 +1,1802 @@ + + + + + diff --git a/src/frontend/src/pages/Login.vue b/src/frontend/src/pages/Login.vue new file mode 100644 index 00000000..e7cd5f9e --- /dev/null +++ b/src/frontend/src/pages/Login.vue @@ -0,0 +1,561 @@ + + + + + diff --git a/src/frontend/src/pages/Messages.vue b/src/frontend/src/pages/Messages.vue new file mode 100644 index 00000000..d8cffac7 --- /dev/null +++ b/src/frontend/src/pages/Messages.vue @@ -0,0 +1,1593 @@ + + + + + diff --git a/src/frontend/src/pages/PairCode.vue b/src/frontend/src/pages/PairCode.vue new file mode 100644 index 00000000..e2eb0abe --- /dev/null +++ b/src/frontend/src/pages/PairCode.vue @@ -0,0 +1,680 @@ + + + + + diff --git a/src/frontend/src/pages/QRCode.vue b/src/frontend/src/pages/QRCode.vue new file mode 100644 index 00000000..26b25ac1 --- /dev/null +++ b/src/frontend/src/pages/QRCode.vue @@ -0,0 +1,381 @@ + + + + + diff --git a/src/frontend/src/pages/RabbitMQ.vue b/src/frontend/src/pages/RabbitMQ.vue new file mode 100644 index 00000000..5d18b252 --- /dev/null +++ b/src/frontend/src/pages/RabbitMQ.vue @@ -0,0 +1,740 @@ + + + + + diff --git a/src/frontend/src/pages/SendMessage.vue b/src/frontend/src/pages/SendMessage.vue new file mode 100644 index 00000000..97237471 --- /dev/null +++ b/src/frontend/src/pages/SendMessage.vue @@ -0,0 +1,1355 @@ + + + + + diff --git a/src/frontend/src/pages/Server.vue b/src/frontend/src/pages/Server.vue new file mode 100644 index 00000000..eafc5456 --- /dev/null +++ b/src/frontend/src/pages/Server.vue @@ -0,0 +1,1240 @@ + + + + + diff --git a/src/frontend/src/pages/Setup.vue b/src/frontend/src/pages/Setup.vue new file mode 100644 index 00000000..a38df2a6 --- /dev/null +++ b/src/frontend/src/pages/Setup.vue @@ -0,0 +1,472 @@ + + + + + diff --git a/src/frontend/src/pages/UserCreate.vue b/src/frontend/src/pages/UserCreate.vue new file mode 100644 index 00000000..cd6013d3 --- /dev/null +++ b/src/frontend/src/pages/UserCreate.vue @@ -0,0 +1,398 @@ + + + + + diff --git a/src/frontend/src/pages/Users.vue b/src/frontend/src/pages/Users.vue new file mode 100644 index 00000000..11883383 --- /dev/null +++ b/src/frontend/src/pages/Users.vue @@ -0,0 +1,495 @@ + + + + + diff --git a/src/frontend/src/pages/Webhooks.vue b/src/frontend/src/pages/Webhooks.vue new file mode 100644 index 00000000..e6705d33 --- /dev/null +++ b/src/frontend/src/pages/Webhooks.vue @@ -0,0 +1,1184 @@ + + + + + diff --git a/src/frontend/src/router.ts b/src/frontend/src/router.ts new file mode 100644 index 00000000..52edd6f1 --- /dev/null +++ b/src/frontend/src/router.ts @@ -0,0 +1,60 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomePage from '@/pages/Home.vue' +import AccountPage from '@/pages/Account.vue' +import LoginPage from '@/pages/Login.vue' +import WebhooksPage from '@/pages/Webhooks.vue' +import RabbitMQPage from '@/pages/RabbitMQ.vue' +import ServerPage from '@/pages/Server.vue' +import SetupPage from '@/pages/Setup.vue' +import ConnectPage from '@/pages/Connect.vue' +import UsersPage from '@/pages/Users.vue' +import UserCreatePage from '@/pages/UserCreate.vue' +import EnvironmentPage from '@/pages/Environment.vue' +import QRCodePage from '@/pages/QRCode.vue' +import PairCodePage from '@/pages/PairCode.vue' +import MessagesPage from '@/pages/Messages.vue' +import SendMessagePage from '@/pages/SendMessage.vue' +import { useSessionStore } from '@/stores/session' + +const router = createRouter({ + history: createWebHistory(), + routes: [ + { path: '/', name: 'home', component: HomePage, meta: { requiresAuth: true } }, + { path: '/account', name: 'account', component: AccountPage, meta: { requiresAuth: true } }, + { path: '/webhooks', name: 'webhooks', component: WebhooksPage, meta: { requiresAuth: true } }, + { path: '/dispatching', name: 'dispatching', component: WebhooksPage, meta: { requiresAuth: true } }, + { path: '/rabbitmq', name: 'rabbitmq', component: RabbitMQPage, meta: { requiresAuth: true } }, + { path: '/connect', name: 'connect', component: ConnectPage, meta: { requiresAuth: true } }, + { path: '/server/:token', name: 'server', component: ServerPage, meta: { requiresAuth: true } }, + { path: '/server/:token/qrcode', name: 'server.qrcode', component: QRCodePage, meta: { requiresAuth: true } }, + { path: '/server/:token/paircode', name: 'server.paircode', component: PairCodePage, meta: { requiresAuth: true } }, + { path: '/server/:token/messages', name: 'server.messages', component: MessagesPage, meta: { requiresAuth: true } }, + { path: '/server/:token/send', name: 'server.send', component: SendMessagePage, meta: { requiresAuth: true } }, + { path: '/server/:token/groups', name: 'server.groups', component: () => import('@/pages/Groups.vue'), meta: { requiresAuth: true } }, + { path: '/server/:token/groups/:id', name: 'server.groups.detail', component: () => import('@/pages/GroupDetail.vue'), meta: { requiresAuth: true } }, + { path: '/setup', name: 'setup', component: SetupPage, meta: { requiresAuth: true } }, + { path: '/users', name: 'users', component: UsersPage, meta: { requiresAuth: true } }, + { path: '/users/create', name: 'users.create', component: UserCreatePage, meta: { requiresAuth: true } }, + { path: '/environment', name: 'environment', component: EnvironmentPage, meta: { requiresAuth: true } }, + { path: '/login', name: 'login', component: LoginPage }, + ], +}) + +router.beforeEach(async (to) => { + const session = useSessionStore() + if (session.loading.value) { + await session.loadSession() + } + + if (to.meta.requiresAuth && !session.user.value) { + return { name: 'login', query: { redirect: to.fullPath } } + } + + if (to.name === 'login' && session.user.value) { + return { name: 'home' } + } + + return true +}) + +export default router diff --git a/src/frontend/src/services/api.ts b/src/frontend/src/services/api.ts new file mode 100644 index 00000000..6950cb2e --- /dev/null +++ b/src/frontend/src/services/api.ts @@ -0,0 +1,9 @@ +import axios from 'axios' + +const api = axios.create({ + baseURL: '/', + withCredentials: true, + headers: { 'Accept': 'application/json' } +}) + +export default api diff --git a/src/frontend/src/services/signalr.ts b/src/frontend/src/services/signalr.ts new file mode 100644 index 00000000..99357816 --- /dev/null +++ b/src/frontend/src/services/signalr.ts @@ -0,0 +1,169 @@ +import * as signalR from '@microsoft/signalr' + +type MessageHandler = (message: any) => void + +class SignalRService { + private connection: signalR.HubConnection | null = null + private messageHandlers: MessageHandler[] = [] + private token: string = '' + private isConnecting: boolean = false + private reconnectAttempts: number = 0 + private maxReconnectAttempts: number = 5 + + /** + * Connect to SignalR hub for a specific server token + */ + async connect(serverToken: string): Promise { + if (this.isConnecting) { + console.log('SignalR: Already connecting...') + return + } + + // If already connected to the same token, do nothing + if (this.connection && this.token === serverToken && + this.connection.state === signalR.HubConnectionState.Connected) { + console.log('SignalR: Already connected to', serverToken) + return + } + + // Disconnect from previous connection if exists + await this.disconnect() + + this.isConnecting = true + this.token = serverToken + + try { + const url = `${window.location.origin}/signalr` + + this.connection = new signalR.HubConnectionBuilder() + .withUrl(url) + .withAutomaticReconnect({ + nextRetryDelayInMilliseconds: (retryContext) => { + // Exponential backoff: 1s, 2s, 4s, 8s, 16s + const delay = Math.min(1000 * Math.pow(2, retryContext.previousRetryCount), 16000) + return delay + } + }) + .configureLogging(signalR.LogLevel.Information) + .build() + + // Set up event handlers + this.connection.on('message', (payload: any) => { + console.log('SignalR: Received message', payload) + this.messageHandlers.forEach(handler => { + try { + handler(payload) + } catch (e) { + console.error('SignalR: Error in message handler', e) + } + }) + }) + + this.connection.onclose((error) => { + console.log('SignalR: Connection closed', error) + }) + + this.connection.onreconnecting((error) => { + console.log('SignalR: Reconnecting...', error) + }) + + this.connection.onreconnected((connectionId) => { + console.log('SignalR: Reconnected with ID:', connectionId) + // Re-register token after reconnection + this.registerToken() + }) + + // Start connection + await this.connection.start() + console.log('SignalR: Connected successfully') + + // Register the token with the hub + await this.registerToken() + + this.reconnectAttempts = 0 + } catch (error) { + console.error('SignalR: Connection error', error) + this.reconnectAttempts++ + + if (this.reconnectAttempts < this.maxReconnectAttempts) { + // Retry connection after delay + const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 16000) + console.log(`SignalR: Retrying in ${delay}ms...`) + setTimeout(() => this.connect(serverToken), delay) + } + } finally { + this.isConnecting = false + } + } + + /** + * Register the server token with the SignalR hub + */ + private async registerToken(): Promise { + if (this.connection && this.connection.state === signalR.HubConnectionState.Connected && this.token) { + try { + await this.connection.invoke('Token', this.token) + console.log('SignalR: Token registered:', this.token) + } catch (error) { + console.error('SignalR: Error registering token', error) + } + } + } + + /** + * Disconnect from SignalR hub + */ + async disconnect(): Promise { + if (this.connection) { + try { + await this.connection.stop() + console.log('SignalR: Disconnected') + } catch (error) { + console.error('SignalR: Error disconnecting', error) + } + this.connection = null + } + this.token = '' + this.reconnectAttempts = 0 + } + + /** + * Add a message handler + */ + onMessage(handler: MessageHandler): () => void { + this.messageHandlers.push(handler) + + // Return unsubscribe function + return () => { + const index = this.messageHandlers.indexOf(handler) + if (index > -1) { + this.messageHandlers.splice(index, 1) + } + } + } + + /** + * Remove all message handlers + */ + clearHandlers(): void { + this.messageHandlers = [] + } + + /** + * Check if connected + */ + isConnected(): boolean { + return this.connection?.state === signalR.HubConnectionState.Connected + } + + /** + * Get current connection state + */ + getState(): signalR.HubConnectionState | null { + return this.connection?.state ?? null + } +} + +// Singleton instance +const signalRService = new SignalRService() +export default signalRService diff --git a/src/frontend/src/services/toast.ts b/src/frontend/src/services/toast.ts new file mode 100644 index 00000000..b4c6eb25 --- /dev/null +++ b/src/frontend/src/services/toast.ts @@ -0,0 +1,25 @@ +import { reactive } from 'vue' + +export type Toast = { + id: number + type: 'success' | 'error' | 'info' + message: string +} + +const toasts = reactive([]) +let idCounter = 1 + +export function pushToast(message: string, type: 'success' | 'error' | 'info' = 'success', timeout = 4000) { + const id = idCounter++ + toasts.push({ id, type, message }) + setTimeout(() => { + const idx = toasts.findIndex((t) => t.id === id) + if (idx !== -1) toasts.splice(idx, 1) + }, timeout) +} + +export function useToasts() { + return toasts +} + +export default { pushToast, useToasts } diff --git a/src/frontend/src/services/ws.ts b/src/frontend/src/services/ws.ts new file mode 100644 index 00000000..50302686 --- /dev/null +++ b/src/frontend/src/services/ws.ts @@ -0,0 +1,45 @@ +type Handler = (payload: any) => void + +class WSService { + socket: WebSocket | null = null + handlers: Record = {} + + connect(path: string) { + if (this.socket) this.disconnect() + const url = (window.location.protocol === 'https:' ? 'wss:' : 'ws:') + '//' + window.location.host + path + this.socket = new WebSocket(url) + + this.socket.onopen = () => console.log('WS connected to', url) + this.socket.onmessage = (e) => { + try { + const data = JSON.parse(e.data) + this.emit('message', data) + } catch (err) { + this.emit('message', e.data) + } + } + + this.socket.onclose = () => console.log('WS closed') + this.socket.onerror = (e) => console.error('WS error', e) + } + + disconnect() { + if (this.socket) { + this.socket.close() + this.socket = null + } + } + + on(event: string, handler: Handler) { + if (!this.handlers[event]) this.handlers[event] = [] + this.handlers[event].push(handler) + } + + emit(event: string, payload: any) { + const hs = this.handlers[event] || [] + hs.forEach(h => h(payload)) + } +} + +const instance = new WSService() +export default instance diff --git a/src/frontend/src/stores/session.ts b/src/frontend/src/stores/session.ts new file mode 100644 index 00000000..95f9a7c4 --- /dev/null +++ b/src/frontend/src/stores/session.ts @@ -0,0 +1,32 @@ +import { ref } from 'vue' +import api from '@/services/api' + +const user = ref(null) +const version = ref('') +const loading = ref(true) +const error = ref('') + +async function loadSession() { + try { + loading.value = true + error.value = '' + const res = await api.get('/api/session') + user.value = res.data.user + version.value = res.data.version + } catch (err: any) { + user.value = null + version.value = '' + error.value = err?.response?.data?.result || err.message || 'Session error' + } finally { + loading.value = false + } +} + +function clearSession() { + user.value = null + version.value = '' +} + +export function useSessionStore() { + return { user, version, loading, error, loadSession, clearSession } +} diff --git a/src/frontend/src/stores/toast.ts b/src/frontend/src/stores/toast.ts new file mode 100644 index 00000000..2027149d --- /dev/null +++ b/src/frontend/src/stores/toast.ts @@ -0,0 +1,38 @@ +import { ref } from 'vue' +import { defineStore } from 'pinia' + +export interface Toast { + id: number + message: string + type: 'success' | 'error' | 'info' | 'warning' + duration: number +} + +export const useToastStore = defineStore('toast', () => { + const toasts = ref([]) + let nextId = 1 + + function show(message: string, type: Toast['type'] = 'info', duration = 5000) { + const id = nextId++ + toasts.value.push({ id, message, type, duration }) + + if (duration > 0) { + setTimeout(() => remove(id), duration) + } + + return id + } + + function remove(id: number) { + const index = toasts.value.findIndex(t => t.id === id) + if (index > -1) { + toasts.value.splice(index, 1) + } + } + + function clear() { + toasts.value = [] + } + + return { toasts, show, remove, clear } +}) diff --git a/src/frontend/src/styles.css b/src/frontend/src/styles.css new file mode 100644 index 00000000..219f875e --- /dev/null +++ b/src/frontend/src/styles.css @@ -0,0 +1,15 @@ +:root{ + --primary-color: #00034B; +} + +body{ + background: #f8f9fa; +} + +.navbar.bg-primary{ + background: var(--primary-color) !important; +} + +.container{ + max-width: 1100px; +} diff --git a/src/frontend/tsconfig.json b/src/frontend/tsconfig.json new file mode 100644 index 00000000..85a26a11 --- /dev/null +++ b/src/frontend/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "Node", + "strict": true, + "jsx": "preserve", + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } + }, + "include": ["src"] +} diff --git a/src/frontend/vite.config.ts b/src/frontend/vite.config.ts new file mode 100644 index 00000000..0b535851 --- /dev/null +++ b/src/frontend/vite.config.ts @@ -0,0 +1,70 @@ +import { defineConfig, loadEnv } from 'vite' +import vue from '@vitejs/plugin-vue' +import path from 'path' +import { fileURLToPath } from 'url' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +// https://vitejs.dev/config/ +export default defineConfig(({ command, mode }) => { + // load .env variables for current mode + const env = loadEnv(mode, process.cwd(), '') + const backendUrl = env.VITE_BACKEND_URL || `http://127.0.0.1:${env.VITE_BACKEND_PORT || process.env.WEBAPIPORT || '32000'}` + + return { + plugins: [vue()], + base: command === 'serve' ? '/' : '/assets/frontend/', + server: { + port: Number(env.VITE_DEV_PORT || 5173), + proxy: { + '/api': { + target: backendUrl, + changeOrigin: true, + secure: false, + }, + '/form': { + target: backendUrl, + changeOrigin: true, + secure: false, + }, + '/login': { + target: backendUrl, + changeOrigin: true, + secure: false, + }, + '/logout': { + target: backendUrl, + changeOrigin: true, + secure: false, + }, + '/session': { + target: backendUrl, + changeOrigin: true, + secure: false, + } + } + }, + build: { + outDir: path.resolve(__dirname, '../assets/frontend'), + emptyOutDir: true, + rollupOptions: { + output: { + entryFileNames: 'assets/index.js', + chunkFileNames: (chunkInfo) => `assets/${chunkInfo.name.toLowerCase()}.js`, + assetFileNames: (assetInfo) => { + const name = assetInfo.name || 'asset' + const ext = name.substring(name.lastIndexOf('.')) + const baseName = name.substring(0, name.lastIndexOf('.')) + return `assets/${baseName.toLowerCase()}${ext}` + } + } + } + }, + resolve: { + alias: { + '@': path.resolve(__dirname, 'src') + } + } + } +}) diff --git a/src/models/qp_receive_response.go b/src/models/qp_receive_response.go index 56cdd7fc..43c4c69b 100644 --- a/src/models/qp_receive_response.go +++ b/src/models/qp_receive_response.go @@ -7,6 +7,9 @@ import ( type QpReceiveResponse struct { QpResponse Total uint64 `json:"total"` + Page int `json:"page,omitempty"` + Limit int `json:"limit,omitempty"` + TotalPages int `json:"total_pages,omitempty"` Messages []whatsapp.WhatsappMessage `json:"messages,omitempty"` Server *QpServer `json:"server,omitempty"` } diff --git a/src/models/qp_whatsapp_extensions.go b/src/models/qp_whatsapp_extensions.go index ebb619ea..c5ee697e 100644 --- a/src/models/qp_whatsapp_extensions.go +++ b/src/models/qp_whatsapp_extensions.go @@ -300,4 +300,20 @@ func ToggleCalls(source whatsapp.IWhatsappOptions) error { return source.Save(reason) } +func ToggleReadUpdate(source whatsapp.IWhatsappOptions) error { + options := source.GetOptions() + + switch options.ReadUpdate { + case whatsapp.UnSetBooleanType: + options.ReadUpdate = whatsapp.TrueBooleanType + case whatsapp.TrueBooleanType: + options.ReadUpdate = whatsapp.FalseBooleanType + default: + options.ReadUpdate = whatsapp.UnSetBooleanType + } + + reason := fmt.Sprintf("toggle read update: %s", options.ReadUpdate) + return source.Save(reason) +} + //#endregion diff --git a/src/models/sqlite_migration.go b/src/models/sqlite_migration.go new file mode 100644 index 00000000..4d4ac971 --- /dev/null +++ b/src/models/sqlite_migration.go @@ -0,0 +1,32 @@ +package models + +import ( + "os" + "path/filepath" + + environment "github.com/nocodeleaks/quepasa/environment" +) + +// CheckLocalSqliteExists checks if a local sqlite db file exists for the configured database name. +// It returns the filename (relative path) and true when exists, otherwise empty string and false. +func CheckLocalSqliteExists() (string, bool) { + params := environment.Settings.Database.GetDBParameters() + dbName := params.DataBase + if dbName == "" { + dbName = "quepasa" + } + + c1 := dbName + ".db" + c2 := dbName + ".sqlite" + + if _, err := os.Stat(c1); err == nil { + p, _ := filepath.Abs(c1) + return p, true + } + if _, err := os.Stat(c2); err == nil { + p, _ := filepath.Abs(c2) + return p, true + } + + return "", false +} diff --git a/src/swagger/docs.go b/src/swagger/docs.go index 80c3f641..10d4ed1b 100644 --- a/src/swagger/docs.go +++ b/src/swagger/docs.go @@ -75,6 +75,91 @@ const docTemplate = `{ } } }, + "/api/server/{token}/messages": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Retrieves messages from WhatsApp server with pagination, timestamp and exceptions filtering (authenticated SPA endpoint)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SPA" + ], + "summary": "Get server messages (SPA)", + "parameters": [ + { + "type": "string", + "description": "Server token", + "name": "token", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Timestamp filter for messages (Unix timestamp)", + "name": "timestamp", + "in": "query" + }, + { + "type": "string", + "description": "Filter by exceptions: 'true' for messages with errors, 'false' for messages without errors, omit for all", + "name": "exceptions", + "in": "query" + }, + { + "type": "integer", + "description": "Page number (default: 1)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "Messages per page (default: 50, max: 500)", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.QpReceiveResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "503": { + "description": "Service Unavailable", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + } + } + } + }, "/chat/archive": { "post": { "security": [ @@ -274,13 +359,13 @@ const docTemplate = `{ } }, "/command": { - "get": { + "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "Execute control commands for the bot server (start, stop, restart)", + "description": "Execute control commands for the bot server (start, stop, restart) or toggle settings (groups, broadcasts, readreceipts, readupdate, calls, debug)", "consumes": [ "application/json" ], @@ -293,16 +378,21 @@ const docTemplate = `{ "summary": "Execute bot commands", "parameters": [ { - "enum": [ - "start", - "stop", - "restart" - ], - "type": "string", - "description": "Command action", - "name": "action", - "in": "query", - "required": true + "description": "Command request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "token": { + "type": "string" + } + } + } } ], "responses": { @@ -317,6 +407,12 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/models.QpResponse" } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } } } } @@ -1770,7 +1866,7 @@ const docTemplate = `{ "ApiKeyAuth": [] } ], - "description": "Retrieves pending messages from WhatsApp with optional timestamp filtering and exceptions error filtering", + "description": "Retrieves pending messages from WhatsApp with optional cache filters", "consumes": [ "application/json" ], @@ -1793,6 +1889,54 @@ const docTemplate = `{ "description": "Filter by exceptions error status: 'true' for messages with exceptions errors, 'false' for messages without exceptions errors, omit for all messages", "name": "exceptions", "in": "query" + }, + { + "type": "string", + "description": "Filter by message type (supports comma-separated list)", + "name": "type", + "in": "query" + }, + { + "type": "string", + "description": "Filter by category: sent, received, sync, unhandled, events", + "name": "category", + "in": "query" + }, + { + "type": "string", + "description": "Search text in id, chat, text, trackid, participant and exceptions", + "name": "search", + "in": "query" + }, + { + "type": "string", + "description": "Filter by fromme boolean: true or false", + "name": "fromme", + "in": "query" + }, + { + "type": "string", + "description": "Filter by fromhistory boolean: true or false", + "name": "fromhistory", + "in": "query" + }, + { + "type": "string", + "description": "Filter by chat id (contains)", + "name": "chatid", + "in": "query" + }, + { + "type": "string", + "description": "Filter by message id (contains)", + "name": "messageid", + "in": "query" + }, + { + "type": "string", + "description": "Filter by track id (contains)", + "name": "trackid", + "in": "query" } ], "responses": { @@ -2066,6 +2210,184 @@ const docTemplate = `{ } } }, + "/server/{token}/disable": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Stops the WhatsApp server instance identified by {token}. Sends feedback to the caller on success.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SPA" + ], + "summary": "Disable a server (SPA)", + "parameters": [ + { + "type": "string", + "description": "Server token", + "name": "token", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + } + } + } + }, + "/server/{token}/enable": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Starts the WhatsApp server instance identified by {token}. Sends a system message to notify connected listeners.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SPA" + ], + "summary": "Enable a server (SPA)", + "parameters": [ + { + "type": "string", + "description": "Server token", + "name": "token", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + } + } + } + }, + "/server/{token}/messages/{messageid}/history/download": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Given a ProtocolMessage history-sync event message id, attempts to download and decrypt the referenced media using the active Whatsmeow connection, attaches it to the message and triggers an update so the UI and dispatchers are notified.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SPA" + ], + "summary": "Download history-sync media", + "parameters": [ + { + "type": "string", + "description": "Server token", + "name": "token", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Message id (protocol message)", + "name": "messageid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "503": { + "description": "Service Unavailable", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + } + } + } + }, "/spam": { "post": { "security": [ @@ -2667,6 +2989,10 @@ const docTemplate = `{ "master_key": { "type": "string" }, + "password": { + "description": "default password for database seeding", + "type": "string" + }, "prefix": { "type": "string" }, @@ -2680,12 +3006,45 @@ const docTemplate = `{ "use_ssl_websocket": { "type": "boolean" }, + "user": { + "description": "default user for database seeding", + "type": "string" + }, "webhook_timeout": { "description": "webhook timeout in milliseconds", "type": "integer" } } }, + "environment.BrandingSettings": { + "type": "object", + "properties": { + "accentColor": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "companyUrl": { + "type": "string" + }, + "favicon": { + "type": "string" + }, + "logo": { + "type": "string" + }, + "primaryColor": { + "type": "string" + }, + "secondaryColor": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, "environment.DashboardSettings": { "type": "object", "properties": { @@ -2729,6 +3088,9 @@ const docTemplate = `{ "api": { "$ref": "#/definitions/environment.APISettings" }, + "branding": { + "$ref": "#/definitions/environment.BrandingSettings" + }, "database": { "description": "Embedded structs for organized access to different environment categories", "allOf": [ @@ -2799,6 +3161,9 @@ const docTemplate = `{ "read_update": { "type": "string" }, + "retry_message_store": { + "type": "string" + }, "wakeup_duration": { "type": "string" }, @@ -2815,6 +3180,10 @@ const docTemplate = `{ }, "prefix": { "type": "string" + }, + "serversViewMode": { + "description": "\"card\" or \"table\"", + "type": "string" } } }, @@ -2842,9 +3211,38 @@ const docTemplate = `{ "convert_wave_to_ogg": { "type": "boolean" }, + "force_audio_as_ptt": { + "type": "boolean" + }, "log_level": { "type": "string" }, + "login_custom_css": { + "type": "string" + }, + "login_font_awesome": { + "type": "string" + }, + "login_footer": { + "type": "string" + }, + "login_google_fonts": { + "type": "string" + }, + "login_layout": { + "description": "center|split|simple", + "type": "string" + }, + "login_logo": { + "description": "Login customization", + "type": "string" + }, + "login_subtitle": { + "type": "string" + }, + "login_warning": { + "type": "string" + }, "migrations": { "type": "string" }, @@ -3019,6 +3417,9 @@ const docTemplate = `{ }, "whatsmeow_log_level": { "type": "string" + }, + "whatsmeow_use_retry_message_store": { + "type": "boolean" } } }, @@ -3412,12 +3813,18 @@ const docTemplate = `{ "type": "string" } }, + "limit": { + "type": "integer" + }, "messages": { "type": "array", "items": { "$ref": "#/definitions/whatsapp.WhatsappMessage" } }, + "page": { + "type": "integer" + }, "server": { "$ref": "#/definitions/models.QpServer" }, @@ -3429,6 +3836,9 @@ const docTemplate = `{ }, "total": { "type": "integer" + }, + "total_pages": { + "type": "integer" } } }, diff --git a/src/swagger/swagger.json b/src/swagger/swagger.json index 481c2d57..11462ce7 100644 --- a/src/swagger/swagger.json +++ b/src/swagger/swagger.json @@ -72,6 +72,91 @@ } } }, + "/api/server/{token}/messages": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Retrieves messages from WhatsApp server with pagination, timestamp and exceptions filtering (authenticated SPA endpoint)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SPA" + ], + "summary": "Get server messages (SPA)", + "parameters": [ + { + "type": "string", + "description": "Server token", + "name": "token", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Timestamp filter for messages (Unix timestamp)", + "name": "timestamp", + "in": "query" + }, + { + "type": "string", + "description": "Filter by exceptions: 'true' for messages with errors, 'false' for messages without errors, omit for all", + "name": "exceptions", + "in": "query" + }, + { + "type": "integer", + "description": "Page number (default: 1)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "Messages per page (default: 50, max: 500)", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.QpReceiveResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "503": { + "description": "Service Unavailable", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + } + } + } + }, "/chat/archive": { "post": { "security": [ @@ -271,13 +356,13 @@ } }, "/command": { - "get": { + "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "Execute control commands for the bot server (start, stop, restart)", + "description": "Execute control commands for the bot server (start, stop, restart) or toggle settings (groups, broadcasts, readreceipts, readupdate, calls, debug)", "consumes": [ "application/json" ], @@ -290,16 +375,21 @@ "summary": "Execute bot commands", "parameters": [ { - "enum": [ - "start", - "stop", - "restart" - ], - "type": "string", - "description": "Command action", - "name": "action", - "in": "query", - "required": true + "description": "Command request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "token": { + "type": "string" + } + } + } } ], "responses": { @@ -314,6 +404,12 @@ "schema": { "$ref": "#/definitions/models.QpResponse" } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } } } } @@ -1767,7 +1863,7 @@ "ApiKeyAuth": [] } ], - "description": "Retrieves pending messages from WhatsApp with optional timestamp filtering and exceptions error filtering", + "description": "Retrieves pending messages from WhatsApp with optional cache filters", "consumes": [ "application/json" ], @@ -1790,6 +1886,54 @@ "description": "Filter by exceptions error status: 'true' for messages with exceptions errors, 'false' for messages without exceptions errors, omit for all messages", "name": "exceptions", "in": "query" + }, + { + "type": "string", + "description": "Filter by message type (supports comma-separated list)", + "name": "type", + "in": "query" + }, + { + "type": "string", + "description": "Filter by category: sent, received, sync, unhandled, events", + "name": "category", + "in": "query" + }, + { + "type": "string", + "description": "Search text in id, chat, text, trackid, participant and exceptions", + "name": "search", + "in": "query" + }, + { + "type": "string", + "description": "Filter by fromme boolean: true or false", + "name": "fromme", + "in": "query" + }, + { + "type": "string", + "description": "Filter by fromhistory boolean: true or false", + "name": "fromhistory", + "in": "query" + }, + { + "type": "string", + "description": "Filter by chat id (contains)", + "name": "chatid", + "in": "query" + }, + { + "type": "string", + "description": "Filter by message id (contains)", + "name": "messageid", + "in": "query" + }, + { + "type": "string", + "description": "Filter by track id (contains)", + "name": "trackid", + "in": "query" } ], "responses": { @@ -2063,6 +2207,184 @@ } } }, + "/server/{token}/disable": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Stops the WhatsApp server instance identified by {token}. Sends feedback to the caller on success.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SPA" + ], + "summary": "Disable a server (SPA)", + "parameters": [ + { + "type": "string", + "description": "Server token", + "name": "token", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + } + } + } + }, + "/server/{token}/enable": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Starts the WhatsApp server instance identified by {token}. Sends a system message to notify connected listeners.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SPA" + ], + "summary": "Enable a server (SPA)", + "parameters": [ + { + "type": "string", + "description": "Server token", + "name": "token", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + } + } + } + }, + "/server/{token}/messages/{messageid}/history/download": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Given a ProtocolMessage history-sync event message id, attempts to download and decrypt the referenced media using the active Whatsmeow connection, attaches it to the message and triggers an update so the UI and dispatchers are notified.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SPA" + ], + "summary": "Download history-sync media", + "parameters": [ + { + "type": "string", + "description": "Server token", + "name": "token", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Message id (protocol message)", + "name": "messageid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + }, + "503": { + "description": "Service Unavailable", + "schema": { + "$ref": "#/definitions/models.QpResponse" + } + } + } + } + }, "/spam": { "post": { "security": [ @@ -2664,6 +2986,10 @@ "master_key": { "type": "string" }, + "password": { + "description": "default password for database seeding", + "type": "string" + }, "prefix": { "type": "string" }, @@ -2677,12 +3003,45 @@ "use_ssl_websocket": { "type": "boolean" }, + "user": { + "description": "default user for database seeding", + "type": "string" + }, "webhook_timeout": { "description": "webhook timeout in milliseconds", "type": "integer" } } }, + "environment.BrandingSettings": { + "type": "object", + "properties": { + "accentColor": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "companyUrl": { + "type": "string" + }, + "favicon": { + "type": "string" + }, + "logo": { + "type": "string" + }, + "primaryColor": { + "type": "string" + }, + "secondaryColor": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, "environment.DashboardSettings": { "type": "object", "properties": { @@ -2726,6 +3085,9 @@ "api": { "$ref": "#/definitions/environment.APISettings" }, + "branding": { + "$ref": "#/definitions/environment.BrandingSettings" + }, "database": { "description": "Embedded structs for organized access to different environment categories", "allOf": [ @@ -2796,6 +3158,9 @@ "read_update": { "type": "string" }, + "retry_message_store": { + "type": "string" + }, "wakeup_duration": { "type": "string" }, @@ -2812,6 +3177,10 @@ }, "prefix": { "type": "string" + }, + "serversViewMode": { + "description": "\"card\" or \"table\"", + "type": "string" } } }, @@ -2839,9 +3208,38 @@ "convert_wave_to_ogg": { "type": "boolean" }, + "force_audio_as_ptt": { + "type": "boolean" + }, "log_level": { "type": "string" }, + "login_custom_css": { + "type": "string" + }, + "login_font_awesome": { + "type": "string" + }, + "login_footer": { + "type": "string" + }, + "login_google_fonts": { + "type": "string" + }, + "login_layout": { + "description": "center|split|simple", + "type": "string" + }, + "login_logo": { + "description": "Login customization", + "type": "string" + }, + "login_subtitle": { + "type": "string" + }, + "login_warning": { + "type": "string" + }, "migrations": { "type": "string" }, @@ -3016,6 +3414,9 @@ }, "whatsmeow_log_level": { "type": "string" + }, + "whatsmeow_use_retry_message_store": { + "type": "boolean" } } }, @@ -3409,12 +3810,18 @@ "type": "string" } }, + "limit": { + "type": "integer" + }, "messages": { "type": "array", "items": { "$ref": "#/definitions/whatsapp.WhatsappMessage" } }, + "page": { + "type": "integer" + }, "server": { "$ref": "#/definitions/models.QpServer" }, @@ -3426,6 +3833,9 @@ }, "total": { "type": "integer" + }, + "total_pages": { + "type": "integer" } } }, diff --git a/src/swagger/swagger.yaml b/src/swagger/swagger.yaml index 35711256..87bfa50d 100644 --- a/src/swagger/swagger.yaml +++ b/src/swagger/swagger.yaml @@ -170,6 +170,9 @@ definitions: properties: master_key: type: string + password: + description: default password for database seeding + type: string prefix: type: string signing_secret: @@ -179,10 +182,32 @@ definitions: type: integer use_ssl_websocket: type: boolean + user: + description: default user for database seeding + type: string webhook_timeout: description: webhook timeout in milliseconds type: integer type: object + environment.BrandingSettings: + properties: + accentColor: + type: string + companyName: + type: string + companyUrl: + type: string + favicon: + type: string + logo: + type: string + primaryColor: + type: string + secondaryColor: + type: string + title: + type: string + type: object environment.DashboardSettings: properties: enabled: @@ -211,6 +236,8 @@ definitions: properties: api: $ref: '#/definitions/environment.APISettings' + branding: + $ref: '#/definitions/environment.BrandingSettings' database: allOf: - $ref: '#/definitions/environment.DatabaseSettings' @@ -257,6 +284,8 @@ definitions: type: string read_update: type: string + retry_message_store: + type: string wakeup_duration: type: string wakeup_hour: @@ -268,6 +297,9 @@ definitions: type: boolean prefix: type: string + serversViewMode: + description: '"card" or "table"' + type: string type: object environment.GeneralSettings: properties: @@ -285,8 +317,28 @@ definitions: type: boolean convert_wave_to_ogg: type: boolean + force_audio_as_ptt: + type: boolean log_level: type: string + login_custom_css: + type: string + login_font_awesome: + type: string + login_footer: + type: string + login_google_fonts: + type: string + login_layout: + description: center|split|simple + type: string + login_logo: + description: Login customization + type: string + login_subtitle: + type: string + login_warning: + type: string migrations: type: string remove_digit_9: @@ -402,6 +454,8 @@ definitions: type: string whatsmeow_log_level: type: string + whatsmeow_use_retry_message_store: + type: boolean type: object models.QpContactsResponse: properties: @@ -658,10 +712,14 @@ definitions: items: type: string type: array + limit: + type: integer messages: items: $ref: '#/definitions/whatsapp.WhatsappMessage' type: array + page: + type: integer server: $ref: '#/definitions/models.QpServer' status: @@ -670,6 +728,8 @@ definitions: type: boolean total: type: integer + total_pages: + type: integer type: object models.QpRequestResponse: properties: @@ -1297,6 +1357,63 @@ paths: summary: Manage user accounts tags: - Application + /api/server/{token}/messages: + get: + consumes: + - application/json + description: Retrieves messages from WhatsApp server with pagination, timestamp + and exceptions filtering (authenticated SPA endpoint) + parameters: + - description: Server token + in: path + name: token + required: true + type: string + - description: Timestamp filter for messages (Unix timestamp) + in: query + name: timestamp + type: string + - description: 'Filter by exceptions: ''true'' for messages with errors, ''false'' + for messages without errors, omit for all' + in: query + name: exceptions + type: string + - description: 'Page number (default: 1)' + in: query + name: page + type: integer + - description: 'Messages per page (default: 50, max: 500)' + in: query + name: limit + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.QpReceiveResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/models.QpResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/models.QpResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/models.QpResponse' + "503": + description: Service Unavailable + schema: + $ref: '#/definitions/models.QpResponse' + security: + - Bearer: [] + summary: Get server messages (SPA) + tags: + - SPA /chat/archive: post: consumes: @@ -1423,20 +1540,23 @@ paths: tags: - Chat /command: - get: + post: consumes: - application/json description: Execute control commands for the bot server (start, stop, restart) + or toggle settings (groups, broadcasts, readreceipts, readupdate, calls, debug) parameters: - - description: Command action - enum: - - start - - stop - - restart - in: query - name: action + - description: Command request + in: body + name: request required: true - type: string + schema: + properties: + action: + type: string + token: + type: string + type: object produces: - application/json responses: @@ -1448,6 +1568,10 @@ paths: description: Bad Request schema: $ref: '#/definitions/models.QpResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/models.QpResponse' security: - ApiKeyAuth: [] summary: Execute bot commands @@ -2365,8 +2489,7 @@ paths: get: consumes: - application/json - description: Retrieves pending messages from WhatsApp with optional timestamp - filtering and exceptions error filtering + description: Retrieves pending messages from WhatsApp with optional cache filters parameters: - description: Timestamp filter for messages in: query @@ -2378,6 +2501,38 @@ paths: in: query name: exceptions type: string + - description: Filter by message type (supports comma-separated list) + in: query + name: type + type: string + - description: 'Filter by category: sent, received, sync, unhandled, events' + in: query + name: category + type: string + - description: Search text in id, chat, text, trackid, participant and exceptions + in: query + name: search + type: string + - description: 'Filter by fromme boolean: true or false' + in: query + name: fromme + type: string + - description: 'Filter by fromhistory boolean: true or false' + in: query + name: fromhistory + type: string + - description: Filter by chat id (contains) + in: query + name: chatid + type: string + - description: Filter by message id (contains) + in: query + name: messageid + type: string + - description: Filter by track id (contains) + in: query + name: trackid + type: string produces: - application/json responses: @@ -2662,6 +2817,125 @@ paths: summary: Send document with forced document type tags: - Send + /server/{token}/disable: + post: + consumes: + - application/json + description: Stops the WhatsApp server instance identified by {token}. Sends + feedback to the caller on success. + parameters: + - description: Server token + in: path + name: token + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.QpResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/models.QpResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/models.QpResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/models.QpResponse' + security: + - Bearer: [] + summary: Disable a server (SPA) + tags: + - SPA + /server/{token}/enable: + post: + consumes: + - application/json + description: Starts the WhatsApp server instance identified by {token}. Sends + a system message to notify connected listeners. + parameters: + - description: Server token + in: path + name: token + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.QpResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/models.QpResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/models.QpResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/models.QpResponse' + security: + - Bearer: [] + summary: Enable a server (SPA) + tags: + - SPA + /server/{token}/messages/{messageid}/history/download: + post: + consumes: + - application/json + description: Given a ProtocolMessage history-sync event message id, attempts + to download and decrypt the referenced media using the active Whatsmeow connection, + attaches it to the message and triggers an update so the UI and dispatchers + are notified. + parameters: + - description: Server token + in: path + name: token + required: true + type: string + - description: Message id (protocol message) + in: path + name: messageid + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.QpResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/models.QpResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/models.QpResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/models.QpResponse' + "503": + description: Service Unavailable + schema: + $ref: '#/definitions/models.QpResponse' + security: + - Bearer: [] + summary: Download history-sync media + tags: + - SPA /spam: post: consumes: diff --git a/src/webserver/webserver.go b/src/webserver/webserver.go index b8c1c669..9e70975c 100644 --- a/src/webserver/webserver.go +++ b/src/webserver/webserver.go @@ -3,6 +3,8 @@ package webserver import ( "fmt" "net/http" + "net/http/httputil" + "net/url" "os" "path/filepath" "strings" @@ -62,11 +64,11 @@ func newRouter() chi.Router { r.Use(middleware.Logger) } - // Recoverer should wrap all previous middlewares. - // chi applies middlewares in reverse when building the final handler chain, - // so adding Recoverer last makes it the outermost wrapper. r.Use(middleware.Recoverer) + // Serve SPA root (dev proxy or static build) before other configurators + ServeSPA(r) + // Form and SignalR routes are now configured automatically via configurators // Execute registered configurators (e.g., Swagger, custom modules) @@ -77,6 +79,150 @@ func newRouter() chi.Router { return r } +// ServeSPA registers handlers to serve the frontend single-page application. +// In development (QUEPASA_DEV_FRONTEND=1) it proxies requests to the local Vite dev server. +// In production it serves files from assets/frontend and falls back to index.html for SPA routes. +func ServeSPA(r chi.Router) { + // Check if dev proxy is enabled + if v := os.Getenv("QUEPASA_DEV_FRONTEND"); v == "1" || v == "true" { + viteHost := os.Getenv("QUEPASA_FRONTEND_HOST") + if viteHost == "" { + viteHost = "http://127.0.0.1" + } + vitePort := os.Getenv("QUEPASA_FRONTEND_DEV_PORT") + if vitePort == "" { + vitePort = "5173" + } + viteBasePath := os.Getenv("QUEPASA_FRONTEND_BASE_PATH") + if viteBasePath == "" { + viteBasePath = "/assets/frontend" + } + target := viteHost + ":" + vitePort + // create reverse proxy WITHOUT base path rewrite + proxy := NewReverseProxy(target, "") + log.Infof("SPA dev proxy enabled, proxying to %s", target) + + // In dev mode with base: '/', we just proxy everything that isn't API or Form + r.NotFound(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + // Let API, Form and legacy API paths return 404 if not matched by registered routes + // Legacy API paths (/info, /health, /v3, /v4, /current, /swagger, /mcp) should return 404 if not matched + if strings.HasPrefix(req.URL.Path, "/api") || strings.HasPrefix(req.URL.Path, "/form") || isLegacyAPIPath(req.URL.Path) { + w.WriteHeader(http.StatusNotFound) + return + } + // Proxy everything else to Vite (including all GET/POST/etc) + log.Infof("Proxying request: %s %s -> 127.0.0.1:5173%s", req.Method, req.URL.Path, req.URL.Path) + proxy.ServeHTTP(w, req) + })) + return + } + + // Production: serve files from assets/frontend + workDir, _ := os.Getwd() + frontendDir := filepath.Join(workDir, "assets", "frontend") + fs := http.FileServer(http.Dir(frontendDir)) + + // Use NotFound handler to serve SPA index or static file when nothing else matched + r.NotFound(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + // Only serve SPA for GET requests and not for API, assets, form or legacy API paths + // Legacy API paths (/info, /health, /v3, /v4, /current, /swagger, /mcp) should return 404 if not matched + if req.Method != http.MethodGet || + strings.HasPrefix(req.URL.Path, "/api") || + strings.HasPrefix(req.URL.Path, "/assets") || + strings.HasPrefix(req.URL.Path, "/form") || + isLegacyAPIPath(req.URL.Path) { + w.WriteHeader(http.StatusNotFound) + return + } + + // Try to serve a static file first + path := filepath.Join(frontendDir, filepath.Clean(req.URL.Path)) + if info, err := os.Stat(path); err == nil && !info.IsDir() { + fs.ServeHTTP(w, req) + return + } + + // Fallback to index.html + indexPath := filepath.Join(frontendDir, "index.html") + http.ServeFile(w, req, indexPath) + })) +} + +// isLegacyAPIPath checks if the path is a legacy API path that should NOT be served by the SPA. +// These paths are API endpoints that existed before the /api prefix was standardized. +// If API_PREFIX is empty, these paths are used for API routes. +func isLegacyAPIPath(path string) bool { + // List of legacy API path prefixes that should not be served by SPA + legacyPrefixes := []string{ + "/info", + "/health", + "/healthapi", + "/v3/", + "/v4/", + "/current/", + "/swagger", + "/mcp", + "/scan", + "/paircode", + "/command", + "/message", + "/send", + "/receive", + "/download", + "/webhook", + "/picinfo", + "/picdata", + "/contacts", + "/groups", + "/invite", + "/account", + "/rabbitmq", + "/read", + "/edit", + "/isonwhatsapp", + "/useridentifier", + "/getphone", + "/environment", + "/login", + } + + for _, prefix := range legacyPrefixes { + if strings.HasPrefix(path, prefix) { + return true + } + } + return false +} + +// NewReverseProxy creates a reverse proxy to a target (http://host:port) +// basePath is the base path to prepend to requests (e.g., "/assets/frontend") +func NewReverseProxy(target string, basePath string) *httputil.ReverseProxy { + url, err := url.Parse(target) + if err != nil { + // fallback to a proxy to localhost:5173 + url, _ = url.Parse("http://127.0.0.1:5173") + } + proxy := httputil.NewSingleHostReverseProxy(url) + originalDirector := proxy.Director + proxy.Director = func(req *http.Request) { + originalDirector(req) + // Remove the extra log here since we log in NotFound handler + // Rewrite path to include base path if provided + if basePath != "" { + originalPath := req.URL.Path + if originalPath == "/" { + req.URL.Path = basePath + "/" + } else if !strings.HasPrefix(originalPath, basePath) { + req.URL.Path = basePath + originalPath + } + } + // allow websocket upgrades to pass through + req.Header.Set("X-Forwarded-Host", req.Host) + req.Header.Set("X-Origin-Host", url.Host) + } + return proxy +} + func ServeStaticContent(r chi.Router) { // setting group diff --git a/src/whatsapp/whatsapp_boolean_extended.go b/src/whatsapp/whatsapp_boolean_extended.go index f0f464a3..bedfcda2 100644 --- a/src/whatsapp/whatsapp_boolean_extended.go +++ b/src/whatsapp/whatsapp_boolean_extended.go @@ -52,3 +52,15 @@ func (source WhatsappBooleanExtended) Compare(item WhatsappBoolean, value bool) return item.ToBoolean(value) } } + +// ToWhatsappBoolean converts WhatsappBooleanExtended to WhatsappBoolean. +func (source WhatsappBooleanExtended) ToWhatsappBoolean() WhatsappBoolean { + switch source { + case ForcedFalseBooleanType: + return FalseBooleanType + case ForcedTrueBooleanType: + return TrueBooleanType + default: + return WhatsappBoolean(source) + } +}