diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..aaaeeac --- /dev/null +++ b/.env.example @@ -0,0 +1,62 @@ +# 浏览器是否无头模式,为True时为无头模式(无界面),为False时为有头模式(有界面) +BROWSER_HEADLESS=True +# 浏览器用户代理 +BROWSER_USER_AGENT="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36" +# 是否使用动态ua池 +DYNAMIC_USERAGENT=False +# Windows 浏览器路径 +#BROWSER_PATH="C:\Users\Administrator\AppData\Local\Google\Chrome\Bin\chrome.exe" +# 是否启用浏览器代理 +USE_PROXY=False +# 代理类型 +PROXY_TYPE=http +# 代理ip +PROXY_HOST=127.0.0.1 +# 代理端口号 +PROXY_PORT=7897 +# 代理超时时间 +PROXY_TIMEOUT=10 + + +# 临时邮箱类型 可选值:tempemail, zmail +EMAIL_TYPE=tempemail +# 多个域名使用逗号分隔 +EMAIL_DOMAINS=xxx.xx + +# 临时邮箱用户名 +EMAIL_USERNAME=xxx +# 临时邮箱PIN码(如果需要) +EMAIL_PIN= +#EMAIL_CODE_TYPE=INPUT #验证码获取方式INPUT 或者 API + +# ===== ZMail配置 ===== +# ZMail API地址 +EMAIL_API=https://xxxxxxxxxxxxxxx +# 是否启用邮箱API代理 +EMAIL_PROXY_ENABLED=True +# 邮箱API代理地址 +EMAIL_PROXY_ADDRESS=http://ip:port + +# ===== 账号管理配置 ===== +# 系统最大已激活的账号数量,如果达到这个数量,则停止注册 +# so 要么在页面维护好当前已激活的账号,要么在页面删除账号,或者直接增大该值 +MAX_ACCOUNTS=10 + +# 数据库URL +DATABASE_URL="sqlite+aiosqlite:///./accounts.db" + +# ===== API服务配置 ===== +# API服务监听主机地址,0.0.0.0 允许非本机访问 +API_HOST="0.0.0.0" +# API服务端口号 +API_PORT=8000 +# 是否启用调试模式 +API_DEBUG=True +# API服务工作进程数量(Windows下建议使用1) +API_WORKERS=1 +# 是否启用UI +ENABLE_UI=True + +# Cursor main.js 主文件路径 +# windows用户部分安装时是自定义目录安装的,需要修改该配置 +#CURSOR_PATH="D:\devtools\cursor" \ No newline at end of file diff --git a/.env11 b/.env11 new file mode 100644 index 0000000..ee21aa8 --- /dev/null +++ b/.env11 @@ -0,0 +1,32 @@ +BROWSER_HEADLESS=True +DYNAMIC_USERAGENT=True + +# 多个域名使用逗号分隔 +EMAIL_DOMAINS=bjh93fxs.shop + +# 临时邮箱用户名 +EMAIL_USERNAME=zbofano +# 临时邮箱PIN码(如果需要) +EMAIL_PIN= + +# 数据库URL +DATABASE_URL="sqlite+aiosqlite:///./accounts.db" + +# ===== API服务配置 ===== +# API服务监听主机地址,0.0.0.0 允许非本机访问 +API_HOST="0.0.0.0" +# API服务端口号 +API_PORT=8000 +# 是否启用UI +ENABLE_UI=True +# 最大注册账号数量 +MAX_ACCOUNTS=1 +# windows用户部分安装时是自定义目录安装的,需要修改该配置 +CURSOR_PATH=C:\Usersbkino\AppData\Local\Programs\cursor +BROWSER_PATH=C:\Program Files\Google\Chrome\Application\chrome.exe +EMAIL_CODE_TYPE=AUTO + +USE_PROXY=False +PROXY_TYPE=http +PROXY_TIMEOUT=10 +RESTART_TIMESTAMP=1743262912 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a271cfe --- /dev/null +++ b/.gitignore @@ -0,0 +1,54 @@ +# Python 编译文件和缓存 +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# 虚拟环境 +venv/ +env/ +ENV/ +.venv/ +.env/ +.ENV/ + +# 日志文件 +*.log + +# 本地配置文件 +.env + +# 数据库文件 +*.db + +# IDE 文件 +.idea/ +.vscode/ +*.swp +*.swo +.DS_Store + +# 临时文件 +tmp/ +temp/ + +# 其他可能的敏感文件 +*.pem +*.key +credentials.json diff --git a/Project_Overview.md b/Project_Overview.md new file mode 100644 index 0000000..ef4dce6 --- /dev/null +++ b/Project_Overview.md @@ -0,0 +1,277 @@ +# Cursor Auto Register 项目总览 + +**项目简介**: 本项目是一个开源的自动化 Cursor Pro 账户注册和管理工具,旨在为学习和技术交流提供参考。 + +**主要目的**: 本项目旨在简化 Cursor Pro 账户的获取流程,并提供 API 接口供二次开发或集成。 + +**参考项目**: +* [chengazhen/cursor-auto-free](https://github.com/chengazhen/cursor-auto-free) +* [cursor-account-api](https://github.com/Elawen-Carl/cursor-account-api) + +**免责声明**: 本项目仅供学习和测试使用,使用风险自负。建议参考项目根目录下的 `README.md` 文件获取更详细的免责声明和许可信息。 + +## 核心功能 + +* 自动化账户注册与激活:能够自动完成 Cursor 账户的注册流程。 +* 提供 RESTful API 进行账户管理:包括创建、查询(支持分页、搜索、排序)、随机获取、状态更新、数据导入/导出等功能。 +* 提供简单的 Web UI:用于查看系统状态、账户列表、配置信息,并进行基本操作。 +* 集成临时邮箱服务:自动化获取注册过程中所需的邮件验证码。 +* 支持配置项管理:允许用户通过 `.env` 文件或 API 修改如最大账户数、API 服务参数、浏览器行为等配置。 +* 账户数据持久化存储:使用 SQLite 数据库 (`accounts.db`) 保存账户信息及使用记录。 +* 详细的日志记录:记录系统运行状态、注册过程、错误信息等,便于追踪和调试。 +* 后台任务管理:支持启动、停止和监控后台的自动注册任务。 +* 系统辅助功能:如重置机器ID、服务重启等。 + +## 技术架构概览 + +* **后端**: 采用 Python 语言和 FastAPI 异步 Web 框架构建,提供高效的 API 服务。 +* **数据库**: 使用 SQLite 进行数据存储,通过 `aiosqlite` 库实现异步数据库操作,确保在高并发场景下的性能。账户信息和相关记录存储在项目根目录的 `accounts.db` 文件中。 +* **前端**: 提供一个基础的 HTML 前端界面 (`index.html`),结合 `static/` 目录下的静态资源 (CSS, JavaScript),为用户提供基本的可视化操作和信息展示。 +* **核心依赖与工具**: + * 编程语言: Python 3.10+ + * Web 框架: FastAPI, Uvicorn (ASGI 服务器) + * 数据库ORM/Driver: SQLAlchemy (异步模式), aiosqlite + * 浏览器自动化: 可能通过 Selenium 或 Playwright (封装在 `browser_utils.py` 中) 实现与浏览器的交互。 + * 邮件服务: 依赖外部临时邮箱服务 (如 tempmail.plus) 获取验证码,通常需要用户配置 Cloudflare 邮件路由规则进行转发。 + * 人机验证处理: 包含针对 Cloudflare Turnstile 等验证码的应对逻辑 (体现在 `turnstilePatch/` 目录及相关代码中)。 +* **配置管理**: 通过根目录的 `.env` 文件进行环境变量配置,由 `config.py` 读取和管理。 +* **部署**: + * 本地运行: 可直接通过 `uvicorn api:app --host --port --reload` 命令启动 (具体命令依据 `README.md` 或启动脚本)。 + * 容器化: 项目提供了 `dockerfile`,支持使用 Docker 进行构建和部署,方便环境隔离和迁移。 + +## 主要模块/组件详解 + +### `api.py` (FastAPI 应用层) +项目的核心入口和控制中心。基于 FastAPI 构建,定义了所有的 HTTP API 端点,负责: +* 接收和验证客户端请求。 +* 路由请求到相应的业务逻辑处理函数。 +* 调用其他模块(如 `database.py`, `cursor_pro_keep_alive.py`)完成具体操作。 +* 格式化并返回响应给客户端。 +* 实现诸如账户管理、注册任务控制、系统配置查询与更新、UI服务、API文档(Swagger/ReDoc)等功能。 +* 管理应用的生命周期事件(如启动时初始化数据库)。 + +### `cursor_pro_keep_alive.py` (核心注册逻辑) +此模块封装了 Cursor 账户自动化注册和激活的核心业务流程。其主要职责包括: +* 执行完整的账户创建步骤,从访问注册页面到最终激活账户。 +* 周期性地被 `api.py` 中的后台任务调用,以维持设定的账户数量。 +* 协调调用 `get_email_code.py` 来获取邮箱地址和验证码。 +* 利用 `browser_utils.py` 进行浏览器自动化操作(如填写表单、点击链接)。 +* 处理注册过程中可能遇到的 Cloudflare Turnstile 等人机验证(可能调用 `turnstilePatch/` 中的逻辑)。 +* 在注册成功或失败后,更新账户状态并记录相关信息。 + +### `database.py` (数据持久化层) +负责所有与数据库 (`accounts.db`) 相关的操作。 +* 定义数据模型,如 `AccountModel` (存储账户信息) 和 `AccountUsageRecordModel` (存储账户使用记录)。 +* 提供数据库初始化函数 `init_db()`,在应用启动时创建表结构。 +* 封装了异步的 CRUD (创建、读取、更新、删除) 操作接口,供 `api.py` 等模块调用,以管理账户数据。 +* 使用 SQLAlchemy Core 和 `aiosqlite` 实现与 SQLite 的异步交互。 + +### `get_email_code.py` (邮件处理模块) +专用于处理邮件相关的任务,特别是自动化获取注册过程中所需的邮件验证码。 +* 与用户配置的临时邮箱服务 (如 tempmail.plus) API 进行交互。 +* 获取可用的临时邮箱地址。 +* 监控邮箱,等待并提取 Cursor 发送的验证码邮件内容。 + +### `config.py` 与 `.env` (配置模块) +管理项目的各项配置参数。 +* `.env`: 纯文本文件,用于存储用户特定的配置值(如 API 密钥、邮箱账户、数据库路径、服务器端口等),不应提交到版本控制。项目提供了 `.env.example` 作为模板。 +* `config.py`: Python 脚本,定义所有可配置参数的名称、数据类型、默认值,并从 `.env` 文件或环境变量中加载实际配置值。这些配置项在整个应用中被其他模块引用。 + +### `tokenManager/` (Token 管理模块) +此目录 (特别是 `tokenManager/cursor.py` 中的 `Cursor` 类) 封装了与 Cursor 服务端进行认证和 token 管理的逻辑。 +* 可能包括获取新的用户 token、刷新即将过期的 token、验证 token 有效性等功能。 +* 在账户注册成功后,或在需要代表用户与 Cursor API 交互时被调用。 + +### `browser_utils.py` (浏览器工具) +提供一系列用于控制和自动化浏览器行为的辅助函数。 +* 封装了与浏览器驱动 (如 ChromeDriver for Selenium) 的交互。 +* 功能可能包括:启动浏览器(有头或无头模式)、打开指定 URL、查找页面元素、模拟用户输入(填写表单)、点击按钮、执行 JavaScript 脚本等。 +* 主要被 `cursor_pro_keep_alive.py` 在自动化注册流程中使用。 + +### `turnstilePatch/` (人机验证处理) +此目录下的代码专注于处理 Cloudflare Turnstile 等类型的人机验证挑战。 +* 可能包含识别验证码、与第三方验证码识别服务API交互、或尝试其他绕过验证的策略。 +* 在自动化注册过程中,当遇到此类验证时被调用。 + +### `logger.py` (日志系统) +提供标准化的日志记录功能。 +* 配置日志的格式、级别 (INFO, ERROR, DEBUG 等) 和输出目标 (如控制台、日志文件 `app.log`, `api.log`)。 +* 供项目中所有其他模块调用,以记录关键操作、程序流程、错误信息和调试信息。 + +### `index.html` 与 `static/` (前端展现层) +构成项目的用户界面。 +* `index.html`: 单页应用的主 HTML 文件,定义了页面的基本骨架。 +* `static/`: 存放 CSS 样式表、JavaScript 脚本、图片等静态资源,用于美化界面和实现前端交互逻辑。 +* 前端通过调用 `api.py` 提供的 API 来获取数据、展示信息和提交用户操作。 + +### `reset_machine.py` (机器ID重置模块) +提供了一个特定的功能,用于重置或修改被 Cursor 服务识别的机器 ID。 +* 这可能用于解决因同一设备注册过多账户而被限制的问题。 +* 通常通过 `api.py` 中的特定 API 端点 (`/reset-machine`) 触发。 + +## 核心工作流程示例 + +### 新账户自动注册流程 +1. **任务触发**: `api.py` 中的后台任务 (`run_registration`) 按照预设的间隔 (`REGISTRATION_INTERVAL`) 检查当前激活账户数量是否低于 `MAX_ACCOUNTS`。 +2. **启动注册**: 如果需要新账户,任务调用 `cursor_pro_keep_alive.main()` 函数。 +3. **获取邮箱**: `cursor_pro_keep_alive.py` 调用 `get_email_code.py`,后者与临时邮箱服务交互,获取一个临时邮箱地址。 +4. **浏览器操作与表单填写**: `cursor_pro_keep_alive.py` 使用 `browser_utils.py` 控制浏览器(可能是无头模式)打开 Cursor 注册页面,并填入获取的邮箱地址及生成的密码等信息。 +5. **处理人机验证 (如果出现)**: 如果注册页面出现 Cloudflare Turnstile 等人机验证,`cursor_pro_keep_alive.py` 可能会调用 `turnstilePatch/` 中的逻辑尝试解决。 +6. **提交注册与接收验证码**: 提交注册信息后,`cursor_pro_keep_alive.py` 再次通过 `get_email_code.py` 监控临时邮箱,等待并提取 Cursor 发送的验证邮件中的激活链接或验证码。 +7. **账户激活**: 使用获取到的验证码或激活链接,通过 `browser_utils.py` 完成账户激活步骤。 +8. **获取 Token (如果适用)**: 激活后,可能通过 `tokenManager/cursor.py` 获取与该账户关联的 Cursor token。 +9. **数据入库**: 注册成功后,将账户的邮箱、密码、token(如有)、状态等信息通过 `database.py` 提供的接口存入 `accounts.db` 数据库。 +10. **日志记录**: 整个过程中的关键步骤、成功或失败信息都会通过 `logger.py` 记录下来。 + +### 用户通过 API 获取随机账户流程 +1. **API 请求**: 用户或外部应用向 `api.py` 发送 `GET` 请求到 `/account/random` 端点。 +2. **请求处理**: `api.py` 中的对应路由处理函数接收到该请求。 +3. **数据库查询**: 该处理函数调用 `database.py` 中封装的数据库查询方法,从 `accounts` 表中随机选择一个状态为 "active" (或其他可用状态) 的账户记录。 +4. **数据格式化**: `database.py` 返回查询结果给 `api.py`。`api.py` 可能需要将原始数据模型转换为 Pydantic 定义的响应模型,确保返回数据的结构和类型正确。 +5. **API 响应**: `api.py` 将包含随机账户信息的 JSON 数据作为 HTTP 响应返回给请求方。 +6. **日志记录**: API 调用信息(如请求路径、时间、结果等)可能会被 `logger.py` 记录。 + +## 环境要求与部署 + +### 环境要求 +* **Python**: 版本 3.10 或更高。 +* **pip**: Python 包管理器,用于安装项目依赖。 +* **依赖包**: 所有必需的 Python 库均在 `requirements.txt` 文件中列出。可以通过 `pip install -r requirements.txt` 命令一键安装。 +* **外部服务**: + * 临时邮箱服务 (如 tempmail.plus) 并正确配置 Cloudflare DNS 及邮件路由规则,以便 `get_email_code.py` 能够接收验证码。 + * 网络连接:用于访问 Cursor 网站、临时邮箱服务以及可能的验证码服务。 + +### 配置 +项目的核心配置通过位于根目录下的 `.env` 文件进行管理。在首次运行前,需要根据 `.env.example` 文件创建一个 `.env` 文件,并填入实际的配置值。关键配置项包括: +* `EMAIL_DOMAINS`: 用于接收邮件的域名(需配合Cloudflare)。 +* `EMAIL_USERNAME`: 临时邮箱服务提供的用户名/邮箱前缀。 +* `EMAIL_PIN`: 临时邮箱服务可能需要的 PIN 码。 +* `DATABASE_URL`: SQLite 数据库文件的路径,默认为 `sqlite+aiosqlite:///./accounts.db`。 +* `API_HOST`: API 服务监听的主机地址 (如 `0.0.0.0` 允许外部访问)。 +* `API_PORT`: API 服务监听的端口号 (如 `8000`)。 +* `ENABLE_UI`: 是否启用 Web UI (True/False)。 +* `MAX_ACCOUNTS`: 系统维护的最大激活账户数量。 +* `CURSOR_PATH` (可选): Cursor 客户端的安装路径,某些功能可能需要。 +* 浏览器相关配置 (如 `BROWSER_HEADLESS`, `BROWSER_PATH`等)。 +* 代理配置 (如 `USE_PROXY`, `PROXY_HOST`, `PROXY_PORT`等)。 + +### 运行与部署 + +**1. 本地开发/直接运行:** + a. 确保已安装 Python 3.10+ 和 pip。 + b. 克隆项目代码到本地。 + c. 在项目根目录下,复制 `.env.example` 为 `.env`,并修改其中的配置项。 + d. 安装依赖:`pip install -r requirements.txt` + e. 启动应用:通常使用 Uvicorn 作为 ASGI 服务器来运行 FastAPI 应用。命令如下: + ```bash + uvicorn api:app --host --port --reload + ``` + 将 `` 和 ``替换为 `.env` 中配置的值 (例如 `0.0.0.0` 和 `8000`)。`--reload` 参数可以在代码变更时自动重启服务,适合开发环境。 + 项目根目录下的 `启动服务器.bat` (Windows) 可能封装了此命令。 + +**2. Docker 部署:** + 项目提供了 `dockerfile`,可以用于构建 Docker 镜像并进行容器化部署。 + a. 确保已安装 Docker。 + b. 在项目根目录下,构建 Docker 镜像: + ```bash + docker build -t cursor-auto-register . + ``` + c. 运行 Docker 容器 (需要将 `.env` 文件或环境变量传递给容器): + ```bash + docker run -d --env-file .env -p : --name cursor_register_app cursor-auto-register + ``` + 将 `` 替换为希望在宿主机上映射的端口,`` 替换为容器内应用监听的端口 (即 `.env` 中配置的 `API_PORT`)。`-d` 参数使容器在后台运行。确保 `.env` 文件在执行 `docker run` 命令的上下文中可访问,或者使用其他方式 (如 `-e` 参数) 传递环境变量。 + +## 使用与API + +### Web UI +如果 `ENABLE_UI` 配置为 `True`,在服务成功启动后,可以通过浏览器访问部署的地址来使用 Web UI。默认情况下,如果服务运行在本地且端口为 `8000`,则 UI 地址为: +`http://localhost:8000/` 或 `http://127.0.0.1:8000/` + +Web UI 通常提供以下功能: +* 查看当前系统状态和注册任务信息。 +* 展示已注册的账户列表及其状态。 +* 查看和修改部分系统配置。 +* 手动触发某些操作。 + +### 主要 API 端点 +项目通过 FastAPI 提供了一系列 RESTful API 端点,便于程序化交互和集成。以下是一些核心端点示例: + +* **`GET /health`**: + * 描述:检查 API 服务的健康状况。 + * 响应:返回服务运行状态。 + +* **`GET /accounts`**: + * 描述:获取账户列表,支持分页、搜索和排序。 + * 参数(Query):`page`, `per_page`, `search`, `sort_by`, `order`。 + * 响应:包含账户列表及分页信息的 JSON 数据。 + +* **`GET /account/random`**: + * 描述:随机获取一个当前状态为可用的账户。 + * 响应:包含单个账户详细信息的 JSON 数据。 + +* **`POST /account`**: + * 描述:手动创建一个新的账户记录(注意:这通常区别于后台的自动注册任务,具体用途需参考实现,可能用于导入已有账户或特定测试)。 + * 请求体:包含账户信息的 JSON 对象 (如 `email`, `password`, `token`)。 + * 响应:操作结果及创建的账户信息。 + +* **`DELETE /account/{email}` 或 `DELETE /account/id/{id}`**: + * 描述:删除指定邮箱或ID的账户。可能支持软删除或硬删除。 + * 响应:操作结果。 + +* **`PUT /account/id/{id}/status`**: + * 描述:更新指定ID账户的状态。 + * 请求体:包含新状态的 JSON 对象 (如 `{"status": "inactive"}`)。 + * 响应:操作结果及更新后的账户信息。 + +* **`GET /registration/start`**: + * 描述:启动后台的自动注册任务(如果尚未运行)。 + * 响应:任务启动状态。 + +* **`GET /registration/stop`**: + * 描述:停止后台的自动注册任务。 + * 响应:任务停止状态。 + +* **`GET /registration/status`**: + * 描述:获取当前后台自动注册任务的详细状态(如是否运行、上次运行时间、成功/失败次数等)。 + * 响应:包含任务状态信息的 JSON 数据。 + +* **`GET /config`**: + * 描述:获取当前系统的配置信息。 + * 响应:包含所有可配置项及其当前值的 JSON 数据。 + +* **`POST /config`**: + * 描述:更新系统配置项。 + * 请求体:包含要修改的配置项及其新值的 JSON 对象。 + * 响应:操作结果。 + +### API 文档 +服务启动后,FastAPI 会自动生成交互式的 API 文档: +* **Swagger UI**: 可通过访问 `/docs` 路径 (例如 `http://localhost:8000/docs`) 查看和测试 API。 +* **ReDoc**: 可通过访问 `/redoc` 路径 (例如 `http://localhost:8000/redoc`) 获取另一种格式的 API 文档。 + +这些文档详细列出了所有可用的 API 端点、请求参数、请求体结构、响应格式以及示例。 + +## 注意事项与免责声明 + +### 注意事项 +1. **配置准确性**: 请务必确保 `.env` 文件中的各项配置(尤其是 `EMAIL_DOMAINS`, `EMAIL_USERNAME`, 以及 Cloudflare 相关设置)正确无误,错误的配置可能导致注册失败或功能异常。 +2. **依赖服务**: 本项目的许多核心功能(如邮件验证码获取)依赖于第三方服务(如临时邮箱平台、Cloudflare)。这些服务的稳定性、可用性或政策变更可能会直接影响本项目的正常运行。 +3. **Cloudflare 设置**: 使用自定义域名接收邮件时,必须正确配置 Cloudflare 的 DNS 解析以及邮件路由 (Email Routing) 规则,将特定邮件地址或 Catch-all 地址转发到你实际使用的临时邮箱服务能够接收的地址。 +4. **资源权限**: 确保程序运行时对 `accounts.db` 数据库文件以及 `app.log`, `api.log` 等日志文件有足够的读写权限。 +5. **并发与限制**: 自动化注册大量账户可能会触发目标网站(Cursor)的速率限制、更严格的人机验证或账户封禁策略。请合理配置 `MAX_ACCOUNTS` 和 `REGISTRATION_INTERVAL`,避免滥用。 +6. **浏览器与驱动**: 如果项目使用 Selenium/Playwright 等浏览器自动化工具,请确保对应的浏览器已安装,并且浏览器驱动版本与浏览器版本兼容。 +7. **法律与合规**: 用户应自行了解并遵守 Cursor 的服务条款。滥用本工具可能导致违反相关条款。 + +### 免责声明 +本项目 (`Cursor Auto Register`) 严格仅供个人学习、教育和技术研究目的使用。严禁将本项目用于任何商业用途或任何可能违反适用法律法规的活动。 + +开发者不对用户如何使用本项目承担任何责任。用户必须独立承担因使用或无法使用本项目所导致的一切直接或间接风险和后果,包括但不限于: +* 账户被目标服务(如 Cursor)限制或封禁。 +* 违反目标服务的使用条款。 +* 数据丢失或损坏。 +* 任何经济损失或其他形式的损害。 + +通过下载、复制、修改或使用本项目的任何部分,即表示用户已阅读、理解并同意上述所有条款和条件。如果用户不同意这些条款,请勿使用本项目。 + +开发者保留随时修改或终止本项目的权利,恕不另行通知。 diff --git a/api.py b/api.py new file mode 100644 index 0000000..41e0726 --- /dev/null +++ b/api.py @@ -0,0 +1,1524 @@ +# FastAPI 相关导入 +from fastapi import FastAPI, HTTPException, status, UploadFile, Request +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse, FileResponse, Response +from fastapi.staticfiles import StaticFiles + +# 数据模型和验证相关 +from pydantic import BaseModel +from typing import Optional, List + +# 数据库相关 +from sqlalchemy import select, func, delete, desc +from database import get_session, AccountModel, AccountUsageRecordModel, init_db + +# 文件和路径处理 +from pathlib import Path + +# 时间处理 +from datetime import datetime + +# 异步和上下文管理 +import asyncio +from contextlib import asynccontextmanager + +# 系统和环境相关 +import os +import traceback +import uvicorn +from dotenv import load_dotenv + +# 日志和错误处理 +from logger import info, error + +# 自定义模块 +from cursor_pro_keep_alive import main as register_account +from tokenManager.cursor import Cursor + +# 并发和缓存 +import concurrent.futures +from functools import lru_cache + +# 配置参数 +from config import ( + MAX_ACCOUNTS, + REGISTRATION_INTERVAL, + API_HOST, + API_PORT, + API_DEBUG, + API_WORKERS, +) + +# 其他工具 +import json +import time + +# 全局状态追踪 +registration_status = { + "is_running": False, + "last_run": None, + "last_status": None, + "next_run": None, + "total_runs": 0, + "successful_runs": 0, + "failed_runs": 0, +} + +# 定义静态文件目录 +static_path = Path(__file__).parent / "static" +static_path.mkdir(exist_ok=True) # 确保目录存在 + +# 全局任务存储 +background_tasks = {"registration_task": None} + + +# 添加lifespan管理器,在应用启动时初始化数据库 +@asynccontextmanager +async def lifespan(app: FastAPI): + # 启动时初始化数据库 + await init_db() + info(f'服务已启动! \n 首页地址:http://127.0.0.1:{API_PORT}/') + yield + # 关闭时的清理操作 + info("应用程序已关闭!") + + +app = FastAPI( + title="Cursor Account API", + description="API for managing Cursor accounts", + version="1.0.0", + docs_url="/docs", + redoc_url="/redoc", + lifespan=lifespan, + debug=API_DEBUG, +) + + +# 挂载静态文件目录 +app.mount("/static", StaticFiles(directory=str(static_path)), name="static") + +# 添加CORS中间件 +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +class Account(BaseModel): + email: str + password: Optional[str] = None + token: str + user: str + usage_limit: Optional[str] = None + created_at: Optional[str] = None + status: str = "active" # 默认为"active" + id: Optional[int] = None # 添加id字段,可选 + + class Config: + from_attributes = True + + +class AccountResponse(BaseModel): + success: bool + data: Optional[Account] = None + message: str = "" + + +async def get_active_account_count() -> int: + """获取当前账号总数""" + async with get_session() as session: + result = await session.execute( + select(func.count()) + .select_from(AccountModel) + .where(AccountModel.status == "active") + ) + return result.scalar() + + +async def get_account_count() -> int: + """获取当前账号总数""" + async with get_session() as session: + result = await session.execute(select(func.count()).select_from(AccountModel)) + return result.scalar() + + +async def run_registration(): + """运行注册脚本""" + global registration_status + browser_manager = None + + try: + info("注册任务开始运行") + + while registration_status["is_running"]: + try: + count = await get_active_account_count() + info(f"当前数据库已激活账号数: {count}") + + if count >= MAX_ACCOUNTS: + # 修改:不再结束任务,而是进入监控模式 + info(f"已达到最大账号数量 ({count}/{MAX_ACCOUNTS}),进入监控模式") + registration_status["last_status"] = "monitoring" + + # 等待检测间隔时间 + next_check = datetime.now().timestamp() + REGISTRATION_INTERVAL + registration_status["next_run"] = next_check + info(f"将在 {REGISTRATION_INTERVAL} 秒后重新检查账号数量") + await asyncio.sleep(REGISTRATION_INTERVAL) + + # 跳过当前循环的剩余部分,继续下一次循环检查 + continue + + info(f"开始注册尝试 (当前账号数: {count}/{MAX_ACCOUNTS})") + registration_status["last_run"] = datetime.now().isoformat() + registration_status["total_runs"] += 1 + + # 调用注册函数 + try: + success = await asyncio.get_event_loop().run_in_executor( + None, register_account + ) + + if success: + registration_status["successful_runs"] += 1 + registration_status["last_status"] = "success" + info("注册成功") + else: + registration_status["failed_runs"] += 1 + registration_status["last_status"] = "failed" + info("注册失败") + except SystemExit: + # 捕获 SystemExit 异常,这是注册脚本正常退出的方式 + info("注册脚本正常退出") + if registration_status["last_status"] != "error": + registration_status["last_status"] = "completed" + except Exception as e: + error(f"注册过程执行出错: {str(e)}") + error(traceback.format_exc()) + registration_status["failed_runs"] += 1 + registration_status["last_status"] = "error" + + # 更新下次运行时间 + next_run = datetime.now().timestamp() + REGISTRATION_INTERVAL + registration_status["next_run"] = next_run + + info(f"等待 {REGISTRATION_INTERVAL} 秒后进行下一次尝试") + await asyncio.sleep(REGISTRATION_INTERVAL) + + except asyncio.CancelledError: + info("注册迭代被取消") + raise + except Exception as e: + registration_status["failed_runs"] += 1 + registration_status["last_status"] = "error" + error(f"注册过程出错: {str(e)}") + error(traceback.format_exc()) + if not registration_status["is_running"]: + break + await asyncio.sleep(REGISTRATION_INTERVAL) + except asyncio.CancelledError: + info("注册任务被取消") + raise + except Exception as e: + error(f"注册任务致命错误: {str(e)}") + error(traceback.format_exc()) + raise + finally: + registration_status["is_running"] = False + if browser_manager: + try: + browser_manager.quit() + except Exception as e: + error(f"清理浏览器资源时出错: {str(e)}") + error(traceback.format_exc()) + + +@app.get("/", tags=["UI"]) +async def serve_index(): + """提供Web UI界面""" + index_path = Path(__file__).parent / "index.html" + return FileResponse(index_path) + + +@app.get("/general", tags=["General"]) +async def root(): + """API根路径,返回API信息""" + try: + # 获取当前账号数量和使用情况 + async with get_session() as session: + result = await session.execute(select(AccountModel)) + accounts = result.scalars().all() + + usage_info = [] + total_balance = 0 + active_accounts = 0 + + for acc in accounts: + remaining_balance = Cursor.get_remaining_balance(acc.user, acc.token) + remaining_days = Cursor.get_trial_remaining_days(acc.user, acc.token) + + if remaining_balance is not None and remaining_balance > 0: + active_accounts += 1 + total_balance += remaining_balance + + usage_info.append( + { + "email": acc.email, + "balance": remaining_balance, + "days": remaining_days, + "status": ( + "active" + if remaining_balance is not None and remaining_balance > 0 + else "inactive" + ), + } + ) + + return { + "service": { + "name": "Cursor Account API", + "version": "1.0.0", + "status": "running", + "description": "API for managing Cursor Pro accounts and automatic registration", + }, + "statistics": { + "total_accounts": len(accounts), + "active_accounts": active_accounts, + "total_remaining_balance": total_balance, + "max_accounts": MAX_ACCOUNTS, + "remaining_slots": MAX_ACCOUNTS - len(accounts), + "registration_interval": f"{REGISTRATION_INTERVAL} seconds", + }, + "accounts_info": usage_info, # 添加账号详细信息 + "registration_status": { + "is_running": registration_status["is_running"], + "last_run": registration_status["last_run"], + "last_status": registration_status["last_status"], + "next_run": registration_status["next_run"], + "statistics": { + "total_runs": registration_status["total_runs"], + "successful_runs": registration_status["successful_runs"], + "failed_runs": registration_status["failed_runs"], + "success_rate": ( + f"{(registration_status['successful_runs'] / registration_status['total_runs'] * 100):.1f}%" + if registration_status["total_runs"] > 0 + else "N/A" + ), + }, + }, + "endpoints": { + "documentation": {"swagger": "/docs", "redoc": "/redoc"}, + "health": { + "check": "/health", + "registration_status": "/registration/status", + }, + "accounts": { + "list_all": "/accounts", + "random": "/account/random", + "create": {"path": "/account", "method": "POST"}, + "delete": {"path": "/account/{email}", "method": "DELETE"}, + "usage": { + "path": "/account/{email}/usage", + "method": "GET", + "description": "Get account usage by email", + }, + }, + "registration": { + "start": {"path": "/registration/start", "method": "GET"}, + "stop": {"path": "/registration/stop", "method": "POST"}, + "status": {"path": "/registration/status", "method": "GET"}, + }, + "usage": {"check": {"path": "/usage", "method": "GET"}}, + "clean": { + "run": { + "path": "/clean", + "method": "POST", + "params": {"clean_type": ["check", "disable", "delete"]}, + } + }, + }, + "support": { + "github": "https://github.com/Elawen-Carl/cursor-account-api", + "author": "Elawen Carl", + "contact": "elawencarl@gmail.com", + }, + "timestamp": datetime.now().isoformat(), + } + except Exception as e: + error(f"根端点错误: {str(e)}") + error(traceback.format_exc()) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Error fetching API information", + ) + + +@app.get("/health", tags=["General"]) +async def health_check(): + """健康检查端点""" + return {"status": "healthy"} + + +@app.get("/accounts", tags=["Accounts"]) +async def get_accounts( + page: int = 1, + per_page: int = 10, + search: Optional[str] = None, + sort_by: str = "created_at", # 新增排序字段参数 + order: str = "desc" # 新增排序方向参数 +): + """获取所有账号列表,支持分页、搜索和排序""" + try: + async with get_session() as session: + # 验证排序参数 + valid_sort_fields = {"id", "email", "created_at", "usage_limit"} + valid_orders = {"asc", "desc"} + + if sort_by not in valid_sort_fields: + sort_by = "created_at" # 默认排序字段 + if order not in valid_orders: + order = "desc" # 默认排序方向 + + # 构建基本查询 + query = select(AccountModel) + + # 应用排序 + sort_field = getattr(AccountModel, sort_by) + if order == "desc": + query = query.order_by(desc(sort_field)) + else: + query = query.order_by(sort_field) + + # 如果有搜索参数 + if search: + search = f"%{search}%" + query = query.where(AccountModel.email.like(search)) + + # 计算总记录数 + count_query = select(func.count()).select_from(AccountModel) + if search: + count_query = count_query.where(AccountModel.email.like(search)) + total_count = await session.scalar(count_query) + + # 计算分页 + total_pages = (total_count + per_page - 1) // per_page # 向上取整 + + # 应用分页 + query = query.offset((page - 1) * per_page).limit(per_page) + + # 执行查询 + result = await session.execute(query) + accounts = result.scalars().all() + + # 构建分页响应 + return { + "success": True, + "data": accounts, + "pagination": { + "page": page, + "per_page": per_page, + "total_count": total_count, + "total_pages": total_pages + }, + "sort": { + "field": sort_by, + "order": order + } + } + except Exception as e: + error(f"获取账号列表失败: {str(e)}") + error(traceback.format_exc()) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"获取账号列表失败: {str(e)}", + ) + + +@app.get("/account/random", response_model=AccountResponse, tags=["Accounts"]) +async def get_random_account(): + """随机获取一个可用的账号和token""" + try: + async with get_session() as session: + result = await session.execute( + select(AccountModel).order_by(func.random()).limit(1) + ) + account = result.scalar_one_or_none() + + if not account: + return AccountResponse(success=False, message="No accounts available") + + return AccountResponse(success=True, data=Account.from_orm(account)) + except Exception as e: + error(f"获取随机账号失败: {str(e)}") + error(traceback.format_exc()) + raise HTTPException(status_code=500, detail="Internal server error") + + +@app.post("/account", response_model=AccountResponse, tags=["Accounts"]) +async def create_account(account: Account): + """创建新账号""" + try: + async with get_session() as session: + db_account = AccountModel( + email=account.email, + password=account.password, + token=account.token, + usage_limit=account.usage_limit, + created_at=account.created_at, + ) + session.add(db_account) + await session.commit() + return AccountResponse( + success=True, data=account, message="Account created successfully" + ) + except Exception as e: + error(f"创建账号失败: {str(e)}") + error(traceback.format_exc()) + return AccountResponse( + success=False, message=f"Failed to create account: {str(e)}" + ) + + +@app.delete("/account/{email}", response_model=AccountResponse, tags=["Accounts"]) +async def delete_account(email: str, hard_delete: bool = False): + """删除或停用指定邮箱的账号 + + 如果 hard_delete=True,则物理删除账号 + 否则仅将状态设置为'deleted' + """ + try: + async with get_session() as session: + # 先检查账号是否存在 + result = await session.execute( + select(AccountModel).where(AccountModel.email == email) + ) + account = result.scalar_one_or_none() + + if not account: + return AccountResponse(success=False, message=f"账号 {email} 不存在") + + if hard_delete: + # 物理删除账号 + await session.execute( + delete(AccountModel).where(AccountModel.email == email) + ) + delete_message = f"账号 {email} 已永久删除" + else: + # 逻辑删除:将状态更新为'deleted' + account.status = "deleted" + delete_message = f"账号 {email} 已标记为删除状态" + + await session.commit() + + return AccountResponse(success=True, message=delete_message) + except Exception as e: + error(f"删除账号失败: {str(e)}") + error(traceback.format_exc()) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"删除账号失败: {str(e)}", + ) + + +# 添加状态更新的请求体模型 +class StatusUpdate(BaseModel): + status: str + + +@app.put("/account/id/{id}/status", response_model=AccountResponse, tags=["Accounts"]) +async def update_account_status(id: str, update: StatusUpdate): + """更新账号状态 + + 可选状态: active (正常), disabled (停用), deleted (已删除) + """ + # 使用update.status替代原先的status参数 + try: + # 验证状态值 + valid_statuses = ["active", "disabled", "deleted"] + if update.status not in valid_statuses: + return AccountResponse( + success=False, + message=f"无效的状态值。允许的值: {', '.join(valid_statuses)}", + ) + + async with get_session() as session: + # 通过邮箱查询账号 + result = await session.execute( + select(AccountModel).where(AccountModel.id == id) + ) + account = result.scalar_one_or_none() + + if not account: + return AccountResponse( + success=False, message=f"邮箱为 {email} 的账号不存在" + ) + + # 更新状态 + account.status = update.status + await session.commit() + + return AccountResponse( + success=True, + message=f"账号 {account.email} 状态已更新为 '{update.status}'", + ) + except Exception as e: + error(f"通过邮箱更新账号状态失败: {str(e)}") + error(traceback.format_exc()) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"更新账号状态失败: {str(e)}", + ) + + +@app.get("/registration/start", tags=["Registration"]) +async def start_registration(): + """手动启动注册任务""" + info("手动启动注册任务") + global background_tasks, registration_status + try: + # 检查是否已达到最大账号数 + count = await get_active_account_count() + + # 检查任务是否已在运行 + if ( + background_tasks["registration_task"] + and not background_tasks["registration_task"].done() + ): + # 确定当前状态 + current_status = ( + "monitoring" + if registration_status["last_status"] == "monitoring" + else "running" + ) + + status_message = ( + f"注册任务已在运行中 (状态: {current_status})" + if current_status == "running" + else f"已达到最大账号数量({count}/{MAX_ACCOUNTS}),正在监控账号状态,当账号数量减少时将自动继续注册" + ) + + info(f"注册请求被忽略 - 任务已在{current_status}状态") + return { + "success": True, + "message": status_message, + "status": { + "is_running": registration_status["is_running"], + "last_run": registration_status["last_run"], + "next_run": ( + datetime.fromtimestamp( + registration_status["next_run"] + ).isoformat() + if registration_status["next_run"] + else None + ), + "last_status": registration_status["last_status"], + "current_count": count, + "max_accounts": MAX_ACCOUNTS, + }, + } + + # 重置注册状态 + registration_status.update( + { + "is_running": True, + "last_status": "starting", + "last_run": datetime.now().isoformat(), + "next_run": datetime.now().timestamp() + REGISTRATION_INTERVAL, + "total_runs": 0, + "successful_runs": 0, + "failed_runs": 0, + } + ) + + # 创建并启动新任务 + loop = asyncio.get_running_loop() + task = loop.create_task(run_registration()) + background_tasks["registration_task"] = task + + # 添加任务完成回调 + def task_done_callback(task): + try: + task.result() # 这将重新引发任何未处理的异常 + except asyncio.CancelledError: + info("注册任务被取消") + registration_status["last_status"] = "cancelled" + except Exception as e: + error(f"注册任务失败: {str(e)}") + error(traceback.format_exc()) + registration_status["last_status"] = "error" + finally: + if registration_status["is_running"]: # 只有在任务仍在运行时才更新状态 + registration_status["is_running"] = False + background_tasks["registration_task"] = None + + task.add_done_callback(task_done_callback) + info("手动启动注册任务") + + # 等待任务实际开始运行 + await asyncio.sleep(1) + + # 检查任务是否成功启动 + if task.done(): + try: + task.result() # 如果任务已完成,检查是否有异常 + except Exception as e: + error(f"注册任务启动失败: {str(e)}") + error(traceback.format_exc()) + registration_status["is_running"] = False + registration_status["last_status"] = "error" + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Failed to start registration task: {str(e)}", + ) + + # 检查是否已达到最大账号数,预先设置为监控模式 + if count >= MAX_ACCOUNTS: + registration_status["last_status"] = "monitoring" + status_message = f"已达到最大账号数量({count}/{MAX_ACCOUNTS}),进入监控模式,当账号数量减少时将自动继续注册" + else: + status_message = "注册任务启动成功" + + return { + "success": True, + "message": status_message, + "status": { + "is_running": registration_status["is_running"], + "last_run": registration_status["last_run"], + "next_run": datetime.fromtimestamp( + registration_status["next_run"] + ).isoformat(), + "last_status": registration_status["last_status"], + "current_count": count, + "max_accounts": MAX_ACCOUNTS, + }, + } + except Exception as e: + error(f"启动注册任务失败: {str(e)}") + error(traceback.format_exc()) + registration_status["is_running"] = False + registration_status["last_status"] = "error" + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Failed to start registration task: {str(e)}", + ) + + +@app.get("/registration/stop", tags=["Registration"]) +async def stop_registration(): + """手动停止注册任务""" + global background_tasks + try: + if ( + not background_tasks["registration_task"] + or background_tasks["registration_task"].done() + ): + return {"success": False, "message": "No running registration task found"} + + background_tasks["registration_task"].cancel() + try: + await background_tasks["registration_task"] + except asyncio.CancelledError: + info("注册任务被取消") + + background_tasks["registration_task"] = None + registration_status["is_running"] = False + registration_status["last_status"] = "manually stopped" + + return {"success": True, "message": "Registration task stopped successfully"} + except Exception as e: + error(f"停止注册任务失败: {str(e)}") + error(traceback.format_exc()) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Failed to stop registration task: {str(e)}", + ) + + +@app.get("/registration/status", tags=["Registration"]) +async def get_registration_status(): + """获取注册状态""" + try: + count = await get_account_count() + active_count = await get_active_account_count() # 添加获取活跃账号数 + + # 更新任务状态逻辑 + if ( + background_tasks["registration_task"] + and not background_tasks["registration_task"].done() + ): + if registration_status["last_status"] == "monitoring": + task_status = "monitoring" # 新增监控状态 + else: + task_status = "running" + else: + task_status = "stopped" + + status_info = { + "current_count": count, + "active_count": active_count, # 添加活跃账号数 + "max_accounts": MAX_ACCOUNTS, + "is_registration_active": active_count < MAX_ACCOUNTS, + "remaining_slots": MAX_ACCOUNTS - active_count, + "task_status": task_status, + "registration_details": { + "is_running": registration_status["is_running"], + "last_run": registration_status["last_run"], + "last_status": registration_status["last_status"], + "next_run": registration_status["next_run"], + "statistics": { + "total_runs": registration_status["total_runs"], + "successful_runs": registration_status["successful_runs"], + "failed_runs": registration_status["failed_runs"], + "success_rate": ( + f"{(registration_status['successful_runs'] / registration_status['total_runs'] * 100):.1f}%" + if registration_status["total_runs"] > 0 + else "N/A" + ), + }, + }, + } + + # 添加状态解释信息 + if task_status == "monitoring": + status_info["status_message"] = ( + f"已达到最大账号数量({active_count}/{MAX_ACCOUNTS}),正在监控账号状态,当账号数量减少时将自动继续注册" + ) + elif task_status == "running": + status_info["status_message"] = ( + f"正在执行注册流程,当前账号数:{active_count}/{MAX_ACCOUNTS}" + ) + else: + status_info["status_message"] = "注册任务未运行" + + # info(f"请求注册状态 (当前账号数: {count}, 活跃账号数: {active_count}, 状态: {task_status})") + return status_info + + except Exception as e: + error(f"获取注册状态失败: {str(e)}") + error(traceback.format_exc()) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Failed to get registration status: {str(e)}", + ) + + +# 自定义异常处理 +@app.exception_handler(HTTPException) +async def http_exception_handler(request, exc): + error(f"HTTP错误发生: {exc.detail}") + return JSONResponse( + status_code=exc.status_code, content={"success": False, "message": exc.detail} + ) + + +@app.exception_handler(Exception) +async def general_exception_handler(request, exc): + error(f"意外错误发生: {str(exc)}") + error(f"错误详情: {traceback.format_exc()}") + return JSONResponse( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + content={ + "success": False, + "message": "Internal server error occurred", + "detail": str(exc) if app.debug else None, + }, + ) + + +# 添加缓存装饰器 +@lru_cache(maxsize=100) +def get_account_status(user: str, token: str, timestamp: int): + """缓存10分钟内的账号状态""" + balance = Cursor.get_remaining_balance(user, token) + days = Cursor.get_trial_remaining_days(user, token) + return { + "balance": balance, + "days": days, + "status": "active" if balance is not None and balance > 0 else "inactive", + } + + +# 修改 check_usage 接口 +@app.get("/usage") +async def check_usage(): + """ + 获取所有账号的使用量信息 + + 该接口会并发查询所有账号的余额和剩余天数,并返回汇总信息 + 使用了缓存机制避免频繁请求API,缓存时间为10分钟 + + 返回: + - total_accounts: 总账号数量 + - usage_info: 每个账号的详细使用量信息列表 + - summary: 账号状态汇总信息,包括活跃账号数、非活跃账号数和总剩余额度 + """ + try: + async with get_session() as session: + # 从数据库获取所有账号 + result = await session.execute(select(AccountModel)) + accounts = result.scalars().all() + + # 使用当前时间的10分钟间隔作为缓存key + # 将时间戳除以600(10分钟)取整,作为缓存标识 + cache_timestamp = int(datetime.now().timestamp() / 600) + + # 使用线程池并发获取账号状态,最多10个并发线程 + # 避免串行请求API导致接口响应过慢 + with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: + # 为每个账号创建一个异步任务 + futures = [ + executor.submit( + get_account_status, acc.user, acc.token, cache_timestamp + ) + for acc in accounts + ] + + # 收集每个账号的使用量信息 + usage_info = [] + for acc, future in zip(accounts, futures): + status = future.result() + usage_info.append( + { + "email": acc.email, + "usage_limit": status["balance"], # 剩余额度 + "remaining_days": status["days"], # 剩余天数 + "status": status["status"], # 账号状态 + } + ) + + # 返回汇总信息 + return { + "total_accounts": len(accounts), # 总账号数 + "usage_info": usage_info, # 详细使用量信息 + "summary": { + # 统计活跃账号数量 + "active_accounts": sum( + 1 for info in usage_info if info["status"] == "active" + ), + # 统计非活跃账号数量 + "inactive_accounts": sum( + 1 for info in usage_info if info["status"] == "inactive" + ), + # 计算所有账号的总剩余额度 + "total_remaining_balance": sum( + info["usage_limit"] or 0 for info in usage_info + ), + }, + } + except Exception as e: + # 记录错误日志 + error(f"检查使用量失败: {str(e)}") + error(traceback.format_exc()) + # 抛出HTTP异常 + raise HTTPException(status_code=500, detail=str(e)) + + +@app.get("/account/{email}/usage", tags=["Accounts"]) +async def get_account_usage(email: str): + """根据邮箱查询账户使用量并更新数据库""" + try: + async with get_session() as session: + # 查询指定邮箱的账号 + result = await session.execute( + select(AccountModel).where(AccountModel.email == email) + ) + account = result.scalar_one_or_none() + + if not account: + raise HTTPException( + status_code=404, detail=f"Account with email {email} not found" + ) + + # 获取账号使用量 + remaining_balance = Cursor.get_remaining_balance( + account.user, account.token + ) + remaining_days = Cursor.get_trial_remaining_days( + account.user, account.token + ) + + # 计算总额度和已使用额度 + total_limit = 150 # 默认总额度 + used_limit = 0 + + if remaining_balance is not None: + used_limit = total_limit - remaining_balance + if remaining_days is not None and remaining_days == 0: + account.status = "disabled" + + # 更新数据库中的usage_limit字段 + account.usage_limit = str(remaining_balance) + await session.commit() + db_updated = True + else: + db_updated = False + + return { + "success": True, + "email": account.email, + "usage": { + "remaining_balance": remaining_balance, + "total_limit": total_limit, + "used_limit": used_limit, + "remaining_days": remaining_days, + "status": ( + "active" + if remaining_balance is not None and remaining_balance > 0 + else "inactive" + ), + }, + "db_updated": db_updated, + "timestamp": datetime.now().isoformat(), + } + + except HTTPException: + raise + except Exception as e: + error(f"查询账号使用量失败: {str(e)}") + error(traceback.format_exc()) + return {"success": False, "message": f"Failed to get account usage: {str(e)}"} + + +# 添加通过ID删除账号的API +@app.delete("/account/id/{id}", response_model=AccountResponse, tags=["Accounts"]) +async def delete_account_by_id(id: int, hard_delete: bool = False): + """通过ID删除或停用账号 + + 如果 hard_delete=True,则物理删除账号 + 否则仅将状态设置为'deleted' + """ + try: + async with get_session() as session: + # 通过ID查询账号 + result = await session.execute( + select(AccountModel).where(AccountModel.id == id) + ) + account = result.scalar_one_or_none() + + if not account: + return AccountResponse(success=False, message=f"ID为 {id} 的账号不存在") + + email = account.email # 保存邮箱以在响应中显示 + + if hard_delete: + # 物理删除账号 + await session.execute(delete(AccountModel).where(AccountModel.id == id)) + delete_message = f"账号 {email} (ID: {id}) 已永久删除" + else: + # 逻辑删除:将状态更新为'deleted' + account.status = "deleted" + delete_message = f"账号 {email} (ID: {id}) 已标记为删除状态" + + await session.commit() + + return AccountResponse(success=True, message=delete_message) + except Exception as e: + error(f"通过ID删除账号失败: {str(e)}") + error(traceback.format_exc()) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"删除账号失败: {str(e)}", + ) + +# 添加导出账号列表功能 +@app.get("/accounts/export", tags=["Accounts"]) +async def export_accounts(): + """导出所有账号为JSON文件""" + try: + async with get_session() as session: + query = select(AccountModel).order_by(desc(AccountModel.created_at)) + result = await session.execute(query) + accounts = result.scalars().all() + + # 转换为可序列化的数据 + accounts_data = [] + for account in accounts: + account_dict = { + "id": account.id, + "email": account.email, + "password": account.password, + "token": account.token, + "user": account.user, + "usage_limit": account.usage_limit, + "created_at": account.created_at, + "status": account.status + } + accounts_data.append(account_dict) + + # 创建响应 + content = json.dumps(accounts_data, ensure_ascii=False, indent=2) + response = Response(content=content) + response.headers["Content-Disposition"] = "attachment; filename=cursor_accounts.json" + response.headers["Content-Type"] = "application/json" + + return response + + except Exception as e: + error(f"导出账号失败: {str(e)}") + error(traceback.format_exc()) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"导出账号失败: {str(e)}", + ) + +# 添加导入账号列表功能 +@app.post("/accounts/import", tags=["Accounts"]) +async def import_accounts(file: UploadFile): + """从JSON文件导入账号""" + try: + # 读取上传的文件内容 + content = await file.read() + + # 解析JSON数据 + try: + accounts_data = json.loads(content.decode("utf-8")) + except json.JSONDecodeError: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="无效的JSON文件格式", + ) + + # 验证数据结构 + if not isinstance(accounts_data, list): + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="JSON数据必须是账号对象的数组", + ) + + # 导入计数器 + imported = 0 + updated = 0 + skipped = 0 + + async with get_session() as session: + for account_data in accounts_data: + # 提取必要字段,提供默认值 + email = account_data.get("email") + if not email: + skipped += 1 + continue + + # 检查账号是否已存在 + query = select(AccountModel).where(AccountModel.email == email) + result = await session.execute(query) + existing_account = result.scalar_one_or_none() + + if existing_account: + # 更新现有账号 + existing_account.password = account_data.get("password", existing_account.password) + existing_account.token = account_data.get("token", existing_account.token) + existing_account.user = account_data.get("user", existing_account.user) + existing_account.usage_limit = account_data.get("usage_limit", existing_account.usage_limit) + existing_account.status = account_data.get("status", existing_account.status) + updated += 1 + else: + # 创建新账号 + new_account = AccountModel( + id=account_data.get("id", int(time.time() * 1000)), + email=email, + password=account_data.get("password", ""), + token=account_data.get("token", ""), + user=account_data.get("user", ""), + usage_limit=account_data.get("usage_limit", ""), + created_at=account_data.get("created_at", datetime.now().strftime("%Y-%m-%d %H:%M")), + status=account_data.get("status", "active") + ) + session.add(new_account) + imported += 1 + + # 提交所有更改 + await session.commit() + + return { + "success": True, + "message": f"导入完成: 新增 {imported} 个账号, 更新 {updated} 个账号, 跳过 {skipped} 个无效记录", + } + + except HTTPException: + raise + except Exception as e: + error(f"导入账号失败: {str(e)}") + error(traceback.format_exc()) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"导入账号失败: {str(e)}", + ) + +# 添加"使用Token"功能 +@app.post("/account/use-token/{id}", tags=["Accounts"]) +async def use_account_token(id: int, request: Request, reset_machine_id: bool = False): + """使用指定账号的Token更新Cursor认证,可选是否重置机器ID""" + try: + async with get_session() as session: + # 通过ID查询账号 + result = await session.execute( + select(AccountModel).where(AccountModel.id == id) + ) + account = result.scalar_one_or_none() + + if not account: + return {"success": False, "message": f"ID为 {id} 的账号不存在"} + + # 调用CursorAuthManager更新认证 + from cursor_auth_manager import CursorAuthManager + + auth_manager = CursorAuthManager() + success = auth_manager.update_auth( + email=account.email, + access_token=account.token, + refresh_token=account.token + ) + + # 仅在用户选择时才重置机器ID + patch_success = False + if reset_machine_id: + from cursor_shadow_patcher import CursorShadowPatcher + resetter = CursorShadowPatcher() + patch_success = resetter.reset_machine_ids() + + # 更新返回消息 + if success and reset_machine_id and patch_success: + return { + "success": True, + "message": f"成功使用账号 {account.email} 的Token并重置了机器ID", + } + elif success and reset_machine_id and not patch_success: + return { + "success": True, + "message": f"成功使用账号 {account.email} 的Token,但机器ID重置失败", + } + elif success: + return { + "success": True, + "message": f"成功使用账号 {account.email} 的Token(未重置机器ID)", + } + else: + return {"success": False, "message": "Token更新失败"} + + except Exception as e: + error(f"使用账号Token失败: {str(e)}") + error(traceback.format_exc()) + return {"success": False, "message": f"使用Token失败: {str(e)}"} + +# 添加获取账号使用记录接口 +@app.get("/account/{id}/usage-records", tags=["Accounts"]) +async def get_account_usage_records(id: int): + """获取指定账号的使用记录""" + try: + async with get_session() as session: + # 通过ID查询账号 + result = await session.execute( + select(AccountModel).where(AccountModel.id == id) + ) + account = result.scalar_one_or_none() + + if not account: + return {"success": False, "message": f"ID为 {id} 的账号不存在"} + + # 查询使用记录 + result = await session.execute( + select(AccountUsageRecordModel) + .where(AccountUsageRecordModel.account_id == id) + .order_by(desc(AccountUsageRecordModel.created_at)) + ) + + records = result.scalars().all() + + # 转换记录为字典列表 + records_list = [] + for record in records: + records_list.append({ + "id": record.id, + "account_id": record.account_id, + "email": record.email, + "ip": record.ip, + "user_agent": record.user_agent, + "created_at": record.created_at + }) + + return { + "success": True, + "records": records_list + } + + except Exception as e: + error(f"获取账号使用记录失败: {str(e)}") + error(traceback.format_exc()) + return {"success": False, "message": f"获取账号使用记录失败: {str(e)}"} + +# 添加"重置设备id"功能 +@app.get("/reset-machine", tags=["System"]) +async def reset_machine(): + """重置设备id""" + try: + # 重置Cursor的机器ID + from cursor_shadow_patcher import CursorShadowPatcher + + resetter = CursorShadowPatcher() + patch_success = resetter.reset_machine_ids() + if patch_success: + return { + "success": True, + "message": f"成功重置了机器ID", + } + else: + return {"success": False, "message": "重置机器ID失败"} + except Exception as e: + error(f"重置机器ID失败: {str(e)}") + error(traceback.format_exc()) + return {"success": False, "message": f"重置机器ID失败: {str(e)}"} + + +# 添加配置相关模型 +class ConfigModel(BaseModel): + BROWSER_HEADLESS: bool + DYNAMIC_USERAGENT: Optional[bool] = False + BROWSER_USER_AGENT: str + MAX_ACCOUNTS: int + EMAIL_DOMAINS: str + EMAIL_USERNAME: str + EMAIL_PIN: str + BROWSER_PATH: Optional[str] = None + CURSOR_PATH: Optional[str] = None + USE_PROXY: Optional[bool] = False + PROXY_TYPE: Optional[str] = None + PROXY_HOST: Optional[str] = None + PROXY_PORT: Optional[str] = None + PROXY_TIMEOUT: Optional[int] = None + PROXY_USERNAME: Optional[str] = None + PROXY_PASSWORD: Optional[str] = None + EMAIL_CODE_TYPE: str = "AUTO" # 默认值为AUTO + + +# 获取配置端点 +@app.get("/config", tags=["Config"]) +async def get_config(): + """获取当前系统配置""" + try: + # 重新加载配置以确保获取最新值 + load_dotenv() + + config = { + "BROWSER_HEADLESS": os.getenv("BROWSER_HEADLESS", "True").lower() == "true", + "BROWSER_USER_AGENT": os.getenv("BROWSER_USER_AGENT", ""), + "MAX_ACCOUNTS": int(os.getenv("MAX_ACCOUNTS", "10")), + "EMAIL_TYPE": os.getenv("EMAIL_TYPE", "tempemail"), + "EMAIL_PROXY_ENABLED": os.getenv("EMAIL_PROXY_ENABLED", "False").lower() == "true", + "EMAIL_PROXY_ADDRESS": os.getenv("EMAIL_PROXY_ADDRESS", ""), + "EMAIL_API": os.getenv("EMAIL_API", ""), + "EMAIL_DOMAINS": os.getenv("EMAIL_DOMAINS", ""), + "EMAIL_USERNAME": os.getenv("EMAIL_USERNAME", ""), + "EMAIL_DOMAIN": os.getenv("EMAIL_DOMAIN", ""), + "EMAIL_PIN": os.getenv("EMAIL_PIN", ""), + "EMAIL_CODE_TYPE": os.getenv("EMAIL_CODE_TYPE", "AUTO"), + "BROWSER_PATH": os.getenv("BROWSER_PATH", ""), + "CURSOR_PATH": os.getenv("CURSOR_PATH", ""), + "DYNAMIC_USERAGENT": os.getenv("DYNAMIC_USERAGENT", "False").lower() == "true", + # 添加代理配置 + "USE_PROXY": os.getenv("USE_PROXY", "False"), + "PROXY_TYPE": os.getenv("PROXY_TYPE", "http"), + "PROXY_HOST": os.getenv("PROXY_HOST", ""), + "PROXY_PORT": os.getenv("PROXY_PORT", ""), + "PROXY_TIMEOUT": os.getenv("PROXY_TIMEOUT", "10"), + "PROXY_USERNAME": os.getenv("PROXY_USERNAME", ""), + "PROXY_PASSWORD": os.getenv("PROXY_PASSWORD", ""), + } + + return {"success": True, "data": config} + except Exception as e: + error(f"获取配置失败: {str(e)}") + error(traceback.format_exc()) + return {"success": False, "message": f"获取配置失败: {str(e)}"} + + +# 更新配置端点 +@app.post("/config", tags=["Config"]) +async def update_config(config: ConfigModel): + """更新配置""" + try: + # 获取.env文件路径 + env_path = Path(__file__).parent / ".env" + + # 读取当前.env文件内容 + current_lines = [] + if env_path.exists(): + with open(env_path, "r", encoding="utf-8") as f: + current_lines = f.readlines() + + # 构建配置字典 - 修正:直接使用模型属性而非get方法 + config_dict = { + "BROWSER_HEADLESS": str(config.BROWSER_HEADLESS), + "DYNAMIC_USERAGENT": str(config.DYNAMIC_USERAGENT), + "BROWSER_USER_AGENT": config.BROWSER_USER_AGENT, + "MAX_ACCOUNTS": str(config.MAX_ACCOUNTS), + "EMAIL_DOMAINS": config.EMAIL_DOMAINS, + "EMAIL_USERNAME": config.EMAIL_USERNAME, + "EMAIL_PIN": config.EMAIL_PIN, + "EMAIL_CODE_TYPE": config.EMAIL_CODE_TYPE, + # 添加代理配置 + "USE_PROXY": str(config.USE_PROXY), + "PROXY_TYPE": config.PROXY_TYPE, + "PROXY_HOST": config.PROXY_HOST, + "PROXY_PORT": config.PROXY_PORT, + "PROXY_TIMEOUT": str(config.PROXY_TIMEOUT), + "PROXY_USERNAME": config.PROXY_USERNAME, + "PROXY_PASSWORD": config.PROXY_PASSWORD, + } + + # 添加可选配置(如果提供) + if config.BROWSER_PATH: + config_dict["BROWSER_PATH"] = config.BROWSER_PATH + if config.CURSOR_PATH: + config_dict["CURSOR_PATH"] = config.CURSOR_PATH + + # 处理现有行或创建新行 + updated_lines = [] + updated_keys = set() + + for line in current_lines: + line = line.strip() + if not line or line.startswith("#"): + updated_lines.append(line) + continue + + key, value = line.split("=", 1) if "=" in line else (line, "") + key = key.strip() + + if key in config_dict: + updated_lines.append(f"{key}={config_dict[key]}") + updated_keys.add(key) + else: + updated_lines.append(line) + + # 添加未更新的配置项 + for key, value in config_dict.items(): + if key not in updated_keys and value: + updated_lines.append(f"{key}={value}") + + # 写入更新后的配置 + with open(env_path, "w", encoding="utf-8") as f: + f.write("\n".join(updated_lines)) + + # 重新加载环境变量 + load_dotenv(override=True) + + return {"success": True, "message": "配置已更新"} + except Exception as e: + error(f"更新配置失败: {str(e)}") + error(traceback.format_exc()) + return {"success": False, "message": f"更新配置失败: {str(e)}"} + + +# 优化重启API功能,解决卡住问题 +@app.post("/restart", tags=["System"]) +async def restart_service(): + """重启应用服务""" + try: + info("收到重启服务请求") + + # 使用更简单的重启方法 - 通过reload环境变量触发uvicorn重载 + # 1. 修改.env文件,添加/更新一个时间戳,触发热重载 + env_path = os.path.join(os.getcwd(), ".env") + timestamp = str(int(time.time())) + + # 读取现有.env文件 + if os.path.exists(env_path): + with open(env_path, "r", encoding="utf-8") as f: + env_lines = f.read().splitlines() + else: + env_lines = [] + + # 更新或添加RESTART_TIMESTAMP变量 + timestamp_found = False + for i, line in enumerate(env_lines): + if line.startswith("RESTART_TIMESTAMP="): + env_lines[i] = f"RESTART_TIMESTAMP={timestamp}" + timestamp_found = True + break + + if not timestamp_found: + env_lines.append(f"RESTART_TIMESTAMP={timestamp}") + + # 写回.env文件 + with open(env_path, "w", encoding="utf-8") as f: + f.write("\n".join(env_lines)) + + info(f"已更新重启时间戳: {timestamp}") + + # 仅提示用户手动刷新页面 + return { + "success": True, + "message": "配置已更新,请手动刷新页面以应用更改。" + } + except Exception as e: + error(f"重启服务失败: {str(e)}") + error(traceback.format_exc()) + return {"success": False, "message": f"重启服务失败: {str(e)}"} + + +@app.post("/update_all_usage", tags=["Accounts"]) +async def update_all_accounts_usage(): + """更新所有账户的使用量信息""" + try: + async with get_session() as session: + # 查询所有账号 + result = await session.execute(select(AccountModel)) + accounts = result.scalars().all() + + updated_count = 0 + error_count = 0 + + for account in accounts: + try: + # 获取账号使用量 + remaining_balance = Cursor.get_remaining_balance( + account.user, account.token + ) + remaining_days = Cursor.get_trial_remaining_days( + account.user, account.token + ) + + # 更新数据库 + if remaining_balance is not None: + total_limit = 150 # 默认总额度 + used_limit = total_limit - remaining_balance + + if remaining_days is not None and remaining_days == 0: + account.status = "disabled" + + # 更新数据库中的usage_limit字段 + account.usage_limit = str(remaining_balance) + updated_count += 1 + else: + error_count += 1 + + except Exception as e: + error_count += 1 + logger.error(f"更新账户 {account.email} 失败: {str(e)}") + + # 提交所有更改 + await session.commit() + + return { + "success": True, + "message": f"成功更新 {updated_count} 个账户,失败 {error_count} 个" + } + + except Exception as e: + logger.error(f"批量更新账户余量失败: {str(e)}") + return {"success": False, "message": str(e)} + + +if __name__ == "__main__": + uvicorn.run( + "api:app", + host=API_HOST, + port=API_PORT, + reload=API_DEBUG, + access_log=True, + log_level="error", + workers=API_WORKERS, + loop="asyncio", # Windows下使用默认的asyncio + ) \ No newline at end of file diff --git a/api_module_documentation.md b/api_module_documentation.md new file mode 100644 index 0000000..1cd4671 --- /dev/null +++ b/api_module_documentation.md @@ -0,0 +1,167 @@ +# Module Documentation: api.py + +## 1. 概述 (Overview) + +`api.py` 文件实现了一个基于 FastAPI 的 Web 应用,其核心目的是提供一套 API 接口来管理 Cursor IDE 的账号。此应用不仅支持账号的增删改查、导入导出等基本管理功能,还集成了一个自动化的后台任务来注册新账号,直到达到预设的上限。此外,它还能跟踪账号的使用情况、管理系统配置,并提供与本地 Cursor 客户端集成的功能,如更新认证 Token 和重置机器ID。 + +主要技术栈包括: +* **FastAPI**: 用于构建高性能 API。 +* **SQLAlchemy**: 作为 ORM 与数据库进行异步交互。 +* **Pydantic**: 用于数据校验和 API 的请求/响应模型定义。 +* **Uvicorn**: 作为 ASGI 服务器运行应用。 +* **Asyncio**: 支持异步操作和并发任务,特别是后台注册进程。 + +## 2. 核心功能 (Core Features) + +### 2.1. 账号管理 (Account Management) +该模块提供了全面的账号管理功能: +- **创建账号**: 通过 `POST /account` 端点,可以添加新的 Cursor 账号信息到数据库。 +- **读取账号**: + - `GET /accounts`: 获取所有账号列表,支持分页、按邮件模糊搜索以及按字段(如创建时间、ID、邮箱)升序或降序排序。 + - `GET /account/random`: 随机获取一个当前可用的账号及其 Token。 + - `GET /account/{email}/usage`: 查询指定邮箱账号的详细使用情况(如剩余额度、天数)并更新数据库记录。 +- **更新账号状态**: 通过 `PUT /account/id/{id}/status` 端点,可以修改指定 ID 账号的状态(如 active, disabled, deleted)。 +- **删除账号**: + - `DELETE /account/{email}`: 根据邮箱停用(逻辑删除)或永久删除(物理删除,需 `hard_delete=True`)账号。 + - `DELETE /account/id/{id}`: 根据账号 ID 停用或永久删除账号。 +- **导入/导出账号**: + - `POST /accounts/import`: 从上传的 JSON 文件批量导入或更新账号信息。 + - `GET /accounts/export`: 将所有账号信息导出为 JSON 文件。 + +### 2.2. 自动注册 (Automated Registration) +应用包含一个后台服务,用于自动注册新的 Cursor 账号: +- **后台任务**: `run_registration` 异步函数是注册逻辑的核心,它会循环尝试注册新账号。 +- **启动与停止**: + - `GET /registration/start`: 手动启动后台注册任务。如果任务已运行或账号已满,会返回相应状态。 + - `GET /registration/stop`: 手动停止当前运行的注册任务。 +- **状态查询**: `GET /registration/status` 提供注册任务的当前状态,包括是否正在运行、上次运行时间、下次运行时间、成功/失败次数统计以及当前账号数量与最大限制。 +- **监控模式**: 当数据库中激活的账号数量达到 `MAX_ACCOUNTS` 设定的上限时,注册任务会暂停实际注册操作,进入监控模式,并定期检查账号数量,一旦账号数量低于上限则自动恢复注册。 + +### 2.3. 账号使用情况 (Account Usage) +跟踪和管理账号的实际使用量: +- **查询所有账号使用情况**: `GET /usage` 并发查询并返回所有已存账号的剩余额度和试用天数,结果会进行缓存以提高性能。 +- **查询单个账号使用情况**: `GET /account/{email}/usage` 查询特定邮箱账号的余额和剩余天数,并据此更新数据库中的记录。 +- **更新所有账号使用情况**: `POST /update_all_usage` 批量更新所有账号的余量信息到数据库。 +- **记录账号使用行为**: `GET /account/{id}/usage-records` 获取指定账号的历史使用记录(如IP地址、User-Agent、使用时间)。 + +### 2.4. 系统配置管理 (System Configuration) +允许动态管理应用的配置参数(通常存储在 `.env` 文件中): +- **读取配置**: `GET /config` 返回当前系统配置信息,如浏览器设置、邮箱服务详情、代理设置等。 +- **更新配置**: `POST /config` 允许通过 API 请求更新 `.env` 文件中的配置项,并重新加载。 + +### 2.5. Cursor 客户端集成 (Cursor Client Integration) +提供与本地安装的 Cursor IDE 进行交互的功能: +- **使用账号 Token 更新认证**: `POST /account/use-token/{id}` 使用指定账号的 Access Token 来更新本地 Cursor IDE 的认证配置。可以选择是否同时重置机器ID。 +- **重置机器 ID**: `GET /reset-machine` 调用脚本重置本地 Cursor IDE 的机器识别码。 + +### 2.6. Web UI 与 API 文档 (Web UI & API Documentation) +- **静态首页服务**: `GET /` 提供一个简单的 `index.html` 页面作为应用的 Web UI 入口。 +- **Swagger UI**: `GET /docs` 提供交互式的 API 文档界面。 +- **ReDoc**: `GET /redoc` 提供另一种风格的 API 文档。 + +## 3. 架构与关键组件 (Architecture & Key Components) + +### 3.1. FastAPI 应用实例 (`app`) +- **初始化**: `app = FastAPI(...)` 创建主应用实例,配置了标题、描述、版本、文档URL以及 `lifespan` 管理器。 +- **中间件**: `app.add_middleware(CORSMiddleware, ...)` 添加了 CORS 中间件以支持跨域请求。 +- **生命周期事件**: `@asynccontextmanager async def lifespan(app: FastAPI): ...` 定义了应用的生命周期事件。在应用启动时,会调用 `init_db()` 初始化数据库。 + +### 3.2. 数据库交互 (Database Interaction) +- **`database.py` (外部模块)**: 此模块(未直接提供,但从导入推断)负责数据库的连接管理 (`get_session`),定义数据模型 (`AccountModel`, `AccountUsageRecordModel`),以及数据库初始化逻辑 (`init_db`)。 +- **SQLAlchemy ORM**: 应用通过 SQLAlchemy Core 的查询构造语法(如 `select()`, `delete()`, `func.count()`)和异步会话 (`async with get_session() as session:`) 与数据库进行交互。 + +### 3.3. 路由与端点 (Routing & Endpoints) +- API 端点通过 FastAPI 的装饰器(如 `@app.get`, `@app.post`, `@app.put`, `@app.delete`)绑定到相应的异步处理函数。 +- 端点通过 `tags` 参数在 API 文档中进行分组,主要包括: `General`, `Accounts`, `Registration`, `Config`, `System`。 + +### 3.4. 后台注册任务 (`run_registration`) +- 这是一个核心的异步函数,通过 `asyncio.create_task(run_registration())` 在 `/registration/start` 端点被调用时启动。 +- 任务在一个无限循环中运行(受 `registration_status["is_running"]` 控制),依次执行:检查当前激活账号数是否小于 `MAX_ACCOUNTS`,调用 `register_account`(一个外部同步函数,通过 `run_in_executor` 异步执行)进行实际注册,处理成功/失败结果,更新统计信息,然后根据 `REGISTRATION_INTERVAL` 等待下一轮。 + +### 3.5. 全局状态管理 (Global State Management) +- **`registration_status` (字典)**: 用于实时跟踪和存储自动注册任务的各种状态信息,如是否正在运行 (`is_running`)、上次运行时间 (`last_run`)、上次状态 (`last_status`)、下次计划运行时间 (`next_run`),以及运行次数、成功和失败的统计。 +- **`background_tasks` (字典)**: 主要用于存储 `run_registration` 任务的 `asyncio.Task` 实例,键为 `"registration_task"`。这允许其他部分代码检查任务是否正在运行或取消任务。 + +### 3.6. 配置管理 (Configuration Management) +- **`config.py` (外部模块)**: 定义了应用的一些关键配置常量,如 `MAX_ACCOUNTS`(最大账号数)、`REGISTRATION_INTERVAL`(注册间隔时间)、`API_HOST`、`API_PORT` 等。 +- **`.env` 文件**: 应用启动时及配置更新后,会通过 `python-dotenv` 库的 `load_dotenv()` 函数从项目根目录下的 `.env` 文件加载环境变量。这些变量通常包含敏感信息或环境特定配置。 + +### 3.7. 日志系统 (Logging) +- **`logger.py` (外部模块)**: 应用从该模块导入 `info` 和 `error` 函数,用于在控制台或日志文件(取决于 `logger.py` 的配置)中记录不同级别的事件信息和错误详情,包括堆栈跟踪。 + +### 3.8. 辅助函数与类 (Utility Functions & Classes) +- **数据库查询辅助函数**: `get_active_account_count()` 和 `get_account_count()` 用于高效查询数据库中符合特定条件的账号数量。 +- **`Cursor` 类 (from `tokenManager.cursor`)**: 封装了与 Cursor 服务进行交互的逻辑,例如 `get_remaining_balance()` 和 `get_trial_remaining_days()` 方法用于查询账号的额度和试用期。 +- **`CursorAuthManager` 类 (from `cursor_auth_manager`)**: 负责更新本地 Cursor IDE 的认证文件。 +- **`CursorShadowPatcher` 类 (from `cursor_shadow_patcher`)**: 负责重置本地 Cursor IDE 的机器 ID。 + +## 4. 数据模型 (Data Models - Pydantic) + +Pydantic 模型在 FastAPI 中扮演着数据校验、序列化和文档生成的关键角色: +- **`Account`**: 定义了一个 Cursor 账号的主要属性,如 `email`, `password`, `token`, `user`, `usage_limit`, `created_at`, `status`, `id`。它用于创建账号 (`POST /account`) 的请求体,并在多个响应中作为数据结构。`Config.from_attributes = True` 允许从 ORM 对象创建 Pydantic 模型实例。 +- **`AccountResponse`**: 一个通用的响应模型,封装了操作是否成功 (`success`)、返回的数据 (`data`,通常是 `Account` 模型或其列表)以及可选的消息 (`message`)。 +- **`StatusUpdate`**: 用于 `PUT /account/id/{id}/status` 端点的请求体,包含一个新的 `status` 字符串。 +- **`ConfigModel`**: 定义了 `POST /config` 端点接受的配置项及其类型,例如 `BROWSER_HEADLESS`, `MAX_ACCOUNTS`, `EMAIL_DOMAINS`, 代理相关设置等。 + +这些模型确保了 API 接收的数据符合预期格式,并且响应数据也以结构化的方式返回。 + +## 5. 错误处理 (Error Handling) + +应用实现了全局异常处理机制: +- **`@app.exception_handler(HTTPException)`**: 捕获 FastAPI 自身或其他地方抛出的 `HTTPException`。它会记录错误并通过 `JSONResponse` 返回一个包含 `success: False` 和错误详情(`exc.detail`)的 JSON 响应,状态码与原始异常一致。 +- **`@app.exception_handler(Exception)`**: 捕获所有其他未被处理的 Python 异常。这确保了即使发生意外错误,应用也不会崩溃,而是返回一个标准的 500 内部服务器错误响应,其中包含 `success: False` 和通用错误消息。在调试模式下(`app.debug` 为 True),响应中可能还会包含异常的详细信息。 + +这种集中的错误处理方式有助于提供一致的 API 错误响应格式。 + +## 6. 依赖与环境 (Dependencies & Environment) + +### 主要依赖: +- **FastAPI**: Web 框架。 +- **Uvicorn**: ASGI 服务器。 +- **SQLAlchemy**: ORM,用于数据库异步操作 (需要配合相应的数据库驱动,如 `asyncpg` for PostgreSQL, `aiomysql` for MySQL)。 +- **Pydantic**: 数据验证和模型定义。 +- **python-dotenv**: 加载 `.env` 文件中的环境变量。 +- **requests**: (推断) `tokenManager.cursor.Cursor` 类可能使用此库进行 HTTP 请求以查询 Cursor API。 +- **concurrent.futures**: 用于在 `check_usage` 接口中并发执行账号状态检查。 + +### 运行环境: +- **Python**: 版本 3.7+ (基于 FastAPI 和 `async/await` 语法)。 +- **`.env` 文件**: 必须在项目根目录下存在,并包含所有必要的配置变量 (如数据库连接信息、API 密钥、邮箱配置、代理配置等)。`get_config` 和 `update_config` 端点直接与此文件交互。 +- **数据库服务**: 需要一个 SQLAlchemy 支持的数据库正在运行,并在 `.env` 中配置好连接参数。 +- **网络访问**: 自动注册和账号使用情况查询功能需要网络访问权限,以连接到 Cursor 服务和可能的邮件服务。 + +## 7. 部署与运行 (Deployment & Execution) + +该 FastAPI 应用通过 Uvicorn ASGI 服务器运行。文件末尾的 `if __name__ == "__main__":` 块提供了一个直接运行应用的入口点: +```python +if __name__ == "__main__": + uvicorn.run( + "api:app", + host=API_HOST, + port=API_PORT, + reload=API_DEBUG, + access_log=True, + log_level="error", + workers=API_WORKERS, + loop="asyncio", + ) +``` +- `"api:app"`: 指示 Uvicorn 加载 `api.py` 文件中的 `app` FastAPI 实例。 +- `host=API_HOST`, `port=API_PORT`: 从 `config.py` (或 `.env`) 加载监听的主机和端口。 +- `reload=API_DEBUG`: 如果 `API_DEBUG` 为 True,则启用热重载功能,代码更改时服务器会自动重启。 +- `access_log=True`: 启用访问日志。 +- `log_level="error"`: 设置 Uvicorn 的日志级别。 +- `workers=API_WORKERS`: 配置工作进程数量。对于生产环境,可以根据服务器核心数调整。 +- `loop="asyncio"`: 明确指定使用 asyncio 事件循环。 + +## 8. 注意事项 (Considerations) + +- **并发安全**: 虽然 FastAPI 和 asyncio 处理并发请求,但对全局变量 `registration_status` 和 `background_tasks` 的直接修改可能需要审慎处理,以避免潜在的竞争条件,尤其是在多 worker 配置下(尽管 Python 的 GIL 使得纯 Python 代码的并发问题不如其他语言复杂)。 +- **安全性**: + - **敏感信息**: `.env` 文件中存储了大量敏感配置。需要确保此文件的权限得到妥善管理。 + - **密码存储**: 如果 `AccountModel` 直接存储明文密码,这是严重的安全风险。密码应始终进行哈希处理 (如使用 bcrypt 或 Argon2) 后再存储。 + - **API 认证/授权**: 当前 API 似乎没有实现任何认证或授权机制来保护其端点。在生产环境中,应考虑添加如 OAuth2 或 API 密钥等机制来限制对敏感操作的访问。 +- **配置热重载**: `/restart` 接口通过修改 `.env` 文件中的一个时间戳变量来尝试触发 Uvicorn 的热重载。这种方法的有效性依赖于 Uvicorn 的 `--reload` 选项及其文件监控机制,可能并非在所有情况下都可靠或即时。 +- **外部依赖**: 自动注册功能依赖于外部的 `register_account` 函数和 `tokenManager.cursor` 模块。这些外部组件的稳定性和行为直接影响本应用的功能。 +- **错误处理细节**: 虽然有全局异常处理,但某些函数内部的 `try-except` 块可能会捕获并记录错误,然后继续执行或返回特定响应,这需要仔细审查以确保所有错误路径都得到妥善处理。 +- **数据库迁移**: 随着 `AccountModel` 或 `AccountUsageRecordModel` 的演变,需要一个数据库迁移策略 (如使用 Alembic) 来管理数据库模式的变更。 diff --git a/browser_utils.py b/browser_utils.py new file mode 100644 index 0000000..6dc4755 --- /dev/null +++ b/browser_utils.py @@ -0,0 +1,137 @@ +from DrissionPage import ChromiumOptions, Chromium +import sys +import os +from logger import info, warning, error +from config import ( + BROWSER_USER_AGENT, + BROWSER_PATH, + BROWSER_HEADLESS, + DYNAMIC_USERAGENT, + USE_PROXY, + PROXY_TYPE, + PROXY_HOST, + PROXY_PORT, + PROXY_USERNAME, + PROXY_PASSWORD, + PROXY_TIMEOUT +) +import random +import time + +from fake_useragent import UserAgent + + +def get_random_user_agent(): + ua = UserAgent() + return ua.random + +class BrowserManager: + def __init__(self): + self.browser = None + + def init_browser(self): + try: + info("正在初始化浏览器...") + co = ChromiumOptions() + + # 如果配置了特定的浏览器路径,则使用 + if BROWSER_PATH and os.path.exists(BROWSER_PATH): + co.set_browser_path(BROWSER_PATH) + info(f"使用自定义浏览器路径: {BROWSER_PATH}") + + try: + extension_path = self._get_extension_path() + co.add_extension(extension_path) + except FileNotFoundError as e: + error(f"加载插件失败,警告: {e}") + + # 设置User-Agent + if DYNAMIC_USERAGENT: + # 随机选择一个User-Agent + user_agent = get_random_user_agent() + info(f"使用动态User-Agent: {user_agent}") + co.set_user_agent(user_agent) + elif BROWSER_USER_AGENT: + info(f"使用固定User-Agent: {BROWSER_USER_AGENT}") + co.set_user_agent(BROWSER_USER_AGENT) + else: + info("不配置User-Agent") + + co.set_pref("credentials_enable_service", False) + co.set_argument("--hide-crash-restore-bubble") + # 禁用自动化特征(关键参数) + co.set_argument("--disable-blink-features=AutomationControlled") + co.set_argument("--disable-features=AutomationControlled") + co.set_argument("--disable-automation-extension") + + # 随机化指纹参数 + co.set_pref("webgl.vendor", "NVIDIA Corporation") + co.set_pref( + "webgl.renderer", + "ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0)", + ) + co.set_pref("navigator.plugins.length", 5) + co.set_pref("navigator.hardwareConcurrency", 8) + + # 覆盖自动化特征(关键) + co.set_pref("dom.webdriver.enabled", False) + co.set_pref("useAutomationExtension", False) + + # 设置时区参数 + co.set_argument("--timezone=Asia/Shanghai") + co.set_pref("timezone.override", "Asia/Shanghai") + + # 设置更真实的屏幕参数 + co.set_pref("screen.width", 1920) + co.set_pref("screen.height", 1080) + co.set_pref("screen.pixelDepth", 24) + co.auto_port() + + # 生产环境使用无头模式 + co.headless(BROWSER_HEADLESS) + + # Mac 系统特殊处理 + if sys.platform == "darwin" or sys.platform == "linux": + co.set_argument("--no-sandbox") + co.set_argument("--disable-gpu") + + # 添加代理设置 + if USE_PROXY and PROXY_HOST and PROXY_PORT: + proxy_string = f"{PROXY_TYPE}://" + + # 如果有认证信息 + if PROXY_USERNAME and PROXY_PASSWORD: + proxy_string += f"{PROXY_USERNAME}:{PROXY_PASSWORD}@" + + proxy_string += f"{PROXY_HOST}:{PROXY_PORT}" + + info(f"使用代理: {PROXY_TYPE} {proxy_string}") + co.set_argument(f'--proxy-server={proxy_string}') + + self.browser = Chromium(co) + info("浏览器初始化成功") + except Exception as e: + error(f"浏览器初始化失败: {str(e)}") + return self.browser + + def _get_extension_path(self): + """获取插件路径""" + root_dir = os.getcwd() + extension_path = os.path.join(root_dir, "turnstilePatch") + + if hasattr(sys, "_MEIPASS"): + extension_path = os.path.join(sys._MEIPASS, "turnstilePatch") + + if not os.path.exists(extension_path): + raise FileNotFoundError(f"插件不存在: {extension_path}") + info(f"插件路径: {extension_path}") + return extension_path + + def quit(self): + info("正在关闭浏览器...") + try: + if self.browser: + self.browser.quit() + info("浏览器已关闭") + except Exception as e: + error(f"关闭浏览器出错: {str(e)}") diff --git a/config.py b/config.py new file mode 100644 index 0000000..3412bc5 --- /dev/null +++ b/config.py @@ -0,0 +1,113 @@ +import os +from dotenv import load_dotenv + +# 加载.env文件中的环境变量 +load_dotenv() + +# ===== 日志配置 ===== +# 日志级别:DEBUG, INFO, WARNING, ERROR, CRITICAL +LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") +# 日志格式:时间戳 - 日志级别 - 消息内容 +LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" +# 日志日期格式:年-月-日 时:分:秒 +LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" + +# ===== API服务配置 ===== +# API服务监听主机地址 +API_HOST = os.getenv("API_HOST", "127.0.0.1") +# API服务端口号 +API_PORT = int(os.getenv("API_PORT", 8000)) +# 是否启用调试模式 +API_DEBUG = os.getenv("API_DEBUG", "false").lower() == "true" +# API服务工作进程数量(Windows下建议使用1) +API_WORKERS = int(os.getenv("API_WORKERS", 1)) + +# ===== 账号管理配置 ===== +# 系统最大已激活的账号数量 +MAX_ACCOUNTS = int(os.getenv("MAX_ACCOUNTS", 10)) +# 每次注册间隔时间(秒) +REGISTRATION_INTERVAL = int(os.getenv("REGISTRATION_INTERVAL", 60)) +# 注册失败时的最大重试次数 +REGISTRATION_MAX_RETRIES = int(os.getenv("REGISTRATION_MAX_RETRIES", 3)) +# 注册重试间隔时间(秒) +REGISTRATION_RETRY_INTERVAL = int(os.getenv("REGISTRATION_RETRY_INTERVAL", 5)) + +# ===== 浏览器配置 ===== +# 是否以无头模式运行浏览器(不显示界面) +BROWSER_HEADLESS = os.getenv("BROWSER_HEADLESS", "true").lower() == "true" +# 浏览器可执行文件路径(为空则使用默认路径) +BROWSER_PATH = os.getenv("BROWSER_PATH", None) +# 浏览器下载文件保存路径 +BROWSER_DOWNLOAD_PATH = os.getenv("BROWSER_DOWNLOAD_PATH", None) +# 是否使用动态ua池 +DYNAMIC_USERAGENT = os.getenv("DYNAMIC_USERAGENT", "false").lower() == "true" +# 浏览器User-Agent +BROWSER_USER_AGENT = os.getenv("BROWSER_USER_AGENT", None) + +# ===== Cursor URL配置 ===== +# Cursor登录页面URL +LOGIN_URL = "https://authenticator.cursor.sh" +# Cursor注册页面URL +SIGN_UP_URL = "https://authenticator.cursor.sh/sign-up" +# Cursor设置页面URL +SETTINGS_URL = "https://www.cursor.com/settings" + +# ===== 邮箱配置 ===== +# 邮箱验证码获取方式 +EMAIL_CODE_TYPE = os.getenv("EMAIL_CODE_TYPE", "AUTO") +# 邮箱类型 +EMAIL_TYPE = os.getenv("EMAIL_TYPE", "tempemail") +# 临时邮箱用户名 +EMAIL_USERNAME = os.getenv("EMAIL_USERNAME", "xxx") +# 临时邮箱域名 +EMAIL_DOMAIN = os.getenv("EMAIL_DOMAIN", "mailto.plus") +# 临时邮箱PIN码(如果需要) +EMAIL_PIN = os.getenv("EMAIL_PIN", "") +# 可用于注册的邮箱域名列表(逗号分隔) +EMAIL_DOMAINS = [ + domain.strip() for domain in os.getenv("EMAIL_DOMAINS", "xxx.xx").split(",") +] +# ZMail API地址 +EMAIL_API = os.getenv("EMAIL_API", "") +# 是否启用邮箱API代理 +EMAIL_PROXY_ENABLED = os.getenv("EMAIL_PROXY_ENABLED", "false").lower() == "true" +# 邮箱API代理地址 +EMAIL_PROXY_ADDRESS = os.getenv("EMAIL_PROXY_ADDRESS", "") +# 邮件验证码获取最大重试次数 +EMAIL_VERIFICATION_RETRIES = int(os.getenv("EMAIL_VERIFICATION_RETRIES", 5)) +# 邮件验证码获取重试间隔(秒) +EMAIL_VERIFICATION_WAIT = int(os.getenv("EMAIL_VERIFICATION_WAIT", 5)) + +# ===== 数据库配置 ===== +# 数据库文件名 +DB_NAME = "accounts.db" +# 根据操作系统生成适当的数据库文件路径 +if os.name == "nt": # Windows + DB_PATH = os.path.join(os.getcwd(), DB_NAME) + DATABASE_URL = f"sqlite+aiosqlite:///{DB_PATH}" +else: # Linux/Unix + DB_PATH = os.path.join("/app", DB_NAME) + DATABASE_URL = f"sqlite+aiosqlite:{DB_PATH}" + +# 允许通过环境变量覆盖默认的数据库URL +DATABASE_URL = os.getenv("DATABASE_URL", DATABASE_URL) + +# ===== Cursor main.js 配置 ===== +# Cursor 主文件路径 +CURSOR_PATH = os.getenv("CURSOR_PATH", None) + +# ===== 代理配置 ===== +# 是否启用代理 +USE_PROXY = os.getenv("USE_PROXY", "False").lower() == "true" +# 代理类型 +PROXY_TYPE = os.getenv("PROXY_TYPE", "http") +# 代理服务器地址 +PROXY_HOST = os.getenv("PROXY_HOST", "") +# 代理服务器端口 +PROXY_PORT = os.getenv("PROXY_PORT", "") +# 代理服务器用户名 +PROXY_USERNAME = os.getenv("PROXY_USERNAME", "") +# 代理服务器密码 +PROXY_PASSWORD = os.getenv("PROXY_PASSWORD", "") +# 代理服务器超时时间 +PROXY_TIMEOUT = int(os.getenv("PROXY_TIMEOUT", "10")) \ No newline at end of file diff --git a/cursor_auth_manager.py b/cursor_auth_manager.py new file mode 100644 index 0000000..6709287 --- /dev/null +++ b/cursor_auth_manager.py @@ -0,0 +1,87 @@ +import sqlite3 +import os +import sys + + +class CursorAuthManager: + """Cursor认证信息管理器""" + + def __init__(self): + # 判断操作系统 + if sys.platform == "win32": # Windows + appdata = os.getenv("APPDATA") + if appdata is None: + raise EnvironmentError("APPDATA 环境变量未设置") + self.db_path = os.path.join( + appdata, "Cursor", "User", "globalStorage", "state.vscdb" + ) + elif sys.platform == "darwin": # macOS + self.db_path = os.path.abspath( + os.path.expanduser( + "~/Library/Application Support/Cursor/User/globalStorage/state.vscdb" + ) + ) + elif sys.platform == "linux": # Linux 和其他类Unix系统 + self.db_path = os.path.abspath( + os.path.expanduser("~/.config/Cursor/User/globalStorage/state.vscdb") + ) + else: + raise NotImplementedError(f"不支持的操作系统: {sys.platform}") + + def update_auth(self, email=None, access_token=None, refresh_token=None): + """ + 更新Cursor的认证信息 + :param email: 新的邮箱地址 + :param access_token: 新的访问令牌 + :param refresh_token: 新的刷新令牌 + :return: bool 是否成功更新 + """ + updates = [] + # 登录状态 + updates.append(("cursorAuth/cachedSignUpType", "Auth_0")) + + if email is not None: + updates.append(("cursorAuth/cachedEmail", email)) + if access_token is not None: + updates.append(("cursorAuth/accessToken", access_token)) + if refresh_token is not None: + updates.append(("cursorAuth/refreshToken", refresh_token)) + + if not updates: + print("没有提供任何要更新的值") + return False + + conn = None + try: + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + + for key, value in updates: + # 如果没有更新任何行,说明key不存在,执行插入 + # 检查 accessToken 是否存在 + check_query = "SELECT COUNT(*) FROM itemTable WHERE key = ?" + cursor.execute(check_query, (key,)) + if cursor.fetchone()[0] == 0: + insert_query = "INSERT INTO itemTable (key, value) VALUES (?, ?)" + cursor.execute(insert_query, (key, value)) + else: + update_query = "UPDATE itemTable SET value = ? WHERE key = ?" + cursor.execute(update_query, (value, key)) + + if cursor.rowcount > 0: + print(f"成功更新 {key.split('/')[-1]} : {value}") + else: + print(f"未找到 {key.split('/')[-1]} 或值未变化") + + conn.commit() + return True + + except sqlite3.Error as e: + print("数据库错误:", str(e)) + return False + except Exception as e: + print("发生错误:", str(e)) + return False + finally: + if conn: + conn.close() diff --git a/cursor_pro_keep_alive.py b/cursor_pro_keep_alive.py new file mode 100644 index 0000000..0d0dd73 --- /dev/null +++ b/cursor_pro_keep_alive.py @@ -0,0 +1,578 @@ +import sys +import psutil +import time +import random +from logger import info, warning, error +import traceback +from config import ( + LOGIN_URL, + SIGN_UP_URL, + SETTINGS_URL, + EMAIL_DOMAINS, + REGISTRATION_MAX_RETRIES, + EMAIL_TYPE, + EMAIL_CODE_TYPE +) +import secrets +import hashlib +import base64 +import uuid +import requests +from typing import Optional, Tuple + + +if sys.stdout.encoding != "utf-8": + sys.stdout.reconfigure(encoding="utf-8") +if sys.stderr.encoding != "utf-8": + sys.stderr.reconfigure(encoding="utf-8") + +from browser_utils import BrowserManager +from get_email_code import EmailVerificationHandler + +from datetime import datetime # 添加这行导入 + +TOTAL_USAGE = 0 + + +def handle_turnstile(tab, max_retries: int = 5, retry_interval: tuple = (1, 2)) -> bool: + """ + 处理Turnstile验证 + + Args: + tab: 浏览器标签对象 + max_retries: 最大重试次数 + retry_interval: 重试间隔范围(最小值, 最大值) + + Returns: + bool: 验证是否成功 + """ + info("=============正在检测 Turnstile 验证=============") + + # 初始化重试计数器 + retry_count = 0 + + try: + # 在最大重试次数内循环尝试验证 + while retry_count < max_retries: + # 增加重试计数 + retry_count += 1 + info(f"正在进行 Turnstile 第 {retry_count} 次验证中...") + + try: + # 检查页面状态,但不直接返回,先检查是否有Turnstile验证需要处理 + page_ready = False + if tab.ele("@name=password"): + info("检测到密码输入页面,检查是否有验证需要处理...") + page_ready = True + elif tab.ele("@data-index=0"): + info("检测到验证码输入页面,检查是否有验证需要处理...") + page_ready = True + elif tab.ele("Account Settings"): + info("检测到账户设置页面,检查是否有验证需要处理...") + page_ready = True + + # 初始化元素变量 + element = None + try: + # 尝试通过层级结构定位到Turnstile验证框的容器元素 + element = ( + tab.ele(".main-content") # 找到 .main-content 元素 + .ele("tag:div") # 找到第一个子 div + .ele("tag:div") # 找到第二个子 div + .ele("tag:div") # 找到第三个子 div + ) + except Exception as e: + # 如果无法通过第一种方式找到元素,忽略异常继续执行 + pass + + challenge_check = None + if element: + # 如果找到了容器元素,则在其中定位验证框的输入元素 + try: + challenge_check = ( + element + .shadow_root.ele("tag:iframe") # 找到shadow DOM中的iframe + .ele("tag:body") # 找到iframe中的body + .sr("tag:input") # 找到body中的input元素 + ) + except Exception as e: + pass + else: + # 如果没有找到容器元素,则尝试另一种方式定位验证框 + try: + challenge_check = ( + tab.ele("@id=cf-turnstile", timeout=2) # 通过id直接找到turnstile元素 + .child() # 获取其子元素 + .shadow_root.ele("tag:iframe") # 找到shadow DOM中的iframe + .ele("tag:body") # 找到iframe中的body + .sr("tag:input") # 找到body中的input元素 + ) + except Exception as e: + pass + + if challenge_check: + # 如果找到了验证输入元素,记录日志 + info("检测到 Turnstile 验证,正在处理...") + # 点击前随机延迟,模拟人工操作 + time.sleep(random.uniform(1, 3)) + # 点击验证元素触发验证 + challenge_check.click() + # 等待验证处理 + time.sleep(2) + info("Turnstile 验证通过") + return True + else: + info("未检测到 Turnstile 验证") + + # 如果页面已准备好且没有验证需要处理,则可以返回 + if page_ready: + info("页面已准备好,没有检测到需要处理的验证") + return True + + except Exception as e: + # 记录当前尝试失败的详细信息 + info(f"当前验证尝试失败: {str(e)}") + + # 在下一次尝试前随机延迟 + time.sleep(random.uniform(*retry_interval)) + + # 超过最大重试次数,验证失败 + error(f"Turnstile 验证次数超过最大限制 {max_retries},退出") + return False + + except Exception as e: + # 捕获整个验证过程中的异常 + error_msg = f"Turnstile 验证失败: {str(e)}" + error(error_msg) + return False + + +def get_cursor_session_token(tab, max_attempts: int = 3, retry_interval: int = 2) -> Optional[Tuple[str, str]]: + """ + 获取Cursor会话token + + Args: + tab: 浏览器标签页对象 + max_attempts: 最大尝试次数 + retry_interval: 重试间隔(秒) + + Returns: + Tuple[str, str] | None: 成功返回(userId, accessToken)元组,失败返回None + """ + info("开始获取会话令牌") + + # 首先尝试使用UUID深度登录方式 + info("尝试使用深度登录方式获取token") + + def _generate_pkce_pair(): + """生成PKCE验证对""" + code_verifier = secrets.token_urlsafe(43) + code_challenge_digest = hashlib.sha256(code_verifier.encode('utf-8')).digest() + code_challenge = base64.urlsafe_b64encode(code_challenge_digest).decode('utf-8').rstrip('=') + return code_verifier, code_challenge + + attempts = 0 + while attempts < max_attempts: + try: + verifier, challenge = _generate_pkce_pair() + id = uuid.uuid4() + client_login_url = f"https://www.cursor.com/cn/loginDeepControl?challenge={challenge}&uuid={id}&mode=login" + + info(f"访问深度登录URL: {client_login_url}") + tab.get(client_login_url) + # save_screenshot(tab, f"deeplogin_attempt_{attempts}") + + if tab.ele("xpath=//span[contains(text(), 'Yes, Log In')]", timeout=5): + info("点击确认登录按钮") + tab.ele("xpath=//span[contains(text(), 'Yes, Log In')]").click() + time.sleep(1.5) + + auth_poll_url = f"https://api2.cursor.sh/auth/poll?uuid={id}&verifier={verifier}" + headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Cursor/0.48.6 Chrome/132.0.6834.210 Electron/34.3.4 Safari/537.36", + "Accept": "*/*" + } + + info(f"轮询认证状态: {auth_poll_url}") + response = requests.get(auth_poll_url, headers=headers, timeout=5) + + if response.status_code == 200: + data = response.json() + accessToken = data.get("accessToken", None) + authId = data.get("authId", "") + + if accessToken: + userId = "" + if len(authId.split("|")) > 1: + userId = authId.split("|")[1] + + info("成功获取账号token和userId") + return accessToken, userId + else: + error(f"API请求失败,状态码: {response.status_code}") + else: + warning("未找到登录确认按钮") + + attempts += 1 + if attempts < max_attempts: + wait_time = retry_interval * attempts # 逐步增加等待时间 + warning(f"第 {attempts} 次尝试未获取到token,{wait_time}秒后重试...") + # save_screenshot(tab, f"token_attempt_{attempts}") + time.sleep(wait_time) + + except Exception as e: + error(f"深度登录获取token失败: {str(e)}") + attempts += 1 + # save_screenshot(tab, f"token_error_{attempts}") + if attempts < max_attempts: + wait_time = retry_interval * attempts + warning(f"将在 {wait_time} 秒后重试...") + time.sleep(wait_time) + + +def sign_up_account(browser, tab, account_info): + info("=============开始注册账号=============") + info( + f"账号信息: 邮箱: {account_info['email']}, 密码: {account_info['password']}, 姓名: {account_info['first_name']} {account_info['last_name']}" + ) + if EMAIL_TYPE == "zmail": + EmailVerificationHandler.create_zmail_email(account_info) + tab.get(SIGN_UP_URL) + + tab.wait(2) + + if tab.ele("@name=cf-turnstile-response"): + error("开屏就是检测啊,大佬你的IP或UA需要换一下了啊,有问题了...要等一下") + + try: + if tab.ele("@name=first_name"): + info("=============正在填写个人信息=============") + tab.actions.click("@name=first_name").input(account_info["first_name"]) + info(f"已输入名字: {account_info['first_name']}") + time.sleep(random.uniform(1, 3)) + + tab.actions.click("@name=last_name").input(account_info["last_name"]) + info(f"已输入姓氏: {account_info['last_name']}") + time.sleep(random.uniform(1, 3)) + + tab.actions.click("@name=email").input(account_info["email"]) + info(f"已输入邮箱: {account_info['email']}") + time.sleep(random.uniform(1, 3)) + + info("=============提交个人信息=============") + tab.actions.click("@type=submit") + time.sleep(random.uniform(0.2, 1)) + if ( + tab.ele("verify the user is human. Please try again.") + or tab.ele("Can't verify the user is human. Please try again.") + or tab.ele("Can't verify the user is human. Please try again.") + ): + info("检测到turnstile验证失败,(IP问题、UA问题、域名问题)...正在重试...") + return "EMAIL_USED" + except Exception as e: + info(f"填写个人信息失败: {str(e)}") + return "ERROR" + + handle_turnstile(tab) + + if tab.ele("verify the user is human. Please try again.") or tab.ele( + "Can't verify the user is human. Please try again." + ): + info("检测到turnstile验证失败,正在重试...") + return "EMAIL_USED" + + try: + if tab.ele("@name=password"): + info(f"设置密码:{account_info['password']}") + tab.ele("@name=password").input(account_info["password"]) + time.sleep(random.uniform(1, 2)) + + info("提交密码...") + tab.ele("@type=submit").click() + info("密码设置成功,等待系统响应....") + + except Exception as e: + info(f"密码设置失败: {str(e)}") + return "ERROR" + + info("处理最终验证...") + handle_turnstile(tab) + + if tab.ele("This email is not available."): + info("邮箱已被使用") + return "EMAIL_USED" + + if tab.ele("Sign up is restricted."): + info("注册限制") + return "SIGNUP_RESTRICTED" + + # 创建邮件处理器 + email_handler = EmailVerificationHandler() + i = 0 + while i < 5: + try: + time.sleep(random.uniform(0.2, 1)) + if tab.ele("Account Settings"): + info("注册成功,已进入账号设置页面") + break + if tab.ele("@data-index=0"): + info("等待输入验证码...") + # 切换到邮箱标签页 + code = email_handler.get_verification_code( + source_email=account_info["email"] + ) + if code is None: + info("未获取到验证码...系统异常,正在退出....") + return "EMAIL_GET_CODE_FAILED" + info(f"输入验证码: {code}") + i = 0 + for digit in code: + tab.ele(f"@data-index={i}").input(digit) + time.sleep(random.uniform(0.3, 0.6)) + i += 1 + info("验证码输入完成") + time.sleep(random.uniform(3, 5)) + + # 在验证码输入完成后检测是否出现了Turnstile验证 + info("检查是否出现了Turnstile验证...") + try: + turnstile_element = tab.ele("@id=cf-turnstile", timeout=3) + if turnstile_element: + info("检测到验证码输入后出现Turnstile验证,正在处理...") + handle_turnstile(tab) + except: + info("未检测到Turnstile验证,继续下一步") + + break + except Exception as e: + info(f"验证码处理失败: {str(e)}") + return "ERROR" + + info("完成最终验证...") + handle_turnstile(tab) + time.sleep(random.uniform(3, 5)) + info("账号注册流程完成") + return "SUCCESS" + + +class EmailGenerator: + def __init__( + self, + ): + # 将密码生成移到这里,避免类定义时执行随机密码生成 + self.default_first_name = self.generate_random_name() + self.default_last_name = self.generate_random_name() + + # 从配置文件获取域名配置 + self.domains = EMAIL_DOMAINS + info(f"当前可用域名: {self.domains}") + + self.email = None + self.password = None + + def generate_random_password(self, length=12): + """生成随机密码 - 改进密码生成算法,确保包含各类字符""" + chars = "abcdefghijklmnopqrstuvwxyz" + upper_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + digits = "0123456789" + special = "!@#$%^&*" + + # 确保密码包含至少一个大写字母、一个数字和一个特殊字符 + password = [ + random.choice(chars), + random.choice(upper_chars), + random.choice(digits), + random.choice(special), + ] + + # 添加剩余随机字符 + password.extend( + random.choices(chars + upper_chars + digits + special, k=length - 4) + ) + + # 打乱密码顺序 + random.shuffle(password) + return "".join(password) + + def generate_random_name(self, length=6): + """生成随机用户名""" + first_letter = random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + rest_letters = "".join( + random.choices("abcdefghijklmnopqrstuvwxyz", k=length - 1) + ) + return first_letter + rest_letters + + def generate_email(self, length=8): + """生成随机邮箱地址,使用随机域名""" + random_str = "".join( + random.choices("abcdefghijklmnopqrstuvwxyz1234567890", k=length) + ) + timestamp = str(int(time.time()))[-4:] # 使用时间戳后4位 + # 随机选择一个域名 + domain = random.choice(self.domains) + return f"{random_str}@{domain}" + + def get_account_info(self): + """获取账号信息,确保每次调用都生成新的邮箱和密码""" + self.email = self.generate_email() + self.password = self.generate_random_password() + return { + "email": self.email, + "password": self.password, + "first_name": self.default_first_name.capitalize(), + "last_name": self.default_last_name.capitalize(), + } + + def _save_account_info(self, user, token, total_usage): + try: + from database import get_session, AccountModel + import asyncio + import time + + async def save_to_db(): + info(f"开始保存账号信息: {self.email}") + async with get_session() as session: + # 检查账号是否已存在 + from sqlalchemy import select + + result = await session.execute( + select(AccountModel).where(AccountModel.email == self.email) + ) + existing_account = result.scalar_one_or_none() + + if existing_account: + info(f"更新现有账号信息 (ID: {existing_account.id})") + existing_account.token = token + existing_account.user = user + existing_account.password = self.password + existing_account.usage_limit = str(total_usage) + # 如果账号状态是删除,更新为活跃 + if existing_account.status == "deleted": + existing_account.status = "active" + # 不更新id,保留原始id值 + else: + info("创建新账号记录") + # 生成毫秒级时间戳作为id + timestamp_ms = int(time.time() * 1000) + account = AccountModel( + email=self.email, + password=self.password, + token=token, + user=user, + usage_limit=str(total_usage), + created_at=datetime.now().strftime("%Y-%m-%d %H:%M"), + status="active", # 设置默认状态为活跃 + id=timestamp_ms, # 设置毫秒时间戳id + ) + session.add(account) + + await session.commit() + info(f"账号 {self.email} 信息保存成功") + return True + + return asyncio.run(save_to_db()) + except Exception as e: + info(f"保存账号信息失败: {str(e)}") + return False + + +def cleanup_and_exit(browser_manager=None, exit_code=0): + """清理资源并退出程序""" + try: + if browser_manager: + info("正在关闭浏览器") + if hasattr(browser_manager, "browser"): + browser_manager.browser.quit() + + current_process = psutil.Process() + children = current_process.children(recursive=True) + for child in children: + try: + child.terminate() + except: + pass + + info("程序正常退出") + sys.exit(exit_code) + + except Exception as e: + info(f"清理退出时发生错误: {str(e)}") + sys.exit(1) + + +def main(): + browser_manager = None + max_retries = REGISTRATION_MAX_RETRIES # 从配置文件获取 + current_retry = 0 + + try: + email_handler = EmailVerificationHandler() + if email_handler.check(): + info('邮箱服务连接正常,开始注册!') + else: + if EMAIL_CODE_TYPE == "API": + error('邮箱服务连接失败,并且验证码为API获取,结束注册!') + return + else: + info('邮箱服务连接失败,并且验证码为手动输入,等待输入验证码...') + + email_generator = EmailGenerator() + browser_manager = BrowserManager() + browser = browser_manager.init_browser() + while current_retry < max_retries: + try: + account_info = email_generator.get_account_info() + info( + f"初始化账号信息成功 => 邮箱: {account_info['email']}, 用户名: {account_info['first_name']}, 密码: {account_info['password']}" + ) + + signup_tab = browser.new_tab(LOGIN_URL) + browser.activate_tab(signup_tab) + + signup_tab.run_js("try { turnstile.reset() } catch(e) { }") + result = sign_up_account(browser, signup_tab, account_info) + + if result == "SUCCESS": + token, user = get_cursor_session_token(signup_tab) + info(f"获取到账号Token: {token}, 用户: {user}") + if token: + email_generator._save_account_info(user, token, TOTAL_USAGE) + info("注册流程完成") + cleanup_and_exit(browser_manager, 0) + else: + info("获取Cursor会话Token失败") + current_retry += 1 + elif result in [ + "EMAIL_USED", + "SIGNUP_RESTRICTED", + "VERIFY_FAILED", + "EMAIL_GET_CODE_FAILED", + ]: + info(f"遇到问题: {result},尝试切换邮箱...") + continue # 使用新邮箱重试注册 + else: # ERROR + info("遇到错误,准备重试...") + current_retry += 1 + + # 关闭标签页,准备下一次尝试 + signup_tab.close() + time.sleep(2) + + except Exception as e: + info(f"当前尝试发生错误: {str(e)}") + current_retry += 1 + time.sleep(2) + try: + # 尝试关闭可能存在的标签页 + if "signup_tab" in locals(): + signup_tab.close() + except: + pass + + info(f"达到最大重试次数 {max_retries},注册失败") + except Exception as e: + info(f"主程序错误: {str(e)}") + info(f"错误详情: {traceback.format_exc()}") + cleanup_and_exit(browser_manager, 1) + finally: + cleanup_and_exit(browser_manager, 1) diff --git a/cursor_pro_keep_alive_backup.py b/cursor_pro_keep_alive_backup.py new file mode 100644 index 0000000..9107d40 --- /dev/null +++ b/cursor_pro_keep_alive_backup.py @@ -0,0 +1,495 @@ +import sys +import psutil +import time +import random +from logger import info, warning, error +import traceback +from config import ( + LOGIN_URL, + SIGN_UP_URL, + SETTINGS_URL, + EMAIL_DOMAINS, + REGISTRATION_MAX_RETRIES, + EMAIL_TYPE, + EMAIL_CODE_TYPE +) + + +if sys.stdout.encoding != "utf-8": + sys.stdout.reconfigure(encoding="utf-8") +if sys.stderr.encoding != "utf-8": + sys.stderr.reconfigure(encoding="utf-8") + +from browser_utils import BrowserManager +from get_email_code import EmailVerificationHandler + +from datetime import datetime # 添加这行导入 + +TOTAL_USAGE = 0 + + +def handle_turnstile(tab): + info("=============正在检测 Turnstile 验证=============") + max_count = 5 + try: + count = 1 + while True: + if count > max_count: + error("Turnstile 验证次数超过最大限制,退出") + return False + info(f"正在进行 Turnstile 第 {count} 次验证中...") + try: + # 检查页面状态,但不直接返回,先检查是否有Turnstile验证需要处理 + page_ready = False + if tab.ele("@name=password"): + info("检测到密码输入页面,检查是否有验证需要处理...") + page_ready = True + elif tab.ele("@data-index=0"): + info("检测到验证码输入页面,检查是否有验证需要处理...") + page_ready = True + elif tab.ele("Account Settings"): + info("检测到账户设置页面,检查是否有验证需要处理...") + page_ready = True + + # 即使页面已经准备好,也检查是否有Turnstile验证需要处理 + info("检测 Turnstile 验证...") + try: + challengeCheck = ( + tab.ele("@id=cf-turnstile", timeout=2) + .child() + .shadow_root.ele("tag:iframe") + .ele("tag:body") + .sr("tag:input") + ) + + if challengeCheck: + info("检测到 Turnstile 验证,正在处理...") + challengeCheck.click() + time.sleep(2) + info("Turnstile 验证通过") + return True + else: + info("未检测到 Turnstile 验证") + except: + pass + # 如果页面已准备好且没有验证需要处理,则可以返回 + if page_ready: + info("页面已准备好,没有检测到需要处理的验证") + break + except: + pass + time.sleep(random.uniform(1, 2)) + count += 1 + return True # 返回True表示页面已准备好 + except Exception as e: + info(f"Turnstile 验证失败: {str(e)}") + return False + + +def get_cursor_session_token(tab, max_attempts=5, retry_interval=3): + try: + tab.get(SETTINGS_URL) + time.sleep(5) + try: + usage_selector = ( + "css:div.col-span-2 > div > div > div > div > " + "div:nth-child(1) > div.flex.items-center.justify-between.gap-2 > " + "span.font-mono.text-sm\\/\\[0\\.875rem\\]" + ) + usage_ele = tab.ele(usage_selector) + total_usage = "unknown" + if usage_ele: + total_usage = usage_ele.text.split("/")[-1].strip() + global TOTAL_USAGE + TOTAL_USAGE = total_usage + info(f"使用限制: {total_usage}") + else: + warning("未能找到使用量元素") + except Exception as e: + warning(f"获取使用量信息失败: {str(e)}") + # 继续执行,不要因为获取使用量失败而中断整个流程 + + info("获取Cookie中...") + attempts = 0 + + while attempts < max_attempts: + try: + cookies = tab.cookies() + for cookie in cookies: + if cookie.get("name") == "WorkosCursorSessionToken": + user = cookie["value"].split("%3A%3A")[0] + token = cookie["value"].split("%3A%3A")[1] + info(f"获取到账号Token: {token}, 用户: {user}") + return token, user + + attempts += 1 + if attempts < max_attempts: + warning( + f"未找到Cursor会话Token,重试中... ({attempts}/{max_attempts})" + ) + time.sleep(retry_interval) + else: + info("未找到Cursor会话Token,已达到最大尝试次数") + + except Exception as e: + info(f"获取Token出错: {str(e)}") + attempts += 1 + if attempts < max_attempts: + info( + f"重试获取Token,等待时间: {retry_interval}秒,尝试次数: {attempts}/{max_attempts}" + ) + time.sleep(retry_interval) + + return False + + except Exception as e: + warning(f"获取Token过程出错: {str(e)}") + return False + + +def sign_up_account(browser, tab, account_info): + info("=============开始注册账号=============") + info( + f"账号信息: 邮箱: {account_info['email']}, 密码: {account_info['password']}, 姓名: {account_info['first_name']} {account_info['last_name']}" + ) + if EMAIL_TYPE == "zmail": + EmailVerificationHandler.create_zmail_email(account_info) + tab.get(SIGN_UP_URL) + + tab.wait(2) + + if tab.ele("@name=cf-turnstile-response"): + error("开屏就是检测啊,大佬你的IP或UA需要换一下了啊,有问题了...要等一下") + + try: + if tab.ele("@name=first_name"): + info("=============正在填写个人信息=============") + tab.actions.click("@name=first_name").input(account_info["first_name"]) + info(f"已输入名字: {account_info['first_name']}") + time.sleep(random.uniform(1, 3)) + + tab.actions.click("@name=last_name").input(account_info["last_name"]) + info(f"已输入姓氏: {account_info['last_name']}") + time.sleep(random.uniform(1, 3)) + + tab.actions.click("@name=email").input(account_info["email"]) + info(f"已输入邮箱: {account_info['email']}") + time.sleep(random.uniform(1, 3)) + + info("=============提交个人信息=============") + tab.actions.click("@type=submit") + time.sleep(random.uniform(0.2, 1)) + if ( + tab.ele("verify the user is human. Please try again.") + or tab.ele("Can't verify the user is human. Please try again.") + or tab.ele("Can‘t verify the user is human. Please try again.") + ): + info("检测到turnstile验证失败,(IP问题、UA问题、域名问题)...正在重试...") + return "EMAIL_USED" + except Exception as e: + info(f"填写个人信息失败: {str(e)}") + return "ERROR" + + handle_turnstile(tab) + + if tab.ele("verify the user is human. Please try again.") or tab.ele( + "Can't verify the user is human. Please try again." + ): + info("检测到turnstile验证失败,正在重试...") + return "EMAIL_USED" + + try: + if tab.ele("@name=password"): + info(f"设置密码:{account_info['password']}") + tab.ele("@name=password").input(account_info["password"]) + time.sleep(random.uniform(1, 2)) + + info("提交密码...") + tab.ele("@type=submit").click() + info("密码设置成功,等待系统响应....") + + except Exception as e: + info(f"密码设置失败: {str(e)}") + return "ERROR" + + info("处理最终验证...") + handle_turnstile(tab) + + if tab.ele("This email is not available."): + info("邮箱已被使用") + return "EMAIL_USED" + + if tab.ele("Sign up is restricted."): + info("注册限制") + return "SIGNUP_RESTRICTED" + + # 创建邮件处理器 + email_handler = EmailVerificationHandler() + i = 0 + while i < 5: + try: + time.sleep(random.uniform(0.2, 1)) + if tab.ele("Account Settings"): + info("注册成功,已进入账号设置页面") + break + if tab.ele("@data-index=0"): + info("等待输入验证码...") + # 切换到邮箱标签页 + code = email_handler.get_verification_code( + source_email=account_info["email"] + ) + if code is None: + info("未获取到验证码...系统异常,正在退出....") + return "EMAIL_GET_CODE_FAILED" + info(f"输入验证码: {code}") + i = 0 + for digit in code: + tab.ele(f"@data-index={i}").input(digit) + time.sleep(random.uniform(0.3, 0.6)) + i += 1 + info("验证码输入完成") + time.sleep(random.uniform(3, 5)) + + # 在验证码输入完成后检测是否出现了Turnstile验证 + info("检查是否出现了Turnstile验证...") + try: + turnstile_element = tab.ele("@id=cf-turnstile", timeout=3) + if turnstile_element: + info("检测到验证码输入后出现Turnstile验证,正在处理...") + handle_turnstile(tab) + except: + info("未检测到Turnstile验证,继续下一步") + + break + except Exception as e: + info(f"验证码处理失败: {str(e)}") + return "ERROR" + + info("完成最终验证...") + handle_turnstile(tab) + time.sleep(random.uniform(3, 5)) + info("账号注册流程完成") + return "SUCCESS" + + +class EmailGenerator: + def __init__( + self, + ): + # 将密码生成移到这里,避免类定义时执行随机密码生成 + self.default_first_name = self.generate_random_name() + self.default_last_name = self.generate_random_name() + + # 从配置文件获取域名配置 + self.domains = EMAIL_DOMAINS + info(f"当前可用域名: {self.domains}") + + self.email = None + self.password = None + + def generate_random_password(self, length=12): + """生成随机密码 - 改进密码生成算法,确保包含各类字符""" + chars = "abcdefghijklmnopqrstuvwxyz" + upper_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + digits = "0123456789" + special = "!@#$%^&*" + + # 确保密码包含至少一个大写字母、一个数字和一个特殊字符 + password = [ + random.choice(chars), + random.choice(upper_chars), + random.choice(digits), + random.choice(special), + ] + + # 添加剩余随机字符 + password.extend( + random.choices(chars + upper_chars + digits + special, k=length - 4) + ) + + # 打乱密码顺序 + random.shuffle(password) + return "".join(password) + + def generate_random_name(self, length=6): + """生成随机用户名""" + first_letter = random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + rest_letters = "".join( + random.choices("abcdefghijklmnopqrstuvwxyz", k=length - 1) + ) + return first_letter + rest_letters + + def generate_email(self, length=8): + """生成随机邮箱地址,使用随机域名""" + random_str = "".join( + random.choices("abcdefghijklmnopqrstuvwxyz1234567890", k=length) + ) + timestamp = str(int(time.time()))[-4:] # 使用时间戳后4位 + # 随机选择一个域名 + domain = random.choice(self.domains) + return f"{random_str}@{domain}" + + def get_account_info(self): + """获取账号信息,确保每次调用都生成新的邮箱和密码""" + self.email = self.generate_email() + self.password = self.generate_random_password() + return { + "email": self.email, + "password": self.password, + "first_name": self.default_first_name.capitalize(), + "last_name": self.default_last_name.capitalize(), + } + + def _save_account_info(self, user, token, total_usage): + try: + from database import get_session, AccountModel + import asyncio + import time + + async def save_to_db(): + info(f"开始保存账号信息: {self.email}") + async with get_session() as session: + # 检查账号是否已存在 + from sqlalchemy import select + + result = await session.execute( + select(AccountModel).where(AccountModel.email == self.email) + ) + existing_account = result.scalar_one_or_none() + + if existing_account: + info(f"更新现有账号信息 (ID: {existing_account.id})") + existing_account.token = token + existing_account.user = user + existing_account.password = self.password + existing_account.usage_limit = str(total_usage) + # 如果账号状态是删除,更新为活跃 + if existing_account.status == "deleted": + existing_account.status = "active" + # 不更新id,保留原始id值 + else: + info("创建新账号记录") + # 生成毫秒级时间戳作为id + timestamp_ms = int(time.time() * 1000) + account = AccountModel( + email=self.email, + password=self.password, + token=token, + user=user, + usage_limit=str(total_usage), + created_at=datetime.now().strftime("%Y-%m-%d %H:%M"), + status="active", # 设置默认状态为活跃 + id=timestamp_ms, # 设置毫秒时间戳id + ) + session.add(account) + + await session.commit() + info(f"账号 {self.email} 信息保存成功") + return True + + return asyncio.run(save_to_db()) + except Exception as e: + info(f"保存账号信息失败: {str(e)}") + return False + + +def cleanup_and_exit(browser_manager=None, exit_code=0): + """清理资源并退出程序""" + try: + if browser_manager: + info("正在关闭浏览器") + if hasattr(browser_manager, "browser"): + browser_manager.browser.quit() + + current_process = psutil.Process() + children = current_process.children(recursive=True) + for child in children: + try: + child.terminate() + except: + pass + + info("程序正常退出") + sys.exit(exit_code) + + except Exception as e: + info(f"清理退出时发生错误: {str(e)}") + sys.exit(1) + + +def main(): + browser_manager = None + max_retries = REGISTRATION_MAX_RETRIES # 从配置文件获取 + current_retry = 0 + + try: + email_handler = EmailVerificationHandler() + if email_handler.check(): + info('邮箱服务连接正常,开始注册!') + else: + if EMAIL_CODE_TYPE == "API": + error('邮箱服务连接失败,并且验证码为API获取,结束注册!') + return + else: + info('邮箱服务连接失败,并且验证码为手动输入,等待输入验证码...') + + email_generator = EmailGenerator() + browser_manager = BrowserManager() + browser = browser_manager.init_browser() + while current_retry < max_retries: + try: + account_info = email_generator.get_account_info() + info( + f"初始化账号信息成功 => 邮箱: {account_info['email']}, 用户名: {account_info['first_name']}, 密码: {account_info['password']}" + ) + + signup_tab = browser.new_tab(LOGIN_URL) + browser.activate_tab(signup_tab) + + signup_tab.run_js("try { turnstile.reset() } catch(e) { }") + result = sign_up_account(browser, signup_tab, account_info) + + if result == "SUCCESS": + token, user = get_cursor_session_token(signup_tab) + info(f"获取到账号Token: {token}, 用户: {user}") + if token: + email_generator._save_account_info(user, token, TOTAL_USAGE) + info("注册流程完成") + cleanup_and_exit(browser_manager, 0) + else: + info("获取Cursor会话Token失败") + current_retry += 1 + elif result in [ + "EMAIL_USED", + "SIGNUP_RESTRICTED", + "VERIFY_FAILED", + "EMAIL_GET_CODE_FAILED", + ]: + info(f"遇到问题: {result},尝试切换邮箱...") + continue # 使用新邮箱重试注册 + else: # ERROR + info("遇到错误,准备重试...") + current_retry += 1 + + # 关闭标签页,准备下一次尝试 + signup_tab.close() + time.sleep(2) + + except Exception as e: + info(f"当前尝试发生错误: {str(e)}") + current_retry += 1 + time.sleep(2) + try: + # 尝试关闭可能存在的标签页 + if "signup_tab" in locals(): + signup_tab.close() + except: + pass + + info(f"达到最大重试次数 {max_retries},注册失败") + except Exception as e: + info(f"主程序错误: {str(e)}") + info(f"错误详情: {traceback.format_exc()}") + cleanup_and_exit(browser_manager, 1) + finally: + cleanup_and_exit(browser_manager, 1) diff --git a/cursor_shadow_patcher.py b/cursor_shadow_patcher.py new file mode 100644 index 0000000..e0783e7 --- /dev/null +++ b/cursor_shadow_patcher.py @@ -0,0 +1,288 @@ +import os +import re +import random +import shutil +import pathlib +import platform +from uuid import uuid4 +from logger import info, warning, error + +from config import CURSOR_PATH + + +# 颜色常量定义,保留用于日志输出 +GREEN = "\033[92m" +RED = "\033[91m" +YELLOW = "\033[93m" +BLUE = "\033[96m" +PURPLE = "\033[95m" +RESET = "\033[0m" + +SYSTEM = platform.system() +if SYSTEM not in ("Windows", "Linux", "Darwin"): + raise OSError(f"不支持的操作系统: {SYSTEM}") + + +def uuid(): + """生成随机UUID""" + return str(uuid4()) + + +def path(path_str): + """获取绝对路径""" + return pathlib.Path(path_str).resolve() + + +def randomuuid(randomuuid_str): + """获取随机UUID,如果提供则使用提供的值""" + if not randomuuid_str: + randomuuid_str = uuid() + return randomuuid_str + + +def random_mac(): + """生成随机MAC地址""" + mac = [ + 0x00, + 0x16, + 0x3E, + random.randint(0x00, 0x7F), + random.randint(0x00, 0xFF), + random.randint(0x00, 0xFF), + ] + return ":".join(map(lambda x: "%02x" % x, mac)) + + +def load(file_path: pathlib.Path): + """加载文件内容""" + with open(file_path, "rb") as f: + return f.read() + + +def save(file_path: pathlib.Path, data: bytes): + """保存文件内容""" + with open(file_path, "wb") as f: + f.write(data) + + +def backup(file_path: pathlib.Path): + """备份文件""" + backup_path = file_path.with_suffix(file_path.suffix + ".bak") + if not backup_path.exists(): + shutil.copy2(file_path, backup_path) + print(f"已备份 {file_path} -> {backup_path}") + + +def replace(data: bytes, pattern: str, replace_str: str, probe: str = None) -> bytes: + """替换文件内容""" + pattern_bytes = pattern.encode() if isinstance(pattern, str) else pattern + replace_bytes = ( + replace_str.encode() if isinstance(replace_str, str) else replace_str + ) + + if probe: + probe_bytes = probe.encode() if isinstance(probe, str) else probe + if re.search(probe_bytes, data): + print("检测到已经被修补的代码,跳过...") + return data + + return re.sub(pattern_bytes, replace_bytes, data) + + +def find_main_js(): + """查找Cursor的main.js文件""" + error(f"SYSTEM: {SYSTEM}") + if SYSTEM == "Windows": + localappdata = os.getenv("LOCALAPPDATA") + if not localappdata: + raise OSError("环境变量 %LOCALAPPDATA% 不存在") + + # 使用本地变量保存路径 + cursor_path = CURSOR_PATH + if not cursor_path: + error("当前windows系统, 环境变量 CURSOR_PATH 不存在,使用默认路径") + cursor_path = os.getenv("LOCALAPPDATA", "") + else: + info(f"当前windows系统, CURSOR_PATH: {cursor_path}") + + # 常见的Cursor安装路径 + paths = [ + path(os.path.join(cursor_path, "resources", "app", "out", "main.js")), + path( + os.path.join( + localappdata, + "Programs", + "cursor", + "resources", + "app", + "out", + "main.js", + ) + ), + path( + os.path.join( + localappdata, "cursor", "resources", "app", "out", "main.js" + ) + ), + ] + + for p in paths: + info(f"检查路径: {p}") + if p.exists(): + info(f"找到main.js: {p}") + return p + else: + warning(f"路径不存在: {p}") + + elif SYSTEM == "Darwin": # macOS + paths = [ + path("/Applications/Cursor.app/Contents/Resources/app/out/main.js"), + path( + os.path.expanduser( + "~/Applications/Cursor.app/Contents/Resources/app/out/main.js" + ) + ), + ] + + for p in paths: + if p.exists(): + return p + + elif SYSTEM == "Linux": + # Linux上常见的安装路径 + paths = [ + path("/usr/share/cursor/resources/app/out/main.js"), + path(os.path.expanduser("~/.local/share/cursor/resources/app/out/main.js")), + ] + + for p in paths: + if p.exists(): + return p + + raise FileNotFoundError("无法找到Cursor的main.js文件,请手动指定路径") + + +def patch_cursor( + js_path=None, machine_id=None, mac_addr=None, sqm_id=None, dev_id=None +): + """ + 修补Cursor的main.js文件,替换机器ID等识别信息 + + 参数: + js_path: main.js文件路径,如果为None则自动查找 + machine_id: 机器ID,如果为None则随机生成 + mac_addr: MAC地址,如果为None则随机生成 + sqm_id: Windows SQM ID,如果为None则使用空字符串 + dev_id: 设备ID,如果为None则随机生成 + + 返回: + bool: 是否成功 + """ + try: + # 查找main.js文件 + if not js_path: + js_path = find_main_js() + else: + js_path = path(js_path) + + # 如果找不到main.js文件 + if not js_path.exists(): + print(f"错误: 找不到文件 {js_path}") + return False + + print(f"找到main.js文件: {js_path}") + + # 随机生成ID + machine_id = randomuuid(machine_id) + mac_addr = mac_addr or random_mac() + sqm_id = sqm_id or "" + dev_id = randomuuid(dev_id) + + # 加载文件内容 + data = load(js_path) + + # 备份文件 + backup(js_path) + + # 替换机器ID + data = replace( + data, + r"=.{0,50}timeout.{0,10}5e3.*?,", + f'=/*csp1*/"{machine_id}"/*1csp*/,', + r"=/\*csp1\*/.*?/\*1csp\*/,", + ) + + # 替换MAC地址 + data = replace( + data, + r"(function .{0,50}\{).{0,300}Unable to retrieve mac address.*?(\})", + f'\\1return/*csp2*/"{mac_addr}"/*2csp*/;\\2', + r"()return/\*csp2\*/.*?/\*2csp\*/;()", + ) + + # 替换SQM ID + data = replace( + data, + r'return.{0,50}\.GetStringRegKey.*?HKEY_LOCAL_MACHINE.*?MachineId.*?\|\|.*?""', + f'return/*csp3*/"{sqm_id}"/*3csp*/', + r"return/\*csp3\*/.*?/\*3csp\*/", + ) + + # 替换设备ID + data = replace( + data, + r"return.{0,50}vscode\/deviceid.*?getDeviceId\(\)", + f'return/*csp4*/"{dev_id}"/*4csp*/', + r"return/\*csp4\*/.*?/\*4csp\*/", + ) + + # 保存修改后的文件 + save(js_path, data) + + print(f"成功修补 {js_path}") + print(f"机器ID: {machine_id}") + print(f"MAC地址: {mac_addr}") + print(f"SQM ID: {sqm_id}") + print(f"设备ID: {dev_id}") + + return True + + except Exception as e: + print(f"错误: {str(e)}") + import traceback + + traceback.print_exc() + return False + + +class CursorShadowPatcher: + """Cursor机器标识修改器""" + + @staticmethod + def reset_machine_ids(): + """重置所有机器标识""" + return patch_cursor() + + +if __name__ == "__main__": + # 作为独立脚本运行时,执行交互式修补 + print(f"\n{'=' * 50}") + print("Cursor 机器标识重置工具 (Shadow Patch 增强版)") + print(f"{'=' * 50}") + + js_path = input("请输入main.js路径 (留空=自动检测): ") + machine_id = input("机器ID (留空=随机生成): ") + mac_addr = input("MAC地址 (留空=随机生成): ") + sqm_id = input("Windows SQM ID (留空=使用空值): ") + dev_id = input("设备ID (留空=随机生成): ") + + success = patch_cursor(js_path, machine_id, mac_addr, sqm_id, dev_id) + + if success: + print(f"\n{'=' * 50}") + print("修补成功!") + else: + print(f"\n{'=' * 50}") + print("修补失败!") + + input("按回车键退出...") diff --git a/database.py b/database.py new file mode 100644 index 0000000..8a441e6 --- /dev/null +++ b/database.py @@ -0,0 +1,93 @@ +from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker +from sqlalchemy.orm import DeclarativeBase +from sqlalchemy import Column, String, Text, text, BigInteger, ForeignKey +from contextlib import asynccontextmanager +from logger import info, error +from config import DATABASE_URL + + +# 基础模型类 +class Base(DeclarativeBase): + pass + + +# 账号模型 +class AccountModel(Base): + __tablename__ = "accounts" + email = Column(String, primary_key=True) + user = Column(String, nullable=False) + password = Column(String, nullable=True) + token = Column(String, nullable=False) + usage_limit = Column(Text, nullable=True) + created_at = Column(Text, nullable=True) + status = Column(String, default="active", nullable=False) + id = Column(BigInteger, nullable=False, index=True) # 添加毫秒时间戳列并创建索引 + + +# 账号使用记录模型 +class AccountUsageRecordModel(Base): + __tablename__ = "account_usage_records" + id = Column(BigInteger, primary_key=True, autoincrement=True) + account_id = Column(BigInteger, nullable=False, index=True) # 账号ID + email = Column(String, nullable=False, index=True) # 账号邮箱 + ip = Column(String, nullable=True) # 使用者IP + user_agent = Column(Text, nullable=True) # 使用者UA + created_at = Column(Text, nullable=False) # 创建时间 + + +def create_engine(): + """创建数据库引擎""" + # 直接使用配置文件中的数据库URL + engine = create_async_engine( + DATABASE_URL, + echo=False, + connect_args={"check_same_thread": False} if "sqlite" in DATABASE_URL else {}, + future=True, + ) + # info(f"数据库引擎创建成功: {DATABASE_URL}") + return engine + + +@asynccontextmanager +async def get_session() -> AsyncSession: + """创建数据库会话的异步上下文管理器""" + # 为每个请求创建新的引擎和会话 + engine = create_engine() + async_session = async_sessionmaker( + engine, class_=AsyncSession, expire_on_commit=False, future=True + ) + + session = async_session() + try: + # 确保连接有效 + await session.execute(text("SELECT 1")) + yield session + except Exception as e: + error(f"数据库会话错误: {str(e)}") + try: + await session.rollback() + except Exception as rollback_error: + error(f"回滚过程中出错: {str(rollback_error)}") + raise + finally: + try: + await session.close() + except Exception as e: + error(f"关闭会话时出错: {str(e)}") + try: + await engine.dispose() + except Exception as e: + error(f"释放引擎时出错: {str(e)}") + + +async def init_db(): + """初始化数据库表结构""" + try: + engine = create_engine() + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + await engine.dispose() + info("数据库初始化成功") + except Exception as e: + error(f"数据库初始化失败: {str(e)}") + raise diff --git a/deno脚本 b/deno脚本 new file mode 100644 index 0000000..99df652 --- /dev/null +++ b/deno脚本 @@ -0,0 +1,110 @@ +/** + * 导入Deno标准库中的HTTP服务器模块 + */ +import { serve } from "https://deno.land/std/http/server.ts"; + +/** + * API映射表,定义了路由前缀到实际API端点的映射关系 + * 用于将请求转发到相应的第三方服务 + */ +const apiMapping = { + '/discord': 'https://discord.com/api', // Discord API + '/telegram': 'https://api.telegram.org', // Telegram API + '/openai': 'https://api.openai.com', // OpenAI API + '/claude': 'https://api.anthropic.com', // Anthropic Claude API + '/gemini': 'https://generativelanguage.googleapis.com', // Google Gemini API + '/meta': 'https://www.meta.ai/api', // Meta AI API + '/groq': 'https://api.groq.com/openai', // Groq API (OpenAI兼容) + '/xai': 'https://api.x.ai', // X.AI API + '/cohere': 'https://api.cohere.ai', // Cohere API + '/huggingface': 'https://api-inference.huggingface.co', // Hugging Face API + '/together': 'https://api.together.xyz', // Together AI API + '/novita': 'https://api.novita.ai', // Novita AI API + '/portkey': 'https://api.portkey.ai', // Portkey API + '/fireworks': 'https://api.fireworks.ai', // Fireworks AI API + '/openrouter': 'https://openrouter.ai/api' // OpenRouter API +}; + +/** + * 启动HTTP服务器,处理所有传入的请求 + */ +serve(async (request) => { + // 解析请求URL + const url = new URL(request.url); + const pathname = url.pathname; + + // 处理根路径和index.html请求 + if (pathname === '/' || pathname === '/index.html') { + return new Response('Service is running!', { + status: 200, + headers: { 'Content-Type': 'text/html' } + }); + } + + // 处理robots.txt请求,禁止搜索引擎爬取 + if (pathname === '/robots.txt') { + return new Response('User-agent: *\nDisallow: /', { + status: 200, + headers: { 'Content-Type': 'text/plain' } + }); + } + + // 从请求路径中提取API前缀和剩余路径 + const [prefix, rest] = extractPrefixAndRest(pathname, Object.keys(apiMapping)); + if (!prefix) { + return new Response('Not Found', { status: 404 }); + } + + // 构建目标URL + const targetUrl = `${apiMapping[prefix]}${rest}`; + + try { + // 创建新的请求头,只保留允许的头部信息 + const headers = new Headers(); + const allowedHeaders = ['accept', 'content-type', 'authorization']; + for (const [key, value] of request.headers.entries()) { + if (allowedHeaders.includes(key.toLowerCase())) { + headers.set(key, value); + } + } + + // 转发请求到目标API + const response = await fetch(targetUrl, { + method: request.method, + headers: headers, + body: request.body + }); + + // 设置安全相关的响应头 + const responseHeaders = new Headers(response.headers); + responseHeaders.set('X-Content-Type-Options', 'nosniff'); + responseHeaders.set('X-Frame-Options', 'DENY'); + responseHeaders.set('Referrer-Policy', 'no-referrer'); + + // 返回API响应 + return new Response(response.body, { + status: response.status, + headers: responseHeaders + }); + + } catch (error) { + // 处理请求错误 + console.error('Failed to fetch:', error); + return new Response('Internal Server Error', { status: 500 }); + } +}); + +/** + * 从路径中提取API前缀和剩余部分 + * @param {string} pathname - 请求路径 + * @param {string[]} prefixes - 可用的API前缀列表 + * @returns {[string|null, string|null]} - 返回匹配的前缀和剩余路径,如果没有匹配则返回[null, null] + */ +function extractPrefixAndRest(pathname, prefixes) { + for (const prefix of prefixes) { + if (pathname.startsWith(prefix)) { + return [prefix, pathname.slice(prefix.length)]; + } + } + return [null, null]; +} \ No newline at end of file diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..7e0d10a --- /dev/null +++ b/dockerfile @@ -0,0 +1,34 @@ +# Dockerfile for cursor-auto-register + +# 1. 选择 Python 基础镜像 +FROM python:3.10-slim + +# 2. 设置环境变量,防止 Python 缓冲输出 +ENV PYTHONUNBUFFERED=1 + +# 3. 设置工作目录 +WORKDIR /app + +# 4. 复制依赖文件 +COPY requirements.txt . + +# 5. 安装系统依赖 (针对 Playwright) 和 Python 依赖 +# 更新 apt 包列表,安装 Playwright 所需的依赖,然后安装 Python 包,最后清理 apt 缓存 +RUN apt-get update && \ + apt-get install -y --no-install-recommends libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libdbus-1-3 libatspi2.0-0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libxkbcommon0 libpango-1.0-0 libcairo2 libasound2 && \ + pip install --no-cache-dir -r requirements.txt && \ + # 下载 Playwright 浏览器 (chromium, firefox, webkit 可按需选择) + playwright install --with-deps chromium && \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false && \ + rm -rf /var/lib/apt/lists/* + +# 6. 复制项目代码到工作目录 +COPY . . + +# 7. 暴露应用程序端口 (根据 .env 文件配置,默认为 8000) +EXPOSE 8000 + +# 8. 定义容器启动时运行的命令 +# 使用 uvicorn 启动 FastAPI 应用 +# 确保 api.py 中 FastAPI app 实例的变量名为 'app' +CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/get_cursor_session_token_re.py b/get_cursor_session_token_re.py new file mode 100644 index 0000000..f2abefb --- /dev/null +++ b/get_cursor_session_token_re.py @@ -0,0 +1,81 @@ +def get_cursor_session_token(tab, max_attempts: int = 3, retry_interval: int = 2) -> Optional[Tuple[str, str]]: + """ + 获取Cursor会话token + + Args: + tab: 浏览器标签页对象 + max_attempts: 最大尝试次数 + retry_interval: 重试间隔(秒) + + Returns: + Tuple[str, str] | None: 成功返回(userId, accessToken)元组,失败返回None + """ + logging.info("开始获取会话令牌") + + # 首先尝试使用UUID深度登录方式 + logging.info("尝试使用深度登录方式获取token") + + def _generate_pkce_pair(): + """生成PKCE验证对""" + code_verifier = secrets.token_urlsafe(43) # 生成随机的code_verifier + code_challenge_digest = hashlib.sha256(code_verifier.encode('utf-8')).digest() # 对verifier进行SHA256哈希 + code_challenge = base64.urlsafe_b64encode(code_challenge_digest).decode('utf-8').rstrip('=') # Base64编码并移除填充字符 + return code_verifier, code_challenge + + attempts = 0 + while attempts < max_attempts: + try: + verifier, challenge = _generate_pkce_pair() # 生成PKCE验证对 + id = uuid.uuid4() # 生成唯一的UUID + client_login_url = f"https://www.cursor.com/cn/loginDeepControl?challenge={challenge}&uuid={id}&mode=login" # 构建深度登录URL + + logging.info(f"访问深度登录URL: {client_login_url}") + tab.get(client_login_url) # 访问登录页面 + save_screenshot(tab, f"deeplogin_attempt_{attempts}") # 保存登录页面截图 + + if tab.ele("xpath=//span[contains(text(), 'Yes, Log In')]", timeout=5): # 查找登录确认按钮 + logging.info("点击确认登录按钮") + tab.ele("xpath=//span[contains(text(), 'Yes, Log In')]").click() # 点击确认登录 + time.sleep(1.5) # 等待页面响应 + + auth_poll_url = f"https://api2.cursor.sh/auth/poll?uuid={id}&verifier={verifier}" # 构建认证轮询URL + headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Cursor/0.48.6 Chrome/132.0.6834.210 Electron/34.3.4 Safari/537.36", + "Accept": "*/*" + } # 设置请求头 + + logging.info(f"轮询认证状态: {auth_poll_url}") + response = requests.get(auth_poll_url, headers=headers, timeout=5) # 发送认证状态轮询请求 + + if response.status_code == 200: # 请求成功 + data = response.json() # 解析JSON响应 + accessToken = data.get("accessToken", None) # 获取访问令牌 + authId = data.get("authId", "") # 获取认证ID + + if accessToken: # 如果成功获取到访问令牌 + userId = "" + if len(authId.split("|")) > 1: # 从authId中提取userId + userId = authId.split("|")[1] + + logging.info("成功获取账号token和userId") + return userId, accessToken # 返回用户ID和访问令牌 + else: + logging.error(f"API请求失败,状态码: {response.status_code}") # 记录API请求失败 + else: + logging.warning("未找到登录确认按钮") # 记录未找到登录按钮 + + attempts += 1 # 增加尝试次数 + if attempts < max_attempts: # 如果还有重试机会 + wait_time = retry_interval * attempts # 计算等待时间,逐步增加 + logging.warning(f"第 {attempts} 次尝试未获取到token,{wait_time}秒后重试...") + save_screenshot(tab, f"token_attempt_{attempts}") # 保存失败截图 + time.sleep(wait_time) # 等待指定时间后重试 + + except Exception as e: # 捕获所有异常 + logging.error(f"深度登录获取token失败: {str(e)}") # 记录异常信息 + attempts += 1 # 增加尝试次数 + save_screenshot(tab, f"token_error_{attempts}") # 保存错误截图 + if attempts < max_attempts: # 如果还有重试机会 + wait_time = retry_interval * attempts # 计算等待时间 + logging.warning(f"将在 {wait_time} 秒后重试...") + time.sleep(wait_time) # 等待指定时间后重试 \ No newline at end of file diff --git a/get_email_code.py b/get_email_code.py new file mode 100644 index 0000000..9122bbc --- /dev/null +++ b/get_email_code.py @@ -0,0 +1,464 @@ +from logger import info, error +# 添加warn函数作为info的包装 +def warn(message): + """警告日志函数""" + info(f"警告: {message}") + +import time +import re +import requests +from config import ( + EMAIL_USERNAME, + EMAIL_DOMAIN, + EMAIL_PIN, + EMAIL_VERIFICATION_RETRIES, + EMAIL_VERIFICATION_WAIT, + EMAIL_TYPE, + EMAIL_PROXY_ADDRESS, + EMAIL_PROXY_ENABLED, + EMAIL_API, + EMAIL_CODE_TYPE +) + + +class EmailVerificationHandler: + def __init__(self, username=None, domain=None, pin=None, use_proxy=False): + self.email = EMAIL_TYPE + self.username = username or EMAIL_USERNAME + self.domain = domain or EMAIL_DOMAIN + self.session = requests.Session() + self.emailApi = EMAIL_API + self.emailExtension = self.domain + self.pin = pin or EMAIL_PIN + if self.pin == "": + info("注意: 邮箱PIN码为空") + if self.email == "tempemail": + info( + f"初始化邮箱验证器成功: {self.username}@{self.domain} pin: {self.pin}" + ) + elif self.email == "zmail": + info( + f"初始化邮箱验证器成功: {self.emailApi}" + ) + + # 添加代理支持 + if use_proxy and EMAIL_PROXY_ENABLED: + proxy = { + "http": f"{EMAIL_PROXY_ADDRESS}", + "https": f"{EMAIL_PROXY_ADDRESS}", + } + self.session.proxies.update(proxy) + info(f"已启用代理: {EMAIL_PROXY_ADDRESS}") + + def check(self): + mail_list_url = f"https://tempmail.plus/api/mails?email={self.username}%40{self.domain}&limit=20&epin={self.pin}" + try: + # 增加超时时间并添加错误重试 + for retry in range(3): + try: + info(f"请求URL (尝试 {retry+1}/3): {mail_list_url}") + mail_list_response = self.session.get(mail_list_url, timeout=30) # 增加超时时间到30秒 + mail_list_data = mail_list_response.json() + time.sleep(0.5) + + # 修正判断逻辑:当result为true时才是成功 + if mail_list_data.get("result") == True: + info(f"成功获取邮件列表数据: 共{mail_list_data.get('count', 0)}封邮件") + return True + else: + error(f"API返回结果中无result字段或result为false: {mail_list_data}") + return False + + except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: + if retry < 2: # 如果不是最后一次尝试 + warn(f"请求超时或连接错误,正在重试... ({retry+1}/3)") + time.sleep(2) # 增加重试间隔 + else: + raise # 最后一次尝试失败,抛出异常 + except requests.exceptions.Timeout: + error("获取邮件列表超时") + except requests.exceptions.ConnectionError: + error("获取邮件列表连接错误") + info(f'{mail_list_url}') + except Exception as e: + error(f"获取邮件列表发生错误: {str(e)}") + return False + + def get_verification_code( + self, source_email=None, max_retries=None, wait_time=None + ): + """ + 获取验证码,增加了重试机制 + + Args: + max_retries: 最大重试次数 + wait_time: 每次重试间隔时间(秒) + + Returns: + str: 验证码或None + """ + # 如果邮箱验证码获取方式为输入,则直接返回输入的验证码 + if EMAIL_CODE_TYPE == "INPUT": + info("EMAIL_CODE_TYPE设为INPUT,跳过自动获取,直接手动输入") + return self.prompt_manual_code() + + max_retries = max_retries or EMAIL_VERIFICATION_RETRIES + wait_time = wait_time or EMAIL_VERIFICATION_WAIT + info(f"开始获取邮箱验证码=>最大重试次数:{max_retries}, 等待时间:{wait_time}") + + # 验证邮箱类型是否支持 + if self.email not in ["tempemail", "zmail"]: + error(f"不支持的邮箱类型: {self.email},支持的类型为: tempemail, zmail") + warn("自动切换到手动输入模式") + return self.prompt_manual_code() + + for attempt in range(max_retries): + try: + info(f"当前EMail类型为: {self.email}") + code = None + mail_id = None + + if self.email == "tempemail": + code, mail_id = self.get_tempmail_email_code(source_email) + elif self.email == "zmail": + code, mail_id = self.get_zmail_email_code(source_email) + + if code: + info(f"成功获取验证码: {code}") + return code + elif attempt < max_retries - 1: + info(f"未找到验证码,{wait_time}秒后重试 ({attempt + 1}/{max_retries})...") + time.sleep(wait_time) + else: + info(f"已达到最大重试次数({max_retries}),未找到验证码") + except Exception as e: + error(f"获取验证码失败: {str(e)}") + if attempt < max_retries - 1: + info(f"将在{wait_time}秒后重试...") + time.sleep(wait_time) + else: + error(f"已达到最大重试次数({max_retries}),获取验证码失败") + + # 所有自动尝试都失败后,询问是否手动输入 + response = input("自动获取验证码失败,是否手动输入? (y/n): ").lower() + if response == 'y': + return self.prompt_manual_code() + return None + + # 手动输入验证码 + def prompt_manual_code(self): + """手动输入验证码""" + info("自动获取验证码失败,开始手动输入验证码。") + code = input("输入6位数字验证码: ").strip() + return code + + def get_tempmail_email_code(self, source_email=None): + info("开始获取邮件列表") + # 获取邮件列表 + mail_list_url = f"https://tempmail.plus/api/mails?email={self.username}%40{self.domain}&limit=20&epin={self.pin}" + try: + # 增加错误重试和超时时间 + for retry in range(3): + try: + info(f"请求邮件列表 (尝试 {retry+1}/3): {mail_list_url}") + mail_list_response = self.session.get( + mail_list_url, timeout=30 + ) + mail_list_data = mail_list_response.json() + time.sleep(0.5) + + # 修正判断逻辑 + if mail_list_data.get("result") == True: + info(f"成功获取邮件列表: 共{mail_list_data.get('count', 0)}封邮件") + # 继续处理 + else: + error(f"API返回失败结果: {mail_list_data}") + return None, None + + break # 成功获取数据,跳出重试循环 + except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: + if retry < 2: # 如果不是最后一次尝试 + warn(f"请求超时或连接错误,正在重试... ({retry+1}/3)") + time.sleep(2 * (retry + 1)) # 递增的等待时间 + else: + raise # 最后一次尝试失败,抛出异常 + + # 获取最新邮件的ID + first_id = mail_list_data.get("first_id") + if not first_id: + return None, None + info(f"开始获取邮件详情: {first_id}") + # 获取具体邮件内容 + mail_detail_url = f"https://tempmail.plus/api/mails/{first_id}?email={self.username}%40{self.domain}&epin={self.pin}" + try: + mail_detail_response = self.session.get( + mail_detail_url, timeout=10 + ) # 添加超时参数 + mail_detail_data = mail_detail_response.json() + time.sleep(0.5) + if mail_detail_data.get("result") == False: + error(f"获取邮件详情失败: {mail_detail_data}") + return None, None + except requests.exceptions.Timeout: + error("获取邮件详情超时") + return None, None + except requests.exceptions.ConnectionError: + error("获取邮件详情连接错误") + return None, None + except Exception as e: + error(f"获取邮件详情发生错误: {str(e)}") + return None, None + + # 从邮件文本中提取6位数字验证码 + mail_text = mail_detail_data.get("text", "") + + # 如果提供了source_email,确保邮件内容中包含该邮箱地址 + if source_email and source_email.lower() not in mail_text.lower(): + error(f"邮件内容不包含指定的邮箱地址: {source_email}") + else: + info(f"邮件内容包含指定的邮箱地址: {source_email}") + + code_match = re.search(r"(? bool: + """ + 处理Turnstile验证 + + Args: + tab: 浏览器标签对象 + max_retries: 最大重试次数 + retry_interval: 重试间隔范围(最小值, 最大值) + + Returns: + bool: 验证是否成功 + + Raises: + TurnstileError: 验证过程中的异常 + """ + # 如果没有传入tab参数,则使用实例的tab属性 + tab = tab or self.tab + + # 记录开始检测Turnstile验证的日志 + logging.info(get_translation("detecting_turnstile")) + # 保存验证开始前的屏幕截图 + save_screenshot(tab, "start") + + # 初始化重试计数器 + retry_count = 0 + + try: + # 在最大重试次数内循环尝试验证 + while retry_count < max_retries: + # 增加重试计数 + retry_count += 1 + # 记录当前是第几次尝试验证 + logging.debug(get_translation("retry_verification", count=retry_count)) + + try: + # 初始化元素变量 + element = None + try: + # 尝试通过层级结构定位到Turnstile验证框的容器元素 + element = ( + tab.ele(".main-content") # 找到 .main-content 元素 + .ele("tag:div") # 找到第一个子 div + .ele("tag:div") # 找到第二个子 div + .ele("tag:div") # 找到第三个子 div + ) + except Exception as e: + # 如果无法通过第一种方式找到元素,忽略异常继续执行 + pass + + if element: + # 如果找到了容器元素,则在其中定位验证框的输入元素 + challenge_check = ( + element + .shadow_root.ele("tag:iframe") # 找到shadow DOM中的iframe + .ele("tag:body") # 找到iframe中的body + .sr("tag:input") # 找到body中的input元素 + ) + else: + # 如果没有找到容器元素,则尝试另一种方式定位验证框 + challenge_check = ( + tab.ele("@id=cf-turnstile", timeout=2) # 通过id直接找到turnstile元素 + .child() # 获取其子元素 + .shadow_root.ele("tag:iframe") # 找到shadow DOM中的iframe + .ele("tag:body") # 找到iframe中的body + .sr("tag:input") # 找到body中的input元素 + ) + + if challenge_check: + # 如果找到了验证输入元素,记录日志 + logging.info(get_translation("detected_turnstile")) + # 点击前随机延迟,模拟人工操作 + time.sleep(random.uniform(1, 3)) + # 点击验证元素触发验证 + challenge_check.click() + # 等待验证处理 + time.sleep(2) + + # 保存点击验证后的屏幕截图 + save_screenshot(tab, "clicked") + + # 检查验证是否成功 + if check_verification_success(tab): + # 验证成功,记录日志 + logging.info(get_translation("turnstile_verification_passed")) + # 保存验证成功的屏幕截图 + save_screenshot(tab, "success") + # 返回验证成功 + return True + + except Exception as e: + # 记录当前尝试失败的详细信息 + logging.debug(f"Current attempt unsuccessful: {str(e)}") + + # 再次检查验证是否已经成功(可能在异常处理过程中已经通过验证) + if check_verification_success(tab): + # 返回验证成功 + return True + + # 在下一次尝试前随机延迟 + time.sleep(random.uniform(*retry_interval)) + + # 超过最大重试次数,验证失败 + logging.error(get_translation("verification_failed_max_retries", max_retries=max_retries)) + # 提供额外的帮助信息,引导用户访问开源项目 + logging.error( + "Please visit the open source project for more information: https://github.com/wangffei/wf-cursor-auto-free.git" + ) + # 保存验证失败的屏幕截图 + save_screenshot(tab, "failed") + # 返回验证失败 + return False + + except Exception as e: + # 捕获整个验证过程中的异常 + # 构建错误信息 + error_msg = get_translation("turnstile_exception", error=str(e)) + # 记录错误日志 + logging.error(error_msg) + # 保存发生错误时的屏幕截图 + save_screenshot(tab, "error") + # 抛出TurnstileError异常 + raise TurnstileError(error_msg) \ No newline at end of file diff --git a/images/1.jpg b/images/1.jpg new file mode 100644 index 0000000..e3ec04e Binary files /dev/null and b/images/1.jpg differ diff --git a/images/2.jpg b/images/2.jpg new file mode 100644 index 0000000..86d824a Binary files /dev/null and b/images/2.jpg differ diff --git a/images/3.jpg b/images/3.jpg new file mode 100644 index 0000000..cb5a35f Binary files /dev/null and b/images/3.jpg differ diff --git a/images/4.jpg b/images/4.jpg new file mode 100644 index 0000000..65807b7 Binary files /dev/null and b/images/4.jpg differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..e958447 --- /dev/null +++ b/index.html @@ -0,0 +1,644 @@ + + + + + + + + Cursor账号管理系统 + + + + + + + + + + + + + + + + + +
+
+
+ 加载中... +
+

加载中,请稍候...

+
+
+ + +
+ + + + + +
+ +
+
+
+
+
+
任务控制
+
空闲中
+
+
+
+
+
+
+ + 系统空闲中,可以开始新任务 +
+ + +
+
+ 0 + / + 10 + 剩余: 10 +
+
+
+ + + + + + + + + + +
+ 0% +
+
+
+
+
+ + + +
+
+ + +
+
+
+
+
+
+ 上次运行: + 从未运行 +
+
+ 下次运行: + 未排程 +
+
+
+
+ 总运行次数: + 0 +
+
+ 成功率: + N/A + + (0 成功 / + 0 失败) + +
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +
+
+
+
+
账号列表
+
+
+
+ + + + + + + + + + + + + + + +
邮箱密码TOKEN高级使用创建时间余量操作
+
+
+
+
+
+ + +
+
+
+ 共 0 个账号, + 第 1/1 页 +
+ + + +
+ +
+
+
+
+ + +
+
+
+
+
+
系统配置
+
+
+ +
+
+
+
+ + + True=无界面运行浏览器,False=显示浏览器界面 +
+
+ +
+ + +
+ (建议不要)启用后将从预设的UA列表中随机选择,无需手动配置User-Agent +
+
+ + + 浏览器模拟的用户代理字符串 +
+
+ + + Windows下浏览器可执行文件的完整路径(示例:C:\Users\Administrator\AppData\Local\Google\Chrome\Bin\chrome.exe) +
+
+ + + 系统允许创建的最大账号数量 +
+ + +
+ + + 选择验证码的获取方式:API自动获取或通过控制台手动输入 +
+
+
+
+ + + 选择用于注册的临时邮箱服务类型 +
+
+ + + 用于注册的邮箱域名,多个域名用逗号分隔 +
+ + +
+
+ + + 用于接收验证码的临时邮箱用户名(不需要输入@及后面的部分) +
+
+ + + 临时邮箱PIN码(如果需要) +
+
+ + + +
+ + + Cursor安装目录的完整路径(示例:D:\devtools\cursor) +
+
+ +
+
+
代理服务器设置
+
+
+
+ + +
+ +
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+
+ + + + +
+ +
+
+ +
+
+
系统维护
+
+
+
+
+ +

某些配置更改需要重启服务才能生效

+
+
+ +

解决设备绑定或配额限制问题

+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + +
+
+ 自动刷新(60秒/次) +
+ Loading... +
+
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/logger.py b/logger.py new file mode 100644 index 0000000..3769f0e --- /dev/null +++ b/logger.py @@ -0,0 +1,32 @@ +import logging +import sys +from config import LOG_LEVEL, LOG_FORMAT, LOG_DATE_FORMAT + +# 配置日志 +logging.basicConfig( + level=getattr(logging, LOG_LEVEL), + format=LOG_FORMAT, + datefmt=LOG_DATE_FORMAT, + handlers=[ + logging.StreamHandler(sys.stdout), + logging.FileHandler("app.log", encoding="utf-8"), + ], +) + +logger = logging.getLogger() + + +def info(message): + logger.info(message) + + +def warning(message): + logger.warning(message) + + +def error(message): + logger.error(message) + + +def debug(message): + logger.debug(message) diff --git a/migrate_add_id.py b/migrate_add_id.py new file mode 100644 index 0000000..5e36e76 --- /dev/null +++ b/migrate_add_id.py @@ -0,0 +1,32 @@ +import asyncio +import time +from sqlalchemy import select +from database import init_db, get_session, AccountModel + + +async def migrate_add_id(): + """为现有记录添加ID字段""" + await init_db() + + async with get_session() as session: + # 查询所有没有id的记录 + result = await session.execute( + select(AccountModel).where(AccountModel.id == None) + ) + accounts = result.scalars().all() + + print(f"找到 {len(accounts)} 条需要更新的记录") + + # 为每条记录添加id + for i, account in enumerate(accounts): + # 生成基于索引的间隔时间戳,避免所有记录使用同一时间戳 + timestamp_ms = int(time.time() * 1000) - (len(accounts) - i) * 1000 + account.id = timestamp_ms + print(f"更新记录 {account.email} 的ID为 {timestamp_ms}") + + await session.commit() + print("迁移完成") + + +if __name__ == "__main__": + asyncio.run(migrate_add_id()) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1e3cc43 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,12 @@ +DrissionPage==4.1.0.9 +psutil==6.1.0 +fastapi==0.109.0 +uvicorn==0.27.0 +pydantic==2.5.3 +sqlalchemy==2.0.25 +asyncpg==0.29.0 +python-dotenv==1.0.0 +playwright==1.41.2 +aiosqlite==0.21.0 +fake-useragent==2.1.0 +python-multipart \ No newline at end of file diff --git a/reset_machine.py b/reset_machine.py new file mode 100644 index 0000000..c73c7d2 --- /dev/null +++ b/reset_machine.py @@ -0,0 +1,133 @@ +import os +import sys +import json +import uuid +import hashlib +from colorama import Fore, Style, init + +# 初始化colorama +init() + +# 定义emoji和颜色常量 +EMOJI = { + "FILE": "📄", + "BACKUP": "💾", + "SUCCESS": "✅", + "ERROR": "❌", + "INFO": "ℹ️", + "RESET": "🔄", +} + + +class MachineIDResetter: + def __init__(self): + # 判断操作系统 + if sys.platform == "win32": # Windows + appdata = os.getenv("APPDATA") + if appdata is None: + raise EnvironmentError("APPDATA 环境变量未设置") + self.db_path = os.path.join( + appdata, "Cursor", "User", "globalStorage", "storage.json" + ) + elif sys.platform == "darwin": # macOS + self.db_path = os.path.abspath( + os.path.expanduser( + "~/Library/Application Support/Cursor/User/globalStorage/storage.json" + ) + ) + elif sys.platform == "linux": # Linux 和其他类Unix系统 + self.db_path = os.path.abspath( + os.path.expanduser("~/.config/Cursor/User/globalStorage/storage.json") + ) + else: + raise NotImplementedError(f"不支持的操作系统: {sys.platform}") + + def generate_new_ids(self): + """生成新的机器ID""" + # 生成新的UUID + dev_device_id = str(uuid.uuid4()) + + # 生成新的machineId (64个字符的十六进制) + machine_id = hashlib.sha256(os.urandom(32)).hexdigest() + + # 生成新的macMachineId (128个字符的十六进制) + mac_machine_id = hashlib.sha512(os.urandom(64)).hexdigest() + + # 生成新的sqmId + sqm_id = "{" + str(uuid.uuid4()).upper() + "}" + + return { + "telemetry.devDeviceId": dev_device_id, + "telemetry.macMachineId": mac_machine_id, + "telemetry.machineId": machine_id, + "telemetry.sqmId": sqm_id, + } + + def reset_machine_ids(self): + """重置机器ID并备份原文件""" + try: + print(f"{Fore.CYAN}{EMOJI['INFO']} 正在检查配置文件...{Style.RESET_ALL}") + + # 检查文件是否存在 + if not os.path.exists(self.db_path): + print( + f"{Fore.RED}{EMOJI['ERROR']} 配置文件不存在: {self.db_path}{Style.RESET_ALL}" + ) + return False + + # 检查文件权限 + if not os.access(self.db_path, os.R_OK | os.W_OK): + print( + f"{Fore.RED}{EMOJI['ERROR']} 无法读写配置文件,请检查文件权限!{Style.RESET_ALL}" + ) + print( + f"{Fore.RED}{EMOJI['ERROR']} 如果你使用过 go-cursor-help 来修改 ID; 请修改文件只读权限 {self.db_path} {Style.RESET_ALL}" + ) + return False + + # 读取现有配置 + print(f"{Fore.CYAN}{EMOJI['FILE']} 读取当前配置...{Style.RESET_ALL}") + with open(self.db_path, "r", encoding="utf-8") as f: + config = json.load(f) + + # 生成新的ID + print(f"{Fore.CYAN}{EMOJI['RESET']} 生成新的机器标识...{Style.RESET_ALL}") + new_ids = self.generate_new_ids() + + # 更新配置 + config.update(new_ids) + + # 保存新配置 + print(f"{Fore.CYAN}{EMOJI['FILE']} 保存新配置...{Style.RESET_ALL}") + with open(self.db_path, "w", encoding="utf-8") as f: + json.dump(config, f, indent=4) + + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} 机器标识重置成功!{Style.RESET_ALL}") + print(f"\n{Fore.CYAN}新的机器标识:{Style.RESET_ALL}") + for key, value in new_ids.items(): + print(f"{EMOJI['INFO']} {key}: {Fore.GREEN}{value}{Style.RESET_ALL}") + + return True + + except PermissionError as e: + print(f"{Fore.RED}{EMOJI['ERROR']} 权限错误: {str(e)}{Style.RESET_ALL}") + print( + f"{Fore.YELLOW}{EMOJI['INFO']} 请尝试以管理员身份运行此程序{Style.RESET_ALL}" + ) + return False + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} 重置过程出错: {str(e)}{Style.RESET_ALL}") + + return False + + +if __name__ == "__main__": + print(f"\n{Fore.CYAN}{'=' * 50}{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['RESET']} Cursor 机器标识重置工具{Style.RESET_ALL}") + print(f"{Fore.CYAN}{'=' * 50}{Style.RESET_ALL}") + + resetter = MachineIDResetter() + resetter.reset_machine_ids() + + print(f"\n{Fore.CYAN}{'=' * 50}{Style.RESET_ALL}") + input(f"{EMOJI['INFO']} 按回车键退出...") diff --git a/restart.sh b/restart.sh new file mode 100644 index 0000000..5207e4f --- /dev/null +++ b/restart.sh @@ -0,0 +1,3 @@ +#!/bin/bash +sleep 1 +/Library/Frameworks/Python.framework/Versions/3.10/bin/python3 /Users/catdd/Desktop/work/ai/cursor-auto-register/api.py > restart.log 2>&1 & diff --git a/static/css/all.min.css b/static/css/all.min.css new file mode 100644 index 0000000..f8c3651 --- /dev/null +++ b/static/css/all.min.css @@ -0,0 +1,7053 @@ +/*! + * Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2022 Fonticons, Inc. + */ + .fa { + font-family: var(--fa-style-family,"Font Awesome 6 Free"); + font-weight: var(--fa-style,900) +} + +.fa,.fa-brands,.fa-duotone,.fa-light,.fa-regular,.fa-solid,.fa-thin,.fab,.fad,.fal,.far,.fas,.fat { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: var(--fa-display,inline-block); + font-style: normal; + font-variant: normal; + line-height: 1; + text-rendering: auto +} + +.fa-1x { + font-size: 1em +} + +.fa-2x { + font-size: 2em +} + +.fa-3x { + font-size: 3em +} + +.fa-4x { + font-size: 4em +} + +.fa-5x { + font-size: 5em +} + +.fa-6x { + font-size: 6em +} + +.fa-7x { + font-size: 7em +} + +.fa-8x { + font-size: 8em +} + +.fa-9x { + font-size: 9em +} + +.fa-10x { + font-size: 10em +} + +.fa-2xs { + font-size: .625em; + line-height: .1em; + vertical-align: .225em +} + +.fa-xs { + font-size: .75em; + line-height: .08333em; + vertical-align: .125em +} + +.fa-sm { + font-size: .875em; + line-height: .07143em; + vertical-align: .05357em +} + +.fa-lg { + font-size: 1.25em; + line-height: .05em; + vertical-align: -.075em +} + +.fa-xl { + font-size: 1.5em; + line-height: .04167em; + vertical-align: -.125em +} + +.fa-2xl { + font-size: 2em; + line-height: .03125em; + vertical-align: -.1875em +} + +.fa-fw { + text-align: center; + width: 1.25em +} + +.fa-ul { + list-style-type: none; + margin-left: var(--fa-li-margin,2.5em); + padding-left: 0 +} + +.fa-ul>li { + position: relative +} + +.fa-li { + left: calc(var(--fa-li-width, 2em)*-1); + position: absolute; + text-align: center; + width: var(--fa-li-width,2em); + line-height: inherit +} + +.fa-border { + border-radius: var(--fa-border-radius,.1em); + border: var(--fa-border-width,.08em) var(--fa-border-style,solid) var(--fa-border-color,#eee); + padding: var(--fa-border-padding,.2em .25em .15em) +} + +.fa-pull-left { + float: left; + margin-right: var(--fa-pull-margin,.3em) +} + +.fa-pull-right { + float: right; + margin-left: var(--fa-pull-margin,.3em) +} + +.fa-beat { + -webkit-animation-name: fa-beat; + animation-name: fa-beat; + -webkit-animation-delay: var(--fa-animation-delay,0); + animation-delay: var(--fa-animation-delay,0); + -webkit-animation-direction: var(--fa-animation-direction,normal); + animation-direction: var(--fa-animation-direction,normal); + -webkit-animation-duration: var(--fa-animation-duration,1s); + animation-duration: var(--fa-animation-duration,1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count,infinite); + animation-iteration-count: var(--fa-animation-iteration-count,infinite); + -webkit-animation-timing-function: var(--fa-animation-timing,ease-in-out); + animation-timing-function: var(--fa-animation-timing,ease-in-out) +} + +.fa-bounce { + -webkit-animation-name: fa-bounce; + animation-name: fa-bounce; + -webkit-animation-delay: var(--fa-animation-delay,0); + animation-delay: var(--fa-animation-delay,0); + -webkit-animation-direction: var(--fa-animation-direction,normal); + animation-direction: var(--fa-animation-direction,normal); + -webkit-animation-duration: var(--fa-animation-duration,1s); + animation-duration: var(--fa-animation-duration,1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count,infinite); + animation-iteration-count: var(--fa-animation-iteration-count,infinite); + -webkit-animation-timing-function: var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1)); + animation-timing-function: var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1)) +} + +.fa-fade { + -webkit-animation-name: fa-fade; + animation-name: fa-fade; + -webkit-animation-iteration-count: var(--fa-animation-iteration-count,infinite); + animation-iteration-count: var(--fa-animation-iteration-count,infinite); + -webkit-animation-timing-function: var(--fa-animation-timing,cubic-bezier(.4,0,.6,1)); + animation-timing-function: var(--fa-animation-timing,cubic-bezier(.4,0,.6,1)) +} + +.fa-beat-fade,.fa-fade { + -webkit-animation-delay: var(--fa-animation-delay,0); + animation-delay: var(--fa-animation-delay,0); + -webkit-animation-direction: var(--fa-animation-direction,normal); + animation-direction: var(--fa-animation-direction,normal); + -webkit-animation-duration: var(--fa-animation-duration,1s); + animation-duration: var(--fa-animation-duration,1s) +} + +.fa-beat-fade { + -webkit-animation-name: fa-beat-fade; + animation-name: fa-beat-fade; + -webkit-animation-iteration-count: var(--fa-animation-iteration-count,infinite); + animation-iteration-count: var(--fa-animation-iteration-count,infinite); + -webkit-animation-timing-function: var(--fa-animation-timing,cubic-bezier(.4,0,.6,1)); + animation-timing-function: var(--fa-animation-timing,cubic-bezier(.4,0,.6,1)) +} + +.fa-flip { + -webkit-animation-name: fa-flip; + animation-name: fa-flip; + -webkit-animation-delay: var(--fa-animation-delay,0); + animation-delay: var(--fa-animation-delay,0); + -webkit-animation-direction: var(--fa-animation-direction,normal); + animation-direction: var(--fa-animation-direction,normal); + -webkit-animation-duration: var(--fa-animation-duration,1s); + animation-duration: var(--fa-animation-duration,1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count,infinite); + animation-iteration-count: var(--fa-animation-iteration-count,infinite); + -webkit-animation-timing-function: var(--fa-animation-timing,ease-in-out); + animation-timing-function: var(--fa-animation-timing,ease-in-out) +} + +.fa-shake { + -webkit-animation-name: fa-shake; + animation-name: fa-shake; + -webkit-animation-duration: var(--fa-animation-duration,1s); + animation-duration: var(--fa-animation-duration,1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count,infinite); + animation-iteration-count: var(--fa-animation-iteration-count,infinite); + -webkit-animation-timing-function: var(--fa-animation-timing,linear); + animation-timing-function: var(--fa-animation-timing,linear) +} + +.fa-shake,.fa-spin { + -webkit-animation-delay: var(--fa-animation-delay,0); + animation-delay: var(--fa-animation-delay,0); + -webkit-animation-direction: var(--fa-animation-direction,normal); + animation-direction: var(--fa-animation-direction,normal) +} + +.fa-spin { + -webkit-animation-name: fa-spin; + animation-name: fa-spin; + -webkit-animation-duration: var(--fa-animation-duration,2s); + animation-duration: var(--fa-animation-duration,2s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count,infinite); + animation-iteration-count: var(--fa-animation-iteration-count,infinite); + -webkit-animation-timing-function: var(--fa-animation-timing,linear); + animation-timing-function: var(--fa-animation-timing,linear) +} + +.fa-spin-reverse { + --fa-animation-direction: reverse +} + +.fa-pulse,.fa-spin-pulse { + -webkit-animation-name: fa-spin; + animation-name: fa-spin; + -webkit-animation-direction: var(--fa-animation-direction,normal); + animation-direction: var(--fa-animation-direction,normal); + -webkit-animation-duration: var(--fa-animation-duration,1s); + animation-duration: var(--fa-animation-duration,1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count,infinite); + animation-iteration-count: var(--fa-animation-iteration-count,infinite); + -webkit-animation-timing-function: var(--fa-animation-timing,steps(8)); + animation-timing-function: var(--fa-animation-timing,steps(8)) +} + +@media (prefers-reduced-motion:reduce) { + .fa-beat,.fa-beat-fade,.fa-bounce,.fa-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse { + -webkit-animation-delay: -1ms; + animation-delay: -1ms; + -webkit-animation-duration: 1ms; + animation-duration: 1ms; + -webkit-animation-iteration-count: 1; + animation-iteration-count: 1; + transition-delay: 0s; + transition-duration: 0s + } +} + +@-webkit-keyframes fa-beat { + 0%,90% { + -webkit-transform: scale(1); + transform: scale(1) + } + + 45% { + -webkit-transform: scale(var(--fa-beat-scale,1.25)); + transform: scale(var(--fa-beat-scale,1.25)) + } +} + +@keyframes fa-beat { + 0%,90% { + -webkit-transform: scale(1); + transform: scale(1) + } + + 45% { + -webkit-transform: scale(var(--fa-beat-scale,1.25)); + transform: scale(var(--fa-beat-scale,1.25)) + } +} + +@-webkit-keyframes fa-bounce { + 0% { + -webkit-transform: scale(1) translateY(0); + transform: scale(1) translateY(0) + } + + 10% { + -webkit-transform: scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0); + transform: scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0) + } + + 30% { + -webkit-transform: scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em)); + transform: scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em)) + } + + 50% { + -webkit-transform: scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0); + transform: scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0) + } + + 57% { + -webkit-transform: scale(1) translateY(var(--fa-bounce-rebound,-.125em)); + transform: scale(1) translateY(var(--fa-bounce-rebound,-.125em)) + } + + 64% { + -webkit-transform: scale(1) translateY(0); + transform: scale(1) translateY(0) + } + + to { + -webkit-transform: scale(1) translateY(0); + transform: scale(1) translateY(0) + } +} + +@keyframes fa-bounce { + 0% { + -webkit-transform: scale(1) translateY(0); + transform: scale(1) translateY(0) + } + + 10% { + -webkit-transform: scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0); + transform: scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0) + } + + 30% { + -webkit-transform: scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em)); + transform: scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em)) + } + + 50% { + -webkit-transform: scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0); + transform: scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0) + } + + 57% { + -webkit-transform: scale(1) translateY(var(--fa-bounce-rebound,-.125em)); + transform: scale(1) translateY(var(--fa-bounce-rebound,-.125em)) + } + + 64% { + -webkit-transform: scale(1) translateY(0); + transform: scale(1) translateY(0) + } + + to { + -webkit-transform: scale(1) translateY(0); + transform: scale(1) translateY(0) + } +} + +@-webkit-keyframes fa-fade { + 50% { + opacity: var(--fa-fade-opacity,.4) + } +} + +@keyframes fa-fade { + 50% { + opacity: var(--fa-fade-opacity,.4) + } +} + +@-webkit-keyframes fa-beat-fade { + 0%,to { + opacity: var(--fa-beat-fade-opacity,.4); + -webkit-transform: scale(1); + transform: scale(1) + } + + 50% { + opacity: 1; + -webkit-transform: scale(var(--fa-beat-fade-scale,1.125)); + transform: scale(var(--fa-beat-fade-scale,1.125)) + } +} + +@keyframes fa-beat-fade { + 0%,to { + opacity: var(--fa-beat-fade-opacity,.4); + -webkit-transform: scale(1); + transform: scale(1) + } + + 50% { + opacity: 1; + -webkit-transform: scale(var(--fa-beat-fade-scale,1.125)); + transform: scale(var(--fa-beat-fade-scale,1.125)) + } +} + +@-webkit-keyframes fa-flip { + 50% { + -webkit-transform: rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg)); + transform: rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg)) + } +} + +@keyframes fa-flip { + 50% { + -webkit-transform: rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg)); + transform: rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg)) + } +} + +@-webkit-keyframes fa-shake { + 0% { + -webkit-transform: rotate(-15deg); + transform: rotate(-15deg) + } + + 4% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg) + } + + 8%,24% { + -webkit-transform: rotate(-18deg); + transform: rotate(-18deg) + } + + 12%,28% { + -webkit-transform: rotate(18deg); + transform: rotate(18deg) + } + + 16% { + -webkit-transform: rotate(-22deg); + transform: rotate(-22deg) + } + + 20% { + -webkit-transform: rotate(22deg); + transform: rotate(22deg) + } + + 32% { + -webkit-transform: rotate(-12deg); + transform: rotate(-12deg) + } + + 36% { + -webkit-transform: rotate(12deg); + transform: rotate(12deg) + } + + 40%,to { + -webkit-transform: rotate(0deg); + transform: rotate(0deg) + } +} + +@keyframes fa-shake { + 0% { + -webkit-transform: rotate(-15deg); + transform: rotate(-15deg) + } + + 4% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg) + } + + 8%,24% { + -webkit-transform: rotate(-18deg); + transform: rotate(-18deg) + } + + 12%,28% { + -webkit-transform: rotate(18deg); + transform: rotate(18deg) + } + + 16% { + -webkit-transform: rotate(-22deg); + transform: rotate(-22deg) + } + + 20% { + -webkit-transform: rotate(22deg); + transform: rotate(22deg) + } + + 32% { + -webkit-transform: rotate(-12deg); + transform: rotate(-12deg) + } + + 36% { + -webkit-transform: rotate(12deg); + transform: rotate(12deg) + } + + 40%,to { + -webkit-transform: rotate(0deg); + transform: rotate(0deg) + } +} + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg) + } + + to { + -webkit-transform: rotate(1turn); + transform: rotate(1turn) + } +} + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg) + } + + to { + -webkit-transform: rotate(1turn); + transform: rotate(1turn) + } +} + +.fa-rotate-90 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg) +} + +.fa-rotate-180 { + -webkit-transform: rotate(180deg); + transform: rotate(180deg) +} + +.fa-rotate-270 { + -webkit-transform: rotate(270deg); + transform: rotate(270deg) +} + +.fa-flip-horizontal { + -webkit-transform: scaleX(-1); + transform: scaleX(-1) +} + +.fa-flip-vertical { + -webkit-transform: scaleY(-1); + transform: scaleY(-1) +} + +.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical { + -webkit-transform: scale(-1); + transform: scale(-1) +} + +.fa-rotate-by { + -webkit-transform: rotate(var(--fa-rotate-angle,none)); + transform: rotate(var(--fa-rotate-angle,none)) +} + +.fa-stack { + display: inline-block; + height: 2em; + line-height: 2em; + position: relative; + vertical-align: middle; + width: 2.5em +} + +.fa-stack-1x,.fa-stack-2x { + left: 0; + position: absolute; + text-align: center; + width: 100%; + z-index: var(--fa-stack-z-index,auto) +} + +.fa-stack-1x { + line-height: inherit +} + +.fa-stack-2x { + font-size: 2em +} + +.fa-inverse { + color: var(--fa-inverse,#fff) +} + +.fa-0:before { + content: "\30" +} + +.fa-1:before { + content: "\31" +} + +.fa-2:before { + content: "\32" +} + +.fa-3:before { + content: "\33" +} + +.fa-4:before { + content: "\34" +} + +.fa-5:before { + content: "\35" +} + +.fa-6:before { + content: "\36" +} + +.fa-7:before { + content: "\37" +} + +.fa-8:before { + content: "\38" +} + +.fa-9:before { + content: "\39" +} + +.fa-a:before { + content: "\41" +} + +.fa-address-book:before,.fa-contact-book:before { + content: "\f2b9" +} + +.fa-address-card:before,.fa-contact-card:before,.fa-vcard:before { + content: "\f2bb" +} + +.fa-align-center:before { + content: "\f037" +} + +.fa-align-justify:before { + content: "\f039" +} + +.fa-align-left:before { + content: "\f036" +} + +.fa-align-right:before { + content: "\f038" +} + +.fa-anchor:before { + content: "\f13d" +} + +.fa-angle-down:before { + content: "\f107" +} + +.fa-angle-left:before { + content: "\f104" +} + +.fa-angle-right:before { + content: "\f105" +} + +.fa-angle-up:before { + content: "\f106" +} + +.fa-angle-double-down:before,.fa-angles-down:before { + content: "\f103" +} + +.fa-angle-double-left:before,.fa-angles-left:before { + content: "\f100" +} + +.fa-angle-double-right:before,.fa-angles-right:before { + content: "\f101" +} + +.fa-angle-double-up:before,.fa-angles-up:before { + content: "\f102" +} + +.fa-ankh:before { + content: "\f644" +} + +.fa-apple-alt:before,.fa-apple-whole:before { + content: "\f5d1" +} + +.fa-archway:before { + content: "\f557" +} + +.fa-arrow-down:before { + content: "\f063" +} + +.fa-arrow-down-1-9:before,.fa-sort-numeric-asc:before,.fa-sort-numeric-down:before { + content: "\f162" +} + +.fa-arrow-down-9-1:before,.fa-sort-numeric-desc:before,.fa-sort-numeric-down-alt:before { + content: "\f886" +} + +.fa-arrow-down-a-z:before,.fa-sort-alpha-asc:before,.fa-sort-alpha-down:before { + content: "\f15d" +} + +.fa-arrow-down-long:before,.fa-long-arrow-down:before { + content: "\f175" +} + +.fa-arrow-down-short-wide:before,.fa-sort-amount-desc:before,.fa-sort-amount-down-alt:before { + content: "\f884" +} + +.fa-arrow-down-wide-short:before,.fa-sort-amount-asc:before,.fa-sort-amount-down:before { + content: "\f160" +} + +.fa-arrow-down-z-a:before,.fa-sort-alpha-desc:before,.fa-sort-alpha-down-alt:before { + content: "\f881" +} + +.fa-arrow-left:before { + content: "\f060" +} + +.fa-arrow-left-long:before,.fa-long-arrow-left:before { + content: "\f177" +} + +.fa-arrow-pointer:before,.fa-mouse-pointer:before { + content: "\f245" +} + +.fa-arrow-right:before { + content: "\f061" +} + +.fa-arrow-right-arrow-left:before,.fa-exchange:before { + content: "\f0ec" +} + +.fa-arrow-right-from-bracket:before,.fa-sign-out:before { + content: "\f08b" +} + +.fa-arrow-right-long:before,.fa-long-arrow-right:before { + content: "\f178" +} + +.fa-arrow-right-to-bracket:before,.fa-sign-in:before { + content: "\f090" +} + +.fa-arrow-left-rotate:before,.fa-arrow-rotate-back:before,.fa-arrow-rotate-backward:before,.fa-arrow-rotate-left:before,.fa-undo:before { + content: "\f0e2" +} + +.fa-arrow-right-rotate:before,.fa-arrow-rotate-forward:before,.fa-arrow-rotate-right:before,.fa-redo:before { + content: "\f01e" +} + +.fa-arrow-trend-down:before { + content: "\e097" +} + +.fa-arrow-trend-up:before { + content: "\e098" +} + +.fa-arrow-turn-down:before,.fa-level-down:before { + content: "\f149" +} + +.fa-arrow-turn-up:before,.fa-level-up:before { + content: "\f148" +} + +.fa-arrow-up:before { + content: "\f062" +} + +.fa-arrow-up-1-9:before,.fa-sort-numeric-up:before { + content: "\f163" +} + +.fa-arrow-up-9-1:before,.fa-sort-numeric-up-alt:before { + content: "\f887" +} + +.fa-arrow-up-a-z:before,.fa-sort-alpha-up:before { + content: "\f15e" +} + +.fa-arrow-up-from-bracket:before { + content: "\e09a" +} + +.fa-arrow-up-long:before,.fa-long-arrow-up:before { + content: "\f176" +} + +.fa-arrow-up-right-from-square:before,.fa-external-link:before { + content: "\f08e" +} + +.fa-arrow-up-short-wide:before,.fa-sort-amount-up-alt:before { + content: "\f885" +} + +.fa-arrow-up-wide-short:before,.fa-sort-amount-up:before { + content: "\f161" +} + +.fa-arrow-up-z-a:before,.fa-sort-alpha-up-alt:before { + content: "\f882" +} + +.fa-arrows-h:before,.fa-arrows-left-right:before { + content: "\f07e" +} + +.fa-arrows-rotate:before,.fa-refresh:before,.fa-sync:before { + content: "\f021" +} + +.fa-arrows-up-down:before,.fa-arrows-v:before { + content: "\f07d" +} + +.fa-arrows-up-down-left-right:before,.fa-arrows:before { + content: "\f047" +} + +.fa-asterisk:before { + content: "\2a" +} + +.fa-at:before { + content: "\40" +} + +.fa-atom:before { + content: "\f5d2" +} + +.fa-audio-description:before { + content: "\f29e" +} + +.fa-austral-sign:before { + content: "\e0a9" +} + +.fa-award:before { + content: "\f559" +} + +.fa-b:before { + content: "\42" +} + +.fa-baby:before { + content: "\f77c" +} + +.fa-baby-carriage:before,.fa-carriage-baby:before { + content: "\f77d" +} + +.fa-backward:before { + content: "\f04a" +} + +.fa-backward-fast:before,.fa-fast-backward:before { + content: "\f049" +} + +.fa-backward-step:before,.fa-step-backward:before { + content: "\f048" +} + +.fa-bacon:before { + content: "\f7e5" +} + +.fa-bacteria:before { + content: "\e059" +} + +.fa-bacterium:before { + content: "\e05a" +} + +.fa-bag-shopping:before,.fa-shopping-bag:before { + content: "\f290" +} + +.fa-bahai:before { + content: "\f666" +} + +.fa-baht-sign:before { + content: "\e0ac" +} + +.fa-ban:before,.fa-cancel:before { + content: "\f05e" +} + +.fa-ban-smoking:before,.fa-smoking-ban:before { + content: "\f54d" +} + +.fa-band-aid:before,.fa-bandage:before { + content: "\f462" +} + +.fa-barcode:before { + content: "\f02a" +} + +.fa-bars:before,.fa-navicon:before { + content: "\f0c9" +} + +.fa-bars-progress:before,.fa-tasks-alt:before { + content: "\f828" +} + +.fa-bars-staggered:before,.fa-reorder:before,.fa-stream:before { + content: "\f550" +} + +.fa-baseball-ball:before,.fa-baseball:before { + content: "\f433" +} + +.fa-baseball-bat-ball:before { + content: "\f432" +} + +.fa-basket-shopping:before,.fa-shopping-basket:before { + content: "\f291" +} + +.fa-basketball-ball:before,.fa-basketball:before { + content: "\f434" +} + +.fa-bath:before,.fa-bathtub:before { + content: "\f2cd" +} + +.fa-battery-0:before,.fa-battery-empty:before { + content: "\f244" +} + +.fa-battery-5:before,.fa-battery-full:before,.fa-battery:before { + content: "\f240" +} + +.fa-battery-3:before,.fa-battery-half:before { + content: "\f242" +} + +.fa-battery-2:before,.fa-battery-quarter:before { + content: "\f243" +} + +.fa-battery-4:before,.fa-battery-three-quarters:before { + content: "\f241" +} + +.fa-bed:before { + content: "\f236" +} + +.fa-bed-pulse:before,.fa-procedures:before { + content: "\f487" +} + +.fa-beer-mug-empty:before,.fa-beer:before { + content: "\f0fc" +} + +.fa-bell:before { + content: "\f0f3" +} + +.fa-bell-concierge:before,.fa-concierge-bell:before { + content: "\f562" +} + +.fa-bell-slash:before { + content: "\f1f6" +} + +.fa-bezier-curve:before { + content: "\f55b" +} + +.fa-bicycle:before { + content: "\f206" +} + +.fa-binoculars:before { + content: "\f1e5" +} + +.fa-biohazard:before { + content: "\f780" +} + +.fa-bitcoin-sign:before { + content: "\e0b4" +} + +.fa-blender:before { + content: "\f517" +} + +.fa-blender-phone:before { + content: "\f6b6" +} + +.fa-blog:before { + content: "\f781" +} + +.fa-bold:before { + content: "\f032" +} + +.fa-bolt:before,.fa-zap:before { + content: "\f0e7" +} + +.fa-bolt-lightning:before { + content: "\e0b7" +} + +.fa-bomb:before { + content: "\f1e2" +} + +.fa-bone:before { + content: "\f5d7" +} + +.fa-bong:before { + content: "\f55c" +} + +.fa-book:before { + content: "\f02d" +} + +.fa-atlas:before,.fa-book-atlas:before { + content: "\f558" +} + +.fa-bible:before,.fa-book-bible:before { + content: "\f647" +} + +.fa-book-journal-whills:before,.fa-journal-whills:before { + content: "\f66a" +} + +.fa-book-medical:before { + content: "\f7e6" +} + +.fa-book-open:before { + content: "\f518" +} + +.fa-book-open-reader:before,.fa-book-reader:before { + content: "\f5da" +} + +.fa-book-quran:before,.fa-quran:before { + content: "\f687" +} + +.fa-book-dead:before,.fa-book-skull:before { + content: "\f6b7" +} + +.fa-bookmark:before { + content: "\f02e" +} + +.fa-border-all:before { + content: "\f84c" +} + +.fa-border-none:before { + content: "\f850" +} + +.fa-border-style:before,.fa-border-top-left:before { + content: "\f853" +} + +.fa-bowling-ball:before { + content: "\f436" +} + +.fa-box:before { + content: "\f466" +} + +.fa-archive:before,.fa-box-archive:before { + content: "\f187" +} + +.fa-box-open:before { + content: "\f49e" +} + +.fa-box-tissue:before { + content: "\e05b" +} + +.fa-boxes-alt:before,.fa-boxes-stacked:before,.fa-boxes:before { + content: "\f468" +} + +.fa-braille:before { + content: "\f2a1" +} + +.fa-brain:before { + content: "\f5dc" +} + +.fa-brazilian-real-sign:before { + content: "\e46c" +} + +.fa-bread-slice:before { + content: "\f7ec" +} + +.fa-briefcase:before { + content: "\f0b1" +} + +.fa-briefcase-medical:before { + content: "\f469" +} + +.fa-broom:before { + content: "\f51a" +} + +.fa-broom-ball:before,.fa-quidditch-broom-ball:before,.fa-quidditch:before { + content: "\f458" +} + +.fa-brush:before { + content: "\f55d" +} + +.fa-bug:before { + content: "\f188" +} + +.fa-bug-slash:before { + content: "\e490" +} + +.fa-building:before { + content: "\f1ad" +} + +.fa-bank:before,.fa-building-columns:before,.fa-institution:before,.fa-museum:before,.fa-university:before { + content: "\f19c" +} + +.fa-bullhorn:before { + content: "\f0a1" +} + +.fa-bullseye:before { + content: "\f140" +} + +.fa-burger:before,.fa-hamburger:before { + content: "\f805" +} + +.fa-bus:before { + content: "\f207" +} + +.fa-bus-alt:before,.fa-bus-simple:before { + content: "\f55e" +} + +.fa-briefcase-clock:before,.fa-business-time:before { + content: "\f64a" +} + +.fa-c:before { + content: "\43" +} + +.fa-birthday-cake:before,.fa-cake-candles:before,.fa-cake:before { + content: "\f1fd" +} + +.fa-calculator:before { + content: "\f1ec" +} + +.fa-calendar:before { + content: "\f133" +} + +.fa-calendar-check:before { + content: "\f274" +} + +.fa-calendar-day:before { + content: "\f783" +} + +.fa-calendar-alt:before,.fa-calendar-days:before { + content: "\f073" +} + +.fa-calendar-minus:before { + content: "\f272" +} + +.fa-calendar-plus:before { + content: "\f271" +} + +.fa-calendar-week:before { + content: "\f784" +} + +.fa-calendar-times:before,.fa-calendar-xmark:before { + content: "\f273" +} + +.fa-camera-alt:before,.fa-camera:before { + content: "\f030" +} + +.fa-camera-retro:before { + content: "\f083" +} + +.fa-camera-rotate:before { + content: "\e0d8" +} + +.fa-campground:before { + content: "\f6bb" +} + +.fa-candy-cane:before { + content: "\f786" +} + +.fa-cannabis:before { + content: "\f55f" +} + +.fa-capsules:before { + content: "\f46b" +} + +.fa-automobile:before,.fa-car:before { + content: "\f1b9" +} + +.fa-battery-car:before,.fa-car-battery:before { + content: "\f5df" +} + +.fa-car-crash:before { + content: "\f5e1" +} + +.fa-car-alt:before,.fa-car-rear:before { + content: "\f5de" +} + +.fa-car-side:before { + content: "\f5e4" +} + +.fa-caravan:before { + content: "\f8ff" +} + +.fa-caret-down:before { + content: "\f0d7" +} + +.fa-caret-left:before { + content: "\f0d9" +} + +.fa-caret-right:before { + content: "\f0da" +} + +.fa-caret-up:before { + content: "\f0d8" +} + +.fa-carrot:before { + content: "\f787" +} + +.fa-cart-arrow-down:before { + content: "\f218" +} + +.fa-cart-flatbed:before,.fa-dolly-flatbed:before { + content: "\f474" +} + +.fa-cart-flatbed-suitcase:before,.fa-luggage-cart:before { + content: "\f59d" +} + +.fa-cart-plus:before { + content: "\f217" +} + +.fa-cart-shopping:before,.fa-shopping-cart:before { + content: "\f07a" +} + +.fa-cash-register:before { + content: "\f788" +} + +.fa-cat:before { + content: "\f6be" +} + +.fa-cedi-sign:before { + content: "\e0df" +} + +.fa-cent-sign:before { + content: "\e3f5" +} + +.fa-certificate:before { + content: "\f0a3" +} + +.fa-chair:before { + content: "\f6c0" +} + +.fa-blackboard:before,.fa-chalkboard:before { + content: "\f51b" +} + +.fa-chalkboard-teacher:before,.fa-chalkboard-user:before { + content: "\f51c" +} + +.fa-champagne-glasses:before,.fa-glass-cheers:before { + content: "\f79f" +} + +.fa-charging-station:before { + content: "\f5e7" +} + +.fa-area-chart:before,.fa-chart-area:before { + content: "\f1fe" +} + +.fa-bar-chart:before,.fa-chart-bar:before { + content: "\f080" +} + +.fa-chart-column:before { + content: "\e0e3" +} + +.fa-chart-gantt:before { + content: "\e0e4" +} + +.fa-chart-line:before,.fa-line-chart:before { + content: "\f201" +} + +.fa-chart-pie:before,.fa-pie-chart:before { + content: "\f200" +} + +.fa-check:before { + content: "\f00c" +} + +.fa-check-double:before { + content: "\f560" +} + +.fa-check-to-slot:before,.fa-vote-yea:before { + content: "\f772" +} + +.fa-cheese:before { + content: "\f7ef" +} + +.fa-chess:before { + content: "\f439" +} + +.fa-chess-bishop:before { + content: "\f43a" +} + +.fa-chess-board:before { + content: "\f43c" +} + +.fa-chess-king:before { + content: "\f43f" +} + +.fa-chess-knight:before { + content: "\f441" +} + +.fa-chess-pawn:before { + content: "\f443" +} + +.fa-chess-queen:before { + content: "\f445" +} + +.fa-chess-rook:before { + content: "\f447" +} + +.fa-chevron-down:before { + content: "\f078" +} + +.fa-chevron-left:before { + content: "\f053" +} + +.fa-chevron-right:before { + content: "\f054" +} + +.fa-chevron-up:before { + content: "\f077" +} + +.fa-child:before { + content: "\f1ae" +} + +.fa-church:before { + content: "\f51d" +} + +.fa-circle:before { + content: "\f111" +} + +.fa-arrow-circle-down:before,.fa-circle-arrow-down:before { + content: "\f0ab" +} + +.fa-arrow-circle-left:before,.fa-circle-arrow-left:before { + content: "\f0a8" +} + +.fa-arrow-circle-right:before,.fa-circle-arrow-right:before { + content: "\f0a9" +} + +.fa-arrow-circle-up:before,.fa-circle-arrow-up:before { + content: "\f0aa" +} + +.fa-check-circle:before,.fa-circle-check:before { + content: "\f058" +} + +.fa-chevron-circle-down:before,.fa-circle-chevron-down:before { + content: "\f13a" +} + +.fa-chevron-circle-left:before,.fa-circle-chevron-left:before { + content: "\f137" +} + +.fa-chevron-circle-right:before,.fa-circle-chevron-right:before { + content: "\f138" +} + +.fa-chevron-circle-up:before,.fa-circle-chevron-up:before { + content: "\f139" +} + +.fa-circle-dollar-to-slot:before,.fa-donate:before { + content: "\f4b9" +} + +.fa-circle-dot:before,.fa-dot-circle:before { + content: "\f192" +} + +.fa-arrow-alt-circle-down:before,.fa-circle-down:before { + content: "\f358" +} + +.fa-circle-exclamation:before,.fa-exclamation-circle:before { + content: "\f06a" +} + +.fa-circle-h:before,.fa-hospital-symbol:before { + content: "\f47e" +} + +.fa-adjust:before,.fa-circle-half-stroke:before { + content: "\f042" +} + +.fa-circle-info:before,.fa-info-circle:before { + content: "\f05a" +} + +.fa-arrow-alt-circle-left:before,.fa-circle-left:before { + content: "\f359" +} + +.fa-circle-minus:before,.fa-minus-circle:before { + content: "\f056" +} + +.fa-circle-notch:before { + content: "\f1ce" +} + +.fa-circle-pause:before,.fa-pause-circle:before { + content: "\f28b" +} + +.fa-circle-play:before,.fa-play-circle:before { + content: "\f144" +} + +.fa-circle-plus:before,.fa-plus-circle:before { + content: "\f055" +} + +.fa-circle-question:before,.fa-question-circle:before { + content: "\f059" +} + +.fa-circle-radiation:before,.fa-radiation-alt:before { + content: "\f7ba" +} + +.fa-arrow-alt-circle-right:before,.fa-circle-right:before { + content: "\f35a" +} + +.fa-circle-stop:before,.fa-stop-circle:before { + content: "\f28d" +} + +.fa-arrow-alt-circle-up:before,.fa-circle-up:before { + content: "\f35b" +} + +.fa-circle-user:before,.fa-user-circle:before { + content: "\f2bd" +} + +.fa-circle-xmark:before,.fa-times-circle:before,.fa-xmark-circle:before { + content: "\f057" +} + +.fa-city:before { + content: "\f64f" +} + +.fa-clapperboard:before { + content: "\e131" +} + +.fa-clipboard:before { + content: "\f328" +} + +.fa-clipboard-check:before { + content: "\f46c" +} + +.fa-clipboard-list:before { + content: "\f46d" +} + +.fa-clock-four:before,.fa-clock:before { + content: "\f017" +} + +.fa-clock-rotate-left:before,.fa-history:before { + content: "\f1da" +} + +.fa-clone:before { + content: "\f24d" +} + +.fa-closed-captioning:before { + content: "\f20a" +} + +.fa-cloud:before { + content: "\f0c2" +} + +.fa-cloud-arrow-down:before,.fa-cloud-download-alt:before,.fa-cloud-download:before { + content: "\f0ed" +} + +.fa-cloud-arrow-up:before,.fa-cloud-upload-alt:before,.fa-cloud-upload:before { + content: "\f0ee" +} + +.fa-cloud-meatball:before { + content: "\f73b" +} + +.fa-cloud-moon:before { + content: "\f6c3" +} + +.fa-cloud-moon-rain:before { + content: "\f73c" +} + +.fa-cloud-rain:before { + content: "\f73d" +} + +.fa-cloud-showers-heavy:before { + content: "\f740" +} + +.fa-cloud-sun:before { + content: "\f6c4" +} + +.fa-cloud-sun-rain:before { + content: "\f743" +} + +.fa-clover:before { + content: "\e139" +} + +.fa-code:before { + content: "\f121" +} + +.fa-code-branch:before { + content: "\f126" +} + +.fa-code-commit:before { + content: "\f386" +} + +.fa-code-compare:before { + content: "\e13a" +} + +.fa-code-fork:before { + content: "\e13b" +} + +.fa-code-merge:before { + content: "\f387" +} + +.fa-code-pull-request:before { + content: "\e13c" +} + +.fa-coins:before { + content: "\f51e" +} + +.fa-colon-sign:before { + content: "\e140" +} + +.fa-comment:before { + content: "\f075" +} + +.fa-comment-dollar:before { + content: "\f651" +} + +.fa-comment-dots:before,.fa-commenting:before { + content: "\f4ad" +} + +.fa-comment-medical:before { + content: "\f7f5" +} + +.fa-comment-slash:before { + content: "\f4b3" +} + +.fa-comment-sms:before,.fa-sms:before { + content: "\f7cd" +} + +.fa-comments:before { + content: "\f086" +} + +.fa-comments-dollar:before { + content: "\f653" +} + +.fa-compact-disc:before { + content: "\f51f" +} + +.fa-compass:before { + content: "\f14e" +} + +.fa-compass-drafting:before,.fa-drafting-compass:before { + content: "\f568" +} + +.fa-compress:before { + content: "\f066" +} + +.fa-computer-mouse:before,.fa-mouse:before { + content: "\f8cc" +} + +.fa-cookie:before { + content: "\f563" +} + +.fa-cookie-bite:before { + content: "\f564" +} + +.fa-copy:before { + content: "\f0c5" +} + +.fa-copyright:before { + content: "\f1f9" +} + +.fa-couch:before { + content: "\f4b8" +} + +.fa-credit-card-alt:before,.fa-credit-card:before { + content: "\f09d" +} + +.fa-crop:before { + content: "\f125" +} + +.fa-crop-alt:before,.fa-crop-simple:before { + content: "\f565" +} + +.fa-cross:before { + content: "\f654" +} + +.fa-crosshairs:before { + content: "\f05b" +} + +.fa-crow:before { + content: "\f520" +} + +.fa-crown:before { + content: "\f521" +} + +.fa-crutch:before { + content: "\f7f7" +} + +.fa-cruzeiro-sign:before { + content: "\e152" +} + +.fa-cube:before { + content: "\f1b2" +} + +.fa-cubes:before { + content: "\f1b3" +} + +.fa-d:before { + content: "\44" +} + +.fa-database:before { + content: "\f1c0" +} + +.fa-backspace:before,.fa-delete-left:before { + content: "\f55a" +} + +.fa-democrat:before { + content: "\f747" +} + +.fa-desktop-alt:before,.fa-desktop:before { + content: "\f390" +} + +.fa-dharmachakra:before { + content: "\f655" +} + +.fa-diagram-next:before { + content: "\e476" +} + +.fa-diagram-predecessor:before { + content: "\e477" +} + +.fa-diagram-project:before,.fa-project-diagram:before { + content: "\f542" +} + +.fa-diagram-successor:before { + content: "\e47a" +} + +.fa-diamond:before { + content: "\f219" +} + +.fa-diamond-turn-right:before,.fa-directions:before { + content: "\f5eb" +} + +.fa-dice:before { + content: "\f522" +} + +.fa-dice-d20:before { + content: "\f6cf" +} + +.fa-dice-d6:before { + content: "\f6d1" +} + +.fa-dice-five:before { + content: "\f523" +} + +.fa-dice-four:before { + content: "\f524" +} + +.fa-dice-one:before { + content: "\f525" +} + +.fa-dice-six:before { + content: "\f526" +} + +.fa-dice-three:before { + content: "\f527" +} + +.fa-dice-two:before { + content: "\f528" +} + +.fa-disease:before { + content: "\f7fa" +} + +.fa-divide:before { + content: "\f529" +} + +.fa-dna:before { + content: "\f471" +} + +.fa-dog:before { + content: "\f6d3" +} + +.fa-dollar-sign:before,.fa-dollar:before,.fa-usd:before { + content: "\24" +} + +.fa-dolly-box:before,.fa-dolly:before { + content: "\f472" +} + +.fa-dong-sign:before { + content: "\e169" +} + +.fa-door-closed:before { + content: "\f52a" +} + +.fa-door-open:before { + content: "\f52b" +} + +.fa-dove:before { + content: "\f4ba" +} + +.fa-compress-alt:before,.fa-down-left-and-up-right-to-center:before { + content: "\f422" +} + +.fa-down-long:before,.fa-long-arrow-alt-down:before { + content: "\f309" +} + +.fa-download:before { + content: "\f019" +} + +.fa-dragon:before { + content: "\f6d5" +} + +.fa-draw-polygon:before { + content: "\f5ee" +} + +.fa-droplet:before,.fa-tint:before { + content: "\f043" +} + +.fa-droplet-slash:before,.fa-tint-slash:before { + content: "\f5c7" +} + +.fa-drum:before { + content: "\f569" +} + +.fa-drum-steelpan:before { + content: "\f56a" +} + +.fa-drumstick-bite:before { + content: "\f6d7" +} + +.fa-dumbbell:before { + content: "\f44b" +} + +.fa-dumpster:before { + content: "\f793" +} + +.fa-dumpster-fire:before { + content: "\f794" +} + +.fa-dungeon:before { + content: "\f6d9" +} + +.fa-e:before { + content: "\45" +} + +.fa-deaf:before,.fa-deafness:before,.fa-ear-deaf:before,.fa-hard-of-hearing:before { + content: "\f2a4" +} + +.fa-assistive-listening-systems:before,.fa-ear-listen:before { + content: "\f2a2" +} + +.fa-earth-africa:before,.fa-globe-africa:before { + content: "\f57c" +} + +.fa-earth-america:before,.fa-earth-americas:before,.fa-earth:before,.fa-globe-americas:before { + content: "\f57d" +} + +.fa-earth-asia:before,.fa-globe-asia:before { + content: "\f57e" +} + +.fa-earth-europe:before,.fa-globe-europe:before { + content: "\f7a2" +} + +.fa-earth-oceania:before,.fa-globe-oceania:before { + content: "\e47b" +} + +.fa-egg:before { + content: "\f7fb" +} + +.fa-eject:before { + content: "\f052" +} + +.fa-elevator:before { + content: "\e16d" +} + +.fa-ellipsis-h:before,.fa-ellipsis:before { + content: "\f141" +} + +.fa-ellipsis-v:before,.fa-ellipsis-vertical:before { + content: "\f142" +} + +.fa-envelope:before { + content: "\f0e0" +} + +.fa-envelope-open:before { + content: "\f2b6" +} + +.fa-envelope-open-text:before { + content: "\f658" +} + +.fa-envelopes-bulk:before,.fa-mail-bulk:before { + content: "\f674" +} + +.fa-equals:before { + content: "\3d" +} + +.fa-eraser:before { + content: "\f12d" +} + +.fa-ethernet:before { + content: "\f796" +} + +.fa-eur:before,.fa-euro-sign:before,.fa-euro:before { + content: "\f153" +} + +.fa-exclamation:before { + content: "\21" +} + +.fa-expand:before { + content: "\f065" +} + +.fa-eye:before { + content: "\f06e" +} + +.fa-eye-dropper-empty:before,.fa-eye-dropper:before,.fa-eyedropper:before { + content: "\f1fb" +} + +.fa-eye-low-vision:before,.fa-low-vision:before { + content: "\f2a8" +} + +.fa-eye-slash:before { + content: "\f070" +} + +.fa-f:before { + content: "\46" +} + +.fa-angry:before,.fa-face-angry:before { + content: "\f556" +} + +.fa-dizzy:before,.fa-face-dizzy:before { + content: "\f567" +} + +.fa-face-flushed:before,.fa-flushed:before { + content: "\f579" +} + +.fa-face-frown:before,.fa-frown:before { + content: "\f119" +} + +.fa-face-frown-open:before,.fa-frown-open:before { + content: "\f57a" +} + +.fa-face-grimace:before,.fa-grimace:before { + content: "\f57f" +} + +.fa-face-grin:before,.fa-grin:before { + content: "\f580" +} + +.fa-face-grin-beam:before,.fa-grin-beam:before { + content: "\f582" +} + +.fa-face-grin-beam-sweat:before,.fa-grin-beam-sweat:before { + content: "\f583" +} + +.fa-face-grin-hearts:before,.fa-grin-hearts:before { + content: "\f584" +} + +.fa-face-grin-squint:before,.fa-grin-squint:before { + content: "\f585" +} + +.fa-face-grin-squint-tears:before,.fa-grin-squint-tears:before { + content: "\f586" +} + +.fa-face-grin-stars:before,.fa-grin-stars:before { + content: "\f587" +} + +.fa-face-grin-tears:before,.fa-grin-tears:before { + content: "\f588" +} + +.fa-face-grin-tongue:before,.fa-grin-tongue:before { + content: "\f589" +} + +.fa-face-grin-tongue-squint:before,.fa-grin-tongue-squint:before { + content: "\f58a" +} + +.fa-face-grin-tongue-wink:before,.fa-grin-tongue-wink:before { + content: "\f58b" +} + +.fa-face-grin-wide:before,.fa-grin-alt:before { + content: "\f581" +} + +.fa-face-grin-wink:before,.fa-grin-wink:before { + content: "\f58c" +} + +.fa-face-kiss:before,.fa-kiss:before { + content: "\f596" +} + +.fa-face-kiss-beam:before,.fa-kiss-beam:before { + content: "\f597" +} + +.fa-face-kiss-wink-heart:before,.fa-kiss-wink-heart:before { + content: "\f598" +} + +.fa-face-laugh:before,.fa-laugh:before { + content: "\f599" +} + +.fa-face-laugh-beam:before,.fa-laugh-beam:before { + content: "\f59a" +} + +.fa-face-laugh-squint:before,.fa-laugh-squint:before { + content: "\f59b" +} + +.fa-face-laugh-wink:before,.fa-laugh-wink:before { + content: "\f59c" +} + +.fa-face-meh:before,.fa-meh:before { + content: "\f11a" +} + +.fa-face-meh-blank:before,.fa-meh-blank:before { + content: "\f5a4" +} + +.fa-face-rolling-eyes:before,.fa-meh-rolling-eyes:before { + content: "\f5a5" +} + +.fa-face-sad-cry:before,.fa-sad-cry:before { + content: "\f5b3" +} + +.fa-face-sad-tear:before,.fa-sad-tear:before { + content: "\f5b4" +} + +.fa-face-smile:before,.fa-smile:before { + content: "\f118" +} + +.fa-face-smile-beam:before,.fa-smile-beam:before { + content: "\f5b8" +} + +.fa-face-smile-wink:before,.fa-smile-wink:before { + content: "\f4da" +} + +.fa-face-surprise:before,.fa-surprise:before { + content: "\f5c2" +} + +.fa-face-tired:before,.fa-tired:before { + content: "\f5c8" +} + +.fa-fan:before { + content: "\f863" +} + +.fa-faucet:before { + content: "\e005" +} + +.fa-fax:before { + content: "\f1ac" +} + +.fa-feather:before { + content: "\f52d" +} + +.fa-feather-alt:before,.fa-feather-pointed:before { + content: "\f56b" +} + +.fa-file:before { + content: "\f15b" +} + +.fa-file-arrow-down:before,.fa-file-download:before { + content: "\f56d" +} + +.fa-file-arrow-up:before,.fa-file-upload:before { + content: "\f574" +} + +.fa-file-audio:before { + content: "\f1c7" +} + +.fa-file-code:before { + content: "\f1c9" +} + +.fa-file-contract:before { + content: "\f56c" +} + +.fa-file-csv:before { + content: "\f6dd" +} + +.fa-file-excel:before { + content: "\f1c3" +} + +.fa-arrow-right-from-file:before,.fa-file-export:before { + content: "\f56e" +} + +.fa-file-image:before { + content: "\f1c5" +} + +.fa-arrow-right-to-file:before,.fa-file-import:before { + content: "\f56f" +} + +.fa-file-invoice:before { + content: "\f570" +} + +.fa-file-invoice-dollar:before { + content: "\f571" +} + +.fa-file-alt:before,.fa-file-lines:before,.fa-file-text:before { + content: "\f15c" +} + +.fa-file-medical:before { + content: "\f477" +} + +.fa-file-pdf:before { + content: "\f1c1" +} + +.fa-file-powerpoint:before { + content: "\f1c4" +} + +.fa-file-prescription:before { + content: "\f572" +} + +.fa-file-signature:before { + content: "\f573" +} + +.fa-file-video:before { + content: "\f1c8" +} + +.fa-file-medical-alt:before,.fa-file-waveform:before { + content: "\f478" +} + +.fa-file-word:before { + content: "\f1c2" +} + +.fa-file-archive:before,.fa-file-zipper:before { + content: "\f1c6" +} + +.fa-fill:before { + content: "\f575" +} + +.fa-fill-drip:before { + content: "\f576" +} + +.fa-film:before { + content: "\f008" +} + +.fa-filter:before { + content: "\f0b0" +} + +.fa-filter-circle-dollar:before,.fa-funnel-dollar:before { + content: "\f662" +} + +.fa-filter-circle-xmark:before { + content: "\e17b" +} + +.fa-fingerprint:before { + content: "\f577" +} + +.fa-fire:before { + content: "\f06d" +} + +.fa-fire-extinguisher:before { + content: "\f134" +} + +.fa-fire-alt:before,.fa-fire-flame-curved:before { + content: "\f7e4" +} + +.fa-burn:before,.fa-fire-flame-simple:before { + content: "\f46a" +} + +.fa-fish:before { + content: "\f578" +} + +.fa-flag:before { + content: "\f024" +} + +.fa-flag-checkered:before { + content: "\f11e" +} + +.fa-flag-usa:before { + content: "\f74d" +} + +.fa-flask:before { + content: "\f0c3" +} + +.fa-floppy-disk:before,.fa-save:before { + content: "\f0c7" +} + +.fa-florin-sign:before { + content: "\e184" +} + +.fa-folder:before { + content: "\f07b" +} + +.fa-folder-minus:before { + content: "\f65d" +} + +.fa-folder-open:before { + content: "\f07c" +} + +.fa-folder-plus:before { + content: "\f65e" +} + +.fa-folder-tree:before { + content: "\f802" +} + +.fa-font:before { + content: "\f031" +} + +.fa-football-ball:before,.fa-football:before { + content: "\f44e" +} + +.fa-forward:before { + content: "\f04e" +} + +.fa-fast-forward:before,.fa-forward-fast:before { + content: "\f050" +} + +.fa-forward-step:before,.fa-step-forward:before { + content: "\f051" +} + +.fa-franc-sign:before { + content: "\e18f" +} + +.fa-frog:before { + content: "\f52e" +} + +.fa-futbol-ball:before,.fa-futbol:before,.fa-soccer-ball:before { + content: "\f1e3" +} + +.fa-g:before { + content: "\47" +} + +.fa-gamepad:before { + content: "\f11b" +} + +.fa-gas-pump:before { + content: "\f52f" +} + +.fa-dashboard:before,.fa-gauge-med:before,.fa-gauge:before,.fa-tachometer-alt-average:before { + content: "\f624" +} + +.fa-gauge-high:before,.fa-tachometer-alt-fast:before,.fa-tachometer-alt:before { + content: "\f625" +} + +.fa-gauge-simple-med:before,.fa-gauge-simple:before,.fa-tachometer-average:before { + content: "\f629" +} + +.fa-gauge-simple-high:before,.fa-tachometer-fast:before,.fa-tachometer:before { + content: "\f62a" +} + +.fa-gavel:before,.fa-legal:before { + content: "\f0e3" +} + +.fa-cog:before,.fa-gear:before { + content: "\f013" +} + +.fa-cogs:before,.fa-gears:before { + content: "\f085" +} + +.fa-gem:before { + content: "\f3a5" +} + +.fa-genderless:before { + content: "\f22d" +} + +.fa-ghost:before { + content: "\f6e2" +} + +.fa-gift:before { + content: "\f06b" +} + +.fa-gifts:before { + content: "\f79c" +} + +.fa-glasses:before { + content: "\f530" +} + +.fa-globe:before { + content: "\f0ac" +} + +.fa-golf-ball-tee:before,.fa-golf-ball:before { + content: "\f450" +} + +.fa-gopuram:before { + content: "\f664" +} + +.fa-graduation-cap:before,.fa-mortar-board:before { + content: "\f19d" +} + +.fa-greater-than:before { + content: "\3e" +} + +.fa-greater-than-equal:before { + content: "\f532" +} + +.fa-grip-horizontal:before,.fa-grip:before { + content: "\f58d" +} + +.fa-grip-lines:before { + content: "\f7a4" +} + +.fa-grip-lines-vertical:before { + content: "\f7a5" +} + +.fa-grip-vertical:before { + content: "\f58e" +} + +.fa-guarani-sign:before { + content: "\e19a" +} + +.fa-guitar:before { + content: "\f7a6" +} + +.fa-gun:before { + content: "\e19b" +} + +.fa-h:before { + content: "\48" +} + +.fa-hammer:before { + content: "\f6e3" +} + +.fa-hamsa:before { + content: "\f665" +} + +.fa-hand-paper:before,.fa-hand:before { + content: "\f256" +} + +.fa-hand-back-fist:before,.fa-hand-rock:before { + content: "\f255" +} + +.fa-allergies:before,.fa-hand-dots:before { + content: "\f461" +} + +.fa-fist-raised:before,.fa-hand-fist:before { + content: "\f6de" +} + +.fa-hand-holding:before { + content: "\f4bd" +} + +.fa-hand-holding-dollar:before,.fa-hand-holding-usd:before { + content: "\f4c0" +} + +.fa-hand-holding-droplet:before,.fa-hand-holding-water:before { + content: "\f4c1" +} + +.fa-hand-holding-heart:before { + content: "\f4be" +} + +.fa-hand-holding-medical:before { + content: "\e05c" +} + +.fa-hand-lizard:before { + content: "\f258" +} + +.fa-hand-middle-finger:before { + content: "\f806" +} + +.fa-hand-peace:before { + content: "\f25b" +} + +.fa-hand-point-down:before { + content: "\f0a7" +} + +.fa-hand-point-left:before { + content: "\f0a5" +} + +.fa-hand-point-right:before { + content: "\f0a4" +} + +.fa-hand-point-up:before { + content: "\f0a6" +} + +.fa-hand-pointer:before { + content: "\f25a" +} + +.fa-hand-scissors:before { + content: "\f257" +} + +.fa-hand-sparkles:before { + content: "\e05d" +} + +.fa-hand-spock:before { + content: "\f259" +} + +.fa-hands:before,.fa-sign-language:before,.fa-signing:before { + content: "\f2a7" +} + +.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before,.fa-hands-american-sign-language-interpreting:before,.fa-hands-asl-interpreting:before { + content: "\f2a3" +} + +.fa-hands-bubbles:before,.fa-hands-wash:before { + content: "\e05e" +} + +.fa-hands-clapping:before { + content: "\e1a8" +} + +.fa-hands-holding:before { + content: "\f4c2" +} + +.fa-hands-praying:before,.fa-praying-hands:before { + content: "\f684" +} + +.fa-handshake:before { + content: "\f2b5" +} + +.fa-hands-helping:before,.fa-handshake-angle:before { + content: "\f4c4" +} + +.fa-handshake-alt-slash:before,.fa-handshake-simple-slash:before { + content: "\e05f" +} + +.fa-handshake-slash:before { + content: "\e060" +} + +.fa-hanukiah:before { + content: "\f6e6" +} + +.fa-hard-drive:before,.fa-hdd:before { + content: "\f0a0" +} + +.fa-hashtag:before { + content: "\23" +} + +.fa-hat-cowboy:before { + content: "\f8c0" +} + +.fa-hat-cowboy-side:before { + content: "\f8c1" +} + +.fa-hat-wizard:before { + content: "\f6e8" +} + +.fa-head-side-cough:before { + content: "\e061" +} + +.fa-head-side-cough-slash:before { + content: "\e062" +} + +.fa-head-side-mask:before { + content: "\e063" +} + +.fa-head-side-virus:before { + content: "\e064" +} + +.fa-header:before,.fa-heading:before { + content: "\f1dc" +} + +.fa-headphones:before { + content: "\f025" +} + +.fa-headphones-alt:before,.fa-headphones-simple:before { + content: "\f58f" +} + +.fa-headset:before { + content: "\f590" +} + +.fa-heart:before { + content: "\f004" +} + +.fa-heart-broken:before,.fa-heart-crack:before { + content: "\f7a9" +} + +.fa-heart-pulse:before,.fa-heartbeat:before { + content: "\f21e" +} + +.fa-helicopter:before { + content: "\f533" +} + +.fa-hard-hat:before,.fa-hat-hard:before,.fa-helmet-safety:before { + content: "\f807" +} + +.fa-highlighter:before { + content: "\f591" +} + +.fa-hippo:before { + content: "\f6ed" +} + +.fa-hockey-puck:before { + content: "\f453" +} + +.fa-holly-berry:before { + content: "\f7aa" +} + +.fa-horse:before { + content: "\f6f0" +} + +.fa-horse-head:before { + content: "\f7ab" +} + +.fa-hospital-alt:before,.fa-hospital-wide:before,.fa-hospital:before { + content: "\f0f8" +} + +.fa-hospital-user:before { + content: "\f80d" +} + +.fa-hot-tub-person:before,.fa-hot-tub:before { + content: "\f593" +} + +.fa-hotdog:before { + content: "\f80f" +} + +.fa-hotel:before { + content: "\f594" +} + +.fa-hourglass-2:before,.fa-hourglass-half:before,.fa-hourglass:before { + content: "\f254" +} + +.fa-hourglass-empty:before { + content: "\f252" +} + +.fa-hourglass-3:before,.fa-hourglass-end:before { + content: "\f253" +} + +.fa-hourglass-1:before,.fa-hourglass-start:before { + content: "\f251" +} + +.fa-home-alt:before,.fa-home-lg-alt:before,.fa-home:before,.fa-house:before { + content: "\f015" +} + +.fa-home-lg:before,.fa-house-chimney:before { + content: "\e3af" +} + +.fa-house-chimney-crack:before,.fa-house-damage:before { + content: "\f6f1" +} + +.fa-clinic-medical:before,.fa-house-chimney-medical:before { + content: "\f7f2" +} + +.fa-house-chimney-user:before { + content: "\e065" +} + +.fa-house-chimney-window:before { + content: "\e00d" +} + +.fa-house-crack:before { + content: "\e3b1" +} + +.fa-house-laptop:before,.fa-laptop-house:before { + content: "\e066" +} + +.fa-house-medical:before { + content: "\e3b2" +} + +.fa-home-user:before,.fa-house-user:before { + content: "\e1b0" +} + +.fa-hryvnia-sign:before,.fa-hryvnia:before { + content: "\f6f2" +} + +.fa-i:before { + content: "\49" +} + +.fa-i-cursor:before { + content: "\f246" +} + +.fa-ice-cream:before { + content: "\f810" +} + +.fa-icicles:before { + content: "\f7ad" +} + +.fa-heart-music-camera-bolt:before,.fa-icons:before { + content: "\f86d" +} + +.fa-id-badge:before { + content: "\f2c1" +} + +.fa-drivers-license:before,.fa-id-card:before { + content: "\f2c2" +} + +.fa-id-card-alt:before,.fa-id-card-clip:before { + content: "\f47f" +} + +.fa-igloo:before { + content: "\f7ae" +} + +.fa-image:before { + content: "\f03e" +} + +.fa-image-portrait:before,.fa-portrait:before { + content: "\f3e0" +} + +.fa-images:before { + content: "\f302" +} + +.fa-inbox:before { + content: "\f01c" +} + +.fa-indent:before { + content: "\f03c" +} + +.fa-indian-rupee-sign:before,.fa-indian-rupee:before,.fa-inr:before { + content: "\e1bc" +} + +.fa-industry:before { + content: "\f275" +} + +.fa-infinity:before { + content: "\f534" +} + +.fa-info:before { + content: "\f129" +} + +.fa-italic:before { + content: "\f033" +} + +.fa-j:before { + content: "\4a" +} + +.fa-jedi:before { + content: "\f669" +} + +.fa-fighter-jet:before,.fa-jet-fighter:before { + content: "\f0fb" +} + +.fa-joint:before { + content: "\f595" +} + +.fa-k:before { + content: "\4b" +} + +.fa-kaaba:before { + content: "\f66b" +} + +.fa-key:before { + content: "\f084" +} + +.fa-keyboard:before { + content: "\f11c" +} + +.fa-khanda:before { + content: "\f66d" +} + +.fa-kip-sign:before { + content: "\e1c4" +} + +.fa-first-aid:before,.fa-kit-medical:before { + content: "\f479" +} + +.fa-kiwi-bird:before { + content: "\f535" +} + +.fa-l:before { + content: "\4c" +} + +.fa-landmark:before { + content: "\f66f" +} + +.fa-language:before { + content: "\f1ab" +} + +.fa-laptop:before { + content: "\f109" +} + +.fa-laptop-code:before { + content: "\f5fc" +} + +.fa-laptop-medical:before { + content: "\f812" +} + +.fa-lari-sign:before { + content: "\e1c8" +} + +.fa-layer-group:before { + content: "\f5fd" +} + +.fa-leaf:before { + content: "\f06c" +} + +.fa-left-long:before,.fa-long-arrow-alt-left:before { + content: "\f30a" +} + +.fa-arrows-alt-h:before,.fa-left-right:before { + content: "\f337" +} + +.fa-lemon:before { + content: "\f094" +} + +.fa-less-than:before { + content: "\3c" +} + +.fa-less-than-equal:before { + content: "\f537" +} + +.fa-life-ring:before { + content: "\f1cd" +} + +.fa-lightbulb:before { + content: "\f0eb" +} + +.fa-chain:before,.fa-link:before { + content: "\f0c1" +} + +.fa-chain-broken:before,.fa-chain-slash:before,.fa-link-slash:before,.fa-unlink:before { + content: "\f127" +} + +.fa-lira-sign:before { + content: "\f195" +} + +.fa-list-squares:before,.fa-list:before { + content: "\f03a" +} + +.fa-list-check:before,.fa-tasks:before { + content: "\f0ae" +} + +.fa-list-1-2:before,.fa-list-numeric:before,.fa-list-ol:before { + content: "\f0cb" +} + +.fa-list-dots:before,.fa-list-ul:before { + content: "\f0ca" +} + +.fa-litecoin-sign:before { + content: "\e1d3" +} + +.fa-location-arrow:before { + content: "\f124" +} + +.fa-location-crosshairs:before,.fa-location:before { + content: "\f601" +} + +.fa-location-dot:before,.fa-map-marker-alt:before { + content: "\f3c5" +} + +.fa-location-pin:before,.fa-map-marker:before { + content: "\f041" +} + +.fa-lock:before { + content: "\f023" +} + +.fa-lock-open:before { + content: "\f3c1" +} + +.fa-lungs:before { + content: "\f604" +} + +.fa-lungs-virus:before { + content: "\e067" +} + +.fa-m:before { + content: "\4d" +} + +.fa-magnet:before { + content: "\f076" +} + +.fa-magnifying-glass:before,.fa-search:before { + content: "\f002" +} + +.fa-magnifying-glass-dollar:before,.fa-search-dollar:before { + content: "\f688" +} + +.fa-magnifying-glass-location:before,.fa-search-location:before { + content: "\f689" +} + +.fa-magnifying-glass-minus:before,.fa-search-minus:before { + content: "\f010" +} + +.fa-magnifying-glass-plus:before,.fa-search-plus:before { + content: "\f00e" +} + +.fa-manat-sign:before { + content: "\e1d5" +} + +.fa-map:before { + content: "\f279" +} + +.fa-map-location:before,.fa-map-marked:before { + content: "\f59f" +} + +.fa-map-location-dot:before,.fa-map-marked-alt:before { + content: "\f5a0" +} + +.fa-map-pin:before { + content: "\f276" +} + +.fa-marker:before { + content: "\f5a1" +} + +.fa-mars:before { + content: "\f222" +} + +.fa-mars-and-venus:before { + content: "\f224" +} + +.fa-mars-double:before { + content: "\f227" +} + +.fa-mars-stroke:before { + content: "\f229" +} + +.fa-mars-stroke-h:before,.fa-mars-stroke-right:before { + content: "\f22b" +} + +.fa-mars-stroke-up:before,.fa-mars-stroke-v:before { + content: "\f22a" +} + +.fa-glass-martini-alt:before,.fa-martini-glass:before { + content: "\f57b" +} + +.fa-cocktail:before,.fa-martini-glass-citrus:before { + content: "\f561" +} + +.fa-glass-martini:before,.fa-martini-glass-empty:before { + content: "\f000" +} + +.fa-mask:before { + content: "\f6fa" +} + +.fa-mask-face:before { + content: "\e1d7" +} + +.fa-masks-theater:before,.fa-theater-masks:before { + content: "\f630" +} + +.fa-expand-arrows-alt:before,.fa-maximize:before { + content: "\f31e" +} + +.fa-medal:before { + content: "\f5a2" +} + +.fa-memory:before { + content: "\f538" +} + +.fa-menorah:before { + content: "\f676" +} + +.fa-mercury:before { + content: "\f223" +} + +.fa-comment-alt:before,.fa-message:before { + content: "\f27a" +} + +.fa-meteor:before { + content: "\f753" +} + +.fa-microchip:before { + content: "\f2db" +} + +.fa-microphone:before { + content: "\f130" +} + +.fa-microphone-alt:before,.fa-microphone-lines:before { + content: "\f3c9" +} + +.fa-microphone-alt-slash:before,.fa-microphone-lines-slash:before { + content: "\f539" +} + +.fa-microphone-slash:before { + content: "\f131" +} + +.fa-microscope:before { + content: "\f610" +} + +.fa-mill-sign:before { + content: "\e1ed" +} + +.fa-compress-arrows-alt:before,.fa-minimize:before { + content: "\f78c" +} + +.fa-minus:before,.fa-subtract:before { + content: "\f068" +} + +.fa-mitten:before { + content: "\f7b5" +} + +.fa-mobile-android:before,.fa-mobile-phone:before,.fa-mobile:before { + content: "\f3ce" +} + +.fa-mobile-button:before { + content: "\f10b" +} + +.fa-mobile-alt:before,.fa-mobile-screen-button:before { + content: "\f3cd" +} + +.fa-money-bill:before { + content: "\f0d6" +} + +.fa-money-bill-1:before,.fa-money-bill-alt:before { + content: "\f3d1" +} + +.fa-money-bill-1-wave:before,.fa-money-bill-wave-alt:before { + content: "\f53b" +} + +.fa-money-bill-wave:before { + content: "\f53a" +} + +.fa-money-check:before { + content: "\f53c" +} + +.fa-money-check-alt:before,.fa-money-check-dollar:before { + content: "\f53d" +} + +.fa-monument:before { + content: "\f5a6" +} + +.fa-moon:before { + content: "\f186" +} + +.fa-mortar-pestle:before { + content: "\f5a7" +} + +.fa-mosque:before { + content: "\f678" +} + +.fa-motorcycle:before { + content: "\f21c" +} + +.fa-mountain:before { + content: "\f6fc" +} + +.fa-mug-hot:before { + content: "\f7b6" +} + +.fa-coffee:before,.fa-mug-saucer:before { + content: "\f0f4" +} + +.fa-music:before { + content: "\f001" +} + +.fa-n:before { + content: "\4e" +} + +.fa-naira-sign:before { + content: "\e1f6" +} + +.fa-network-wired:before { + content: "\f6ff" +} + +.fa-neuter:before { + content: "\f22c" +} + +.fa-newspaper:before { + content: "\f1ea" +} + +.fa-not-equal:before { + content: "\f53e" +} + +.fa-note-sticky:before,.fa-sticky-note:before { + content: "\f249" +} + +.fa-notes-medical:before { + content: "\f481" +} + +.fa-o:before { + content: "\4f" +} + +.fa-object-group:before { + content: "\f247" +} + +.fa-object-ungroup:before { + content: "\f248" +} + +.fa-oil-can:before { + content: "\f613" +} + +.fa-om:before { + content: "\f679" +} + +.fa-otter:before { + content: "\f700" +} + +.fa-dedent:before,.fa-outdent:before { + content: "\f03b" +} + +.fa-p:before { + content: "\50" +} + +.fa-pager:before { + content: "\f815" +} + +.fa-paint-roller:before { + content: "\f5aa" +} + +.fa-paint-brush:before,.fa-paintbrush:before { + content: "\f1fc" +} + +.fa-palette:before { + content: "\f53f" +} + +.fa-pallet:before { + content: "\f482" +} + +.fa-panorama:before { + content: "\e209" +} + +.fa-paper-plane:before { + content: "\f1d8" +} + +.fa-paperclip:before { + content: "\f0c6" +} + +.fa-parachute-box:before { + content: "\f4cd" +} + +.fa-paragraph:before { + content: "\f1dd" +} + +.fa-passport:before { + content: "\f5ab" +} + +.fa-file-clipboard:before,.fa-paste:before { + content: "\f0ea" +} + +.fa-pause:before { + content: "\f04c" +} + +.fa-paw:before { + content: "\f1b0" +} + +.fa-peace:before { + content: "\f67c" +} + +.fa-pen:before { + content: "\f304" +} + +.fa-pen-alt:before,.fa-pen-clip:before { + content: "\f305" +} + +.fa-pen-fancy:before { + content: "\f5ac" +} + +.fa-pen-nib:before { + content: "\f5ad" +} + +.fa-pen-ruler:before,.fa-pencil-ruler:before { + content: "\f5ae" +} + +.fa-edit:before,.fa-pen-to-square:before { + content: "\f044" +} + +.fa-pencil-alt:before,.fa-pencil:before { + content: "\f303" +} + +.fa-people-arrows-left-right:before,.fa-people-arrows:before { + content: "\e068" +} + +.fa-people-carry-box:before,.fa-people-carry:before { + content: "\f4ce" +} + +.fa-pepper-hot:before { + content: "\f816" +} + +.fa-percent:before,.fa-percentage:before { + content: "\25" +} + +.fa-male:before,.fa-person:before { + content: "\f183" +} + +.fa-biking:before,.fa-person-biking:before { + content: "\f84a" +} + +.fa-person-booth:before { + content: "\f756" +} + +.fa-diagnoses:before,.fa-person-dots-from-line:before { + content: "\f470" +} + +.fa-female:before,.fa-person-dress:before { + content: "\f182" +} + +.fa-hiking:before,.fa-person-hiking:before { + content: "\f6ec" +} + +.fa-person-praying:before,.fa-pray:before { + content: "\f683" +} + +.fa-person-running:before,.fa-running:before { + content: "\f70c" +} + +.fa-person-skating:before,.fa-skating:before { + content: "\f7c5" +} + +.fa-person-skiing:before,.fa-skiing:before { + content: "\f7c9" +} + +.fa-person-skiing-nordic:before,.fa-skiing-nordic:before { + content: "\f7ca" +} + +.fa-person-snowboarding:before,.fa-snowboarding:before { + content: "\f7ce" +} + +.fa-person-swimming:before,.fa-swimmer:before { + content: "\f5c4" +} + +.fa-person-walking:before,.fa-walking:before { + content: "\f554" +} + +.fa-blind:before,.fa-person-walking-with-cane:before { + content: "\f29d" +} + +.fa-peseta-sign:before { + content: "\e221" +} + +.fa-peso-sign:before { + content: "\e222" +} + +.fa-phone:before { + content: "\f095" +} + +.fa-phone-alt:before,.fa-phone-flip:before { + content: "\f879" +} + +.fa-phone-slash:before { + content: "\f3dd" +} + +.fa-phone-volume:before,.fa-volume-control-phone:before { + content: "\f2a0" +} + +.fa-photo-film:before,.fa-photo-video:before { + content: "\f87c" +} + +.fa-piggy-bank:before { + content: "\f4d3" +} + +.fa-pills:before { + content: "\f484" +} + +.fa-pizza-slice:before { + content: "\f818" +} + +.fa-place-of-worship:before { + content: "\f67f" +} + +.fa-plane:before { + content: "\f072" +} + +.fa-plane-arrival:before { + content: "\f5af" +} + +.fa-plane-departure:before { + content: "\f5b0" +} + +.fa-plane-slash:before { + content: "\e069" +} + +.fa-play:before { + content: "\f04b" +} + +.fa-plug:before { + content: "\f1e6" +} + +.fa-add:before,.fa-plus:before { + content: "\2b" +} + +.fa-plus-minus:before { + content: "\e43c" +} + +.fa-podcast:before { + content: "\f2ce" +} + +.fa-poo:before { + content: "\f2fe" +} + +.fa-poo-bolt:before,.fa-poo-storm:before { + content: "\f75a" +} + +.fa-poop:before { + content: "\f619" +} + +.fa-power-off:before { + content: "\f011" +} + +.fa-prescription:before { + content: "\f5b1" +} + +.fa-prescription-bottle:before { + content: "\f485" +} + +.fa-prescription-bottle-alt:before,.fa-prescription-bottle-medical:before { + content: "\f486" +} + +.fa-print:before { + content: "\f02f" +} + +.fa-pump-medical:before { + content: "\e06a" +} + +.fa-pump-soap:before { + content: "\e06b" +} + +.fa-puzzle-piece:before { + content: "\f12e" +} + +.fa-q:before { + content: "\51" +} + +.fa-qrcode:before { + content: "\f029" +} + +.fa-question:before { + content: "\3f" +} + +.fa-quote-left-alt:before,.fa-quote-left:before { + content: "\f10d" +} + +.fa-quote-right-alt:before,.fa-quote-right:before { + content: "\f10e" +} + +.fa-r:before { + content: "\52" +} + +.fa-radiation:before { + content: "\f7b9" +} + +.fa-rainbow:before { + content: "\f75b" +} + +.fa-receipt:before { + content: "\f543" +} + +.fa-record-vinyl:before { + content: "\f8d9" +} + +.fa-ad:before,.fa-rectangle-ad:before { + content: "\f641" +} + +.fa-list-alt:before,.fa-rectangle-list:before { + content: "\f022" +} + +.fa-rectangle-times:before,.fa-rectangle-xmark:before,.fa-times-rectangle:before,.fa-window-close:before { + content: "\f410" +} + +.fa-recycle:before { + content: "\f1b8" +} + +.fa-registered:before { + content: "\f25d" +} + +.fa-repeat:before { + content: "\f363" +} + +.fa-mail-reply:before,.fa-reply:before { + content: "\f3e5" +} + +.fa-mail-reply-all:before,.fa-reply-all:before { + content: "\f122" +} + +.fa-republican:before { + content: "\f75e" +} + +.fa-restroom:before { + content: "\f7bd" +} + +.fa-retweet:before { + content: "\f079" +} + +.fa-ribbon:before { + content: "\f4d6" +} + +.fa-right-from-bracket:before,.fa-sign-out-alt:before { + content: "\f2f5" +} + +.fa-exchange-alt:before,.fa-right-left:before { + content: "\f362" +} + +.fa-long-arrow-alt-right:before,.fa-right-long:before { + content: "\f30b" +} + +.fa-right-to-bracket:before,.fa-sign-in-alt:before { + content: "\f2f6" +} + +.fa-ring:before { + content: "\f70b" +} + +.fa-road:before { + content: "\f018" +} + +.fa-robot:before { + content: "\f544" +} + +.fa-rocket:before { + content: "\f135" +} + +.fa-rotate:before,.fa-sync-alt:before { + content: "\f2f1" +} + +.fa-rotate-back:before,.fa-rotate-backward:before,.fa-rotate-left:before,.fa-undo-alt:before { + content: "\f2ea" +} + +.fa-redo-alt:before,.fa-rotate-forward:before,.fa-rotate-right:before { + content: "\f2f9" +} + +.fa-route:before { + content: "\f4d7" +} + +.fa-feed:before,.fa-rss:before { + content: "\f09e" +} + +.fa-rouble:before,.fa-rub:before,.fa-ruble-sign:before,.fa-ruble:before { + content: "\f158" +} + +.fa-ruler:before { + content: "\f545" +} + +.fa-ruler-combined:before { + content: "\f546" +} + +.fa-ruler-horizontal:before { + content: "\f547" +} + +.fa-ruler-vertical:before { + content: "\f548" +} + +.fa-rupee-sign:before,.fa-rupee:before { + content: "\f156" +} + +.fa-rupiah-sign:before { + content: "\e23d" +} + +.fa-s:before { + content: "\53" +} + +.fa-sailboat:before { + content: "\e445" +} + +.fa-satellite:before { + content: "\f7bf" +} + +.fa-satellite-dish:before { + content: "\f7c0" +} + +.fa-balance-scale:before,.fa-scale-balanced:before { + content: "\f24e" +} + +.fa-balance-scale-left:before,.fa-scale-unbalanced:before { + content: "\f515" +} + +.fa-balance-scale-right:before,.fa-scale-unbalanced-flip:before { + content: "\f516" +} + +.fa-school:before { + content: "\f549" +} + +.fa-cut:before,.fa-scissors:before { + content: "\f0c4" +} + +.fa-screwdriver:before { + content: "\f54a" +} + +.fa-screwdriver-wrench:before,.fa-tools:before { + content: "\f7d9" +} + +.fa-scroll:before { + content: "\f70e" +} + +.fa-scroll-torah:before,.fa-torah:before { + content: "\f6a0" +} + +.fa-sd-card:before { + content: "\f7c2" +} + +.fa-section:before { + content: "\e447" +} + +.fa-seedling:before,.fa-sprout:before { + content: "\f4d8" +} + +.fa-server:before { + content: "\f233" +} + +.fa-shapes:before,.fa-triangle-circle-square:before { + content: "\f61f" +} + +.fa-arrow-turn-right:before,.fa-mail-forward:before,.fa-share:before { + content: "\f064" +} + +.fa-share-from-square:before,.fa-share-square:before { + content: "\f14d" +} + +.fa-share-alt:before,.fa-share-nodes:before { + content: "\f1e0" +} + +.fa-ils:before,.fa-shekel-sign:before,.fa-shekel:before,.fa-sheqel-sign:before,.fa-sheqel:before { + content: "\f20b" +} + +.fa-shield:before { + content: "\f132" +} + +.fa-shield-alt:before,.fa-shield-blank:before { + content: "\f3ed" +} + +.fa-shield-virus:before { + content: "\e06c" +} + +.fa-ship:before { + content: "\f21a" +} + +.fa-shirt:before,.fa-t-shirt:before,.fa-tshirt:before { + content: "\f553" +} + +.fa-shoe-prints:before { + content: "\f54b" +} + +.fa-shop:before,.fa-store-alt:before { + content: "\f54f" +} + +.fa-shop-slash:before,.fa-store-alt-slash:before { + content: "\e070" +} + +.fa-shower:before { + content: "\f2cc" +} + +.fa-shrimp:before { + content: "\e448" +} + +.fa-random:before,.fa-shuffle:before { + content: "\f074" +} + +.fa-shuttle-space:before,.fa-space-shuttle:before { + content: "\f197" +} + +.fa-sign-hanging:before,.fa-sign:before { + content: "\f4d9" +} + +.fa-signal-5:before,.fa-signal-perfect:before,.fa-signal:before { + content: "\f012" +} + +.fa-signature:before { + content: "\f5b7" +} + +.fa-map-signs:before,.fa-signs-post:before { + content: "\f277" +} + +.fa-sim-card:before { + content: "\f7c4" +} + +.fa-sink:before { + content: "\e06d" +} + +.fa-sitemap:before { + content: "\f0e8" +} + +.fa-skull:before { + content: "\f54c" +} + +.fa-skull-crossbones:before { + content: "\f714" +} + +.fa-slash:before { + content: "\f715" +} + +.fa-sleigh:before { + content: "\f7cc" +} + +.fa-sliders-h:before,.fa-sliders:before { + content: "\f1de" +} + +.fa-smog:before { + content: "\f75f" +} + +.fa-smoking:before { + content: "\f48d" +} + +.fa-snowflake:before { + content: "\f2dc" +} + +.fa-snowman:before { + content: "\f7d0" +} + +.fa-snowplow:before { + content: "\f7d2" +} + +.fa-soap:before { + content: "\e06e" +} + +.fa-socks:before { + content: "\f696" +} + +.fa-solar-panel:before { + content: "\f5ba" +} + +.fa-sort:before,.fa-unsorted:before { + content: "\f0dc" +} + +.fa-sort-desc:before,.fa-sort-down:before { + content: "\f0dd" +} + +.fa-sort-asc:before,.fa-sort-up:before { + content: "\f0de" +} + +.fa-spa:before { + content: "\f5bb" +} + +.fa-pastafarianism:before,.fa-spaghetti-monster-flying:before { + content: "\f67b" +} + +.fa-spell-check:before { + content: "\f891" +} + +.fa-spider:before { + content: "\f717" +} + +.fa-spinner:before { + content: "\f110" +} + +.fa-splotch:before { + content: "\f5bc" +} + +.fa-spoon:before,.fa-utensil-spoon:before { + content: "\f2e5" +} + +.fa-spray-can:before { + content: "\f5bd" +} + +.fa-air-freshener:before,.fa-spray-can-sparkles:before { + content: "\f5d0" +} + +.fa-square:before { + content: "\f0c8" +} + +.fa-external-link-square:before,.fa-square-arrow-up-right:before { + content: "\f14c" +} + +.fa-caret-square-down:before,.fa-square-caret-down:before { + content: "\f150" +} + +.fa-caret-square-left:before,.fa-square-caret-left:before { + content: "\f191" +} + +.fa-caret-square-right:before,.fa-square-caret-right:before { + content: "\f152" +} + +.fa-caret-square-up:before,.fa-square-caret-up:before { + content: "\f151" +} + +.fa-check-square:before,.fa-square-check:before { + content: "\f14a" +} + +.fa-envelope-square:before,.fa-square-envelope:before { + content: "\f199" +} + +.fa-square-full:before { + content: "\f45c" +} + +.fa-h-square:before,.fa-square-h:before { + content: "\f0fd" +} + +.fa-minus-square:before,.fa-square-minus:before { + content: "\f146" +} + +.fa-parking:before,.fa-square-parking:before { + content: "\f540" +} + +.fa-pen-square:before,.fa-pencil-square:before,.fa-square-pen:before { + content: "\f14b" +} + +.fa-phone-square:before,.fa-square-phone:before { + content: "\f098" +} + +.fa-phone-square-alt:before,.fa-square-phone-flip:before { + content: "\f87b" +} + +.fa-plus-square:before,.fa-square-plus:before { + content: "\f0fe" +} + +.fa-poll-h:before,.fa-square-poll-horizontal:before { + content: "\f682" +} + +.fa-poll:before,.fa-square-poll-vertical:before { + content: "\f681" +} + +.fa-square-root-alt:before,.fa-square-root-variable:before { + content: "\f698" +} + +.fa-rss-square:before,.fa-square-rss:before { + content: "\f143" +} + +.fa-share-alt-square:before,.fa-square-share-nodes:before { + content: "\f1e1" +} + +.fa-external-link-square-alt:before,.fa-square-up-right:before { + content: "\f360" +} + +.fa-square-xmark:before,.fa-times-square:before,.fa-xmark-square:before { + content: "\f2d3" +} + +.fa-stairs:before { + content: "\e289" +} + +.fa-stamp:before { + content: "\f5bf" +} + +.fa-star:before { + content: "\f005" +} + +.fa-star-and-crescent:before { + content: "\f699" +} + +.fa-star-half:before { + content: "\f089" +} + +.fa-star-half-alt:before,.fa-star-half-stroke:before { + content: "\f5c0" +} + +.fa-star-of-david:before { + content: "\f69a" +} + +.fa-star-of-life:before { + content: "\f621" +} + +.fa-gbp:before,.fa-pound-sign:before,.fa-sterling-sign:before { + content: "\f154" +} + +.fa-stethoscope:before { + content: "\f0f1" +} + +.fa-stop:before { + content: "\f04d" +} + +.fa-stopwatch:before { + content: "\f2f2" +} + +.fa-stopwatch-20:before { + content: "\e06f" +} + +.fa-store:before { + content: "\f54e" +} + +.fa-store-slash:before { + content: "\e071" +} + +.fa-street-view:before { + content: "\f21d" +} + +.fa-strikethrough:before { + content: "\f0cc" +} + +.fa-stroopwafel:before { + content: "\f551" +} + +.fa-subscript:before { + content: "\f12c" +} + +.fa-suitcase:before { + content: "\f0f2" +} + +.fa-medkit:before,.fa-suitcase-medical:before { + content: "\f0fa" +} + +.fa-suitcase-rolling:before { + content: "\f5c1" +} + +.fa-sun:before { + content: "\f185" +} + +.fa-superscript:before { + content: "\f12b" +} + +.fa-swatchbook:before { + content: "\f5c3" +} + +.fa-synagogue:before { + content: "\f69b" +} + +.fa-syringe:before { + content: "\f48e" +} + +.fa-t:before { + content: "\54" +} + +.fa-table:before { + content: "\f0ce" +} + +.fa-table-cells:before,.fa-th:before { + content: "\f00a" +} + +.fa-table-cells-large:before,.fa-th-large:before { + content: "\f009" +} + +.fa-columns:before,.fa-table-columns:before { + content: "\f0db" +} + +.fa-table-list:before,.fa-th-list:before { + content: "\f00b" +} + +.fa-ping-pong-paddle-ball:before,.fa-table-tennis-paddle-ball:before,.fa-table-tennis:before { + content: "\f45d" +} + +.fa-tablet-android:before,.fa-tablet:before { + content: "\f3fb" +} + +.fa-tablet-button:before { + content: "\f10a" +} + +.fa-tablet-alt:before,.fa-tablet-screen-button:before { + content: "\f3fa" +} + +.fa-tablets:before { + content: "\f490" +} + +.fa-digital-tachograph:before,.fa-tachograph-digital:before { + content: "\f566" +} + +.fa-tag:before { + content: "\f02b" +} + +.fa-tags:before { + content: "\f02c" +} + +.fa-tape:before { + content: "\f4db" +} + +.fa-cab:before,.fa-taxi:before { + content: "\f1ba" +} + +.fa-teeth:before { + content: "\f62e" +} + +.fa-teeth-open:before { + content: "\f62f" +} + +.fa-temperature-0:before,.fa-temperature-empty:before,.fa-thermometer-0:before,.fa-thermometer-empty:before { + content: "\f2cb" +} + +.fa-temperature-4:before,.fa-temperature-full:before,.fa-thermometer-4:before,.fa-thermometer-full:before { + content: "\f2c7" +} + +.fa-temperature-2:before,.fa-temperature-half:before,.fa-thermometer-2:before,.fa-thermometer-half:before { + content: "\f2c9" +} + +.fa-temperature-high:before { + content: "\f769" +} + +.fa-temperature-low:before { + content: "\f76b" +} + +.fa-temperature-1:before,.fa-temperature-quarter:before,.fa-thermometer-1:before,.fa-thermometer-quarter:before { + content: "\f2ca" +} + +.fa-temperature-3:before,.fa-temperature-three-quarters:before,.fa-thermometer-3:before,.fa-thermometer-three-quarters:before { + content: "\f2c8" +} + +.fa-tenge-sign:before,.fa-tenge:before { + content: "\f7d7" +} + +.fa-terminal:before { + content: "\f120" +} + +.fa-text-height:before { + content: "\f034" +} + +.fa-remove-format:before,.fa-text-slash:before { + content: "\f87d" +} + +.fa-text-width:before { + content: "\f035" +} + +.fa-thermometer:before { + content: "\f491" +} + +.fa-thumbs-down:before { + content: "\f165" +} + +.fa-thumbs-up:before { + content: "\f164" +} + +.fa-thumb-tack:before,.fa-thumbtack:before { + content: "\f08d" +} + +.fa-ticket:before { + content: "\f145" +} + +.fa-ticket-alt:before,.fa-ticket-simple:before { + content: "\f3ff" +} + +.fa-timeline:before { + content: "\e29c" +} + +.fa-toggle-off:before { + content: "\f204" +} + +.fa-toggle-on:before { + content: "\f205" +} + +.fa-toilet:before { + content: "\f7d8" +} + +.fa-toilet-paper:before { + content: "\f71e" +} + +.fa-toilet-paper-slash:before { + content: "\e072" +} + +.fa-toolbox:before { + content: "\f552" +} + +.fa-tooth:before { + content: "\f5c9" +} + +.fa-torii-gate:before { + content: "\f6a1" +} + +.fa-broadcast-tower:before,.fa-tower-broadcast:before { + content: "\f519" +} + +.fa-tractor:before { + content: "\f722" +} + +.fa-trademark:before { + content: "\f25c" +} + +.fa-traffic-light:before { + content: "\f637" +} + +.fa-trailer:before { + content: "\e041" +} + +.fa-train:before { + content: "\f238" +} + +.fa-subway:before,.fa-train-subway:before { + content: "\f239" +} + +.fa-train-tram:before,.fa-tram:before { + content: "\f7da" +} + +.fa-transgender-alt:before,.fa-transgender:before { + content: "\f225" +} + +.fa-trash:before { + content: "\f1f8" +} + +.fa-trash-arrow-up:before,.fa-trash-restore:before { + content: "\f829" +} + +.fa-trash-alt:before,.fa-trash-can:before { + content: "\f2ed" +} + +.fa-trash-can-arrow-up:before,.fa-trash-restore-alt:before { + content: "\f82a" +} + +.fa-tree:before { + content: "\f1bb" +} + +.fa-exclamation-triangle:before,.fa-triangle-exclamation:before,.fa-warning:before { + content: "\f071" +} + +.fa-trophy:before { + content: "\f091" +} + +.fa-truck:before { + content: "\f0d1" +} + +.fa-shipping-fast:before,.fa-truck-fast:before { + content: "\f48b" +} + +.fa-ambulance:before,.fa-truck-medical:before { + content: "\f0f9" +} + +.fa-truck-monster:before { + content: "\f63b" +} + +.fa-truck-moving:before { + content: "\f4df" +} + +.fa-truck-pickup:before { + content: "\f63c" +} + +.fa-truck-loading:before,.fa-truck-ramp-box:before { + content: "\f4de" +} + +.fa-teletype:before,.fa-tty:before { + content: "\f1e4" +} + +.fa-try:before,.fa-turkish-lira-sign:before,.fa-turkish-lira:before { + content: "\e2bb" +} + +.fa-level-down-alt:before,.fa-turn-down:before { + content: "\f3be" +} + +.fa-level-up-alt:before,.fa-turn-up:before { + content: "\f3bf" +} + +.fa-television:before,.fa-tv-alt:before,.fa-tv:before { + content: "\f26c" +} + +.fa-u:before { + content: "\55" +} + +.fa-umbrella:before { + content: "\f0e9" +} + +.fa-umbrella-beach:before { + content: "\f5ca" +} + +.fa-underline:before { + content: "\f0cd" +} + +.fa-universal-access:before { + content: "\f29a" +} + +.fa-unlock:before { + content: "\f09c" +} + +.fa-unlock-alt:before,.fa-unlock-keyhole:before { + content: "\f13e" +} + +.fa-arrows-alt-v:before,.fa-up-down:before { + content: "\f338" +} + +.fa-arrows-alt:before,.fa-up-down-left-right:before { + content: "\f0b2" +} + +.fa-long-arrow-alt-up:before,.fa-up-long:before { + content: "\f30c" +} + +.fa-expand-alt:before,.fa-up-right-and-down-left-from-center:before { + content: "\f424" +} + +.fa-external-link-alt:before,.fa-up-right-from-square:before { + content: "\f35d" +} + +.fa-upload:before { + content: "\f093" +} + +.fa-user:before { + content: "\f007" +} + +.fa-user-astronaut:before { + content: "\f4fb" +} + +.fa-user-check:before { + content: "\f4fc" +} + +.fa-user-clock:before { + content: "\f4fd" +} + +.fa-user-doctor:before,.fa-user-md:before { + content: "\f0f0" +} + +.fa-user-cog:before,.fa-user-gear:before { + content: "\f4fe" +} + +.fa-user-graduate:before { + content: "\f501" +} + +.fa-user-friends:before,.fa-user-group:before { + content: "\f500" +} + +.fa-user-injured:before { + content: "\f728" +} + +.fa-user-alt:before,.fa-user-large:before { + content: "\f406" +} + +.fa-user-alt-slash:before,.fa-user-large-slash:before { + content: "\f4fa" +} + +.fa-user-lock:before { + content: "\f502" +} + +.fa-user-minus:before { + content: "\f503" +} + +.fa-user-ninja:before { + content: "\f504" +} + +.fa-user-nurse:before { + content: "\f82f" +} + +.fa-user-edit:before,.fa-user-pen:before { + content: "\f4ff" +} + +.fa-user-plus:before { + content: "\f234" +} + +.fa-user-secret:before { + content: "\f21b" +} + +.fa-user-shield:before { + content: "\f505" +} + +.fa-user-slash:before { + content: "\f506" +} + +.fa-user-tag:before { + content: "\f507" +} + +.fa-user-tie:before { + content: "\f508" +} + +.fa-user-times:before,.fa-user-xmark:before { + content: "\f235" +} + +.fa-users:before { + content: "\f0c0" +} + +.fa-users-cog:before,.fa-users-gear:before { + content: "\f509" +} + +.fa-users-slash:before { + content: "\e073" +} + +.fa-cutlery:before,.fa-utensils:before { + content: "\f2e7" +} + +.fa-v:before { + content: "\56" +} + +.fa-shuttle-van:before,.fa-van-shuttle:before { + content: "\f5b6" +} + +.fa-vault:before { + content: "\e2c5" +} + +.fa-vector-square:before { + content: "\f5cb" +} + +.fa-venus:before { + content: "\f221" +} + +.fa-venus-double:before { + content: "\f226" +} + +.fa-venus-mars:before { + content: "\f228" +} + +.fa-vest:before { + content: "\e085" +} + +.fa-vest-patches:before { + content: "\e086" +} + +.fa-vial:before { + content: "\f492" +} + +.fa-vials:before { + content: "\f493" +} + +.fa-video-camera:before,.fa-video:before { + content: "\f03d" +} + +.fa-video-slash:before { + content: "\f4e2" +} + +.fa-vihara:before { + content: "\f6a7" +} + +.fa-virus:before { + content: "\e074" +} + +.fa-virus-covid:before { + content: "\e4a8" +} + +.fa-virus-covid-slash:before { + content: "\e4a9" +} + +.fa-virus-slash:before { + content: "\e075" +} + +.fa-viruses:before { + content: "\e076" +} + +.fa-voicemail:before { + content: "\f897" +} + +.fa-volleyball-ball:before,.fa-volleyball:before { + content: "\f45f" +} + +.fa-volume-high:before,.fa-volume-up:before { + content: "\f028" +} + +.fa-volume-down:before,.fa-volume-low:before { + content: "\f027" +} + +.fa-volume-off:before { + content: "\f026" +} + +.fa-volume-mute:before,.fa-volume-times:before,.fa-volume-xmark:before { + content: "\f6a9" +} + +.fa-vr-cardboard:before { + content: "\f729" +} + +.fa-w:before { + content: "\57" +} + +.fa-wallet:before { + content: "\f555" +} + +.fa-magic:before,.fa-wand-magic:before { + content: "\f0d0" +} + +.fa-magic-wand-sparkles:before,.fa-wand-magic-sparkles:before { + content: "\e2ca" +} + +.fa-wand-sparkles:before { + content: "\f72b" +} + +.fa-warehouse:before { + content: "\f494" +} + +.fa-water:before { + content: "\f773" +} + +.fa-ladder-water:before,.fa-swimming-pool:before,.fa-water-ladder:before { + content: "\f5c5" +} + +.fa-wave-square:before { + content: "\f83e" +} + +.fa-weight-hanging:before { + content: "\f5cd" +} + +.fa-weight-scale:before,.fa-weight:before { + content: "\f496" +} + +.fa-wheelchair:before { + content: "\f193" +} + +.fa-glass-whiskey:before,.fa-whiskey-glass:before { + content: "\f7a0" +} + +.fa-wifi-3:before,.fa-wifi-strong:before,.fa-wifi:before { + content: "\f1eb" +} + +.fa-wind:before { + content: "\f72e" +} + +.fa-window-maximize:before { + content: "\f2d0" +} + +.fa-window-minimize:before { + content: "\f2d1" +} + +.fa-window-restore:before { + content: "\f2d2" +} + +.fa-wine-bottle:before { + content: "\f72f" +} + +.fa-wine-glass:before { + content: "\f4e3" +} + +.fa-wine-glass-alt:before,.fa-wine-glass-empty:before { + content: "\f5ce" +} + +.fa-krw:before,.fa-won-sign:before,.fa-won:before { + content: "\f159" +} + +.fa-wrench:before { + content: "\f0ad" +} + +.fa-x:before { + content: "\58" +} + +.fa-x-ray:before { + content: "\f497" +} + +.fa-close:before,.fa-multiply:before,.fa-remove:before,.fa-times:before,.fa-xmark:before { + content: "\f00d" +} + +.fa-y:before { + content: "\59" +} + +.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen-sign:before,.fa-yen:before { + content: "\f157" +} + +.fa-yin-yang:before { + content: "\f6ad" +} + +.fa-z:before { + content: "\5a" +} + +.fa-sr-only,.fa-sr-only-focusable:not(:focus),.sr-only,.sr-only-focusable:not(:focus) { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0,0,0,0); + white-space: nowrap; + border-width: 0 +} + +:host,:root { + --fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands" +} + +@font-face { + font-family: "Font Awesome 6 Brands"; + font-style: normal; + font-weight: 400; + font-display: block; + src: url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype") +} + +.fa-brands,.fab { + font-family: "Font Awesome 6 Brands"; + font-weight: 400 +} + +.fa-42-group:before,.fa-innosoft:before { + content: "\e080" +} + +.fa-500px:before { + content: "\f26e" +} + +.fa-accessible-icon:before { + content: "\f368" +} + +.fa-accusoft:before { + content: "\f369" +} + +.fa-adn:before { + content: "\f170" +} + +.fa-adversal:before { + content: "\f36a" +} + +.fa-affiliatetheme:before { + content: "\f36b" +} + +.fa-airbnb:before { + content: "\f834" +} + +.fa-algolia:before { + content: "\f36c" +} + +.fa-alipay:before { + content: "\f642" +} + +.fa-amazon:before { + content: "\f270" +} + +.fa-amazon-pay:before { + content: "\f42c" +} + +.fa-amilia:before { + content: "\f36d" +} + +.fa-android:before { + content: "\f17b" +} + +.fa-angellist:before { + content: "\f209" +} + +.fa-angrycreative:before { + content: "\f36e" +} + +.fa-angular:before { + content: "\f420" +} + +.fa-app-store:before { + content: "\f36f" +} + +.fa-app-store-ios:before { + content: "\f370" +} + +.fa-apper:before { + content: "\f371" +} + +.fa-apple:before { + content: "\f179" +} + +.fa-apple-pay:before { + content: "\f415" +} + +.fa-artstation:before { + content: "\f77a" +} + +.fa-asymmetrik:before { + content: "\f372" +} + +.fa-atlassian:before { + content: "\f77b" +} + +.fa-audible:before { + content: "\f373" +} + +.fa-autoprefixer:before { + content: "\f41c" +} + +.fa-avianex:before { + content: "\f374" +} + +.fa-aviato:before { + content: "\f421" +} + +.fa-aws:before { + content: "\f375" +} + +.fa-bandcamp:before { + content: "\f2d5" +} + +.fa-battle-net:before { + content: "\f835" +} + +.fa-behance:before { + content: "\f1b4" +} + +.fa-behance-square:before { + content: "\f1b5" +} + +.fa-bilibili:before { + content: "\e3d9" +} + +.fa-bimobject:before { + content: "\f378" +} + +.fa-bitbucket:before { + content: "\f171" +} + +.fa-bitcoin:before { + content: "\f379" +} + +.fa-bity:before { + content: "\f37a" +} + +.fa-black-tie:before { + content: "\f27e" +} + +.fa-blackberry:before { + content: "\f37b" +} + +.fa-blogger:before { + content: "\f37c" +} + +.fa-blogger-b:before { + content: "\f37d" +} + +.fa-bluetooth:before { + content: "\f293" +} + +.fa-bluetooth-b:before { + content: "\f294" +} + +.fa-bootstrap:before { + content: "\f836" +} + +.fa-bots:before { + content: "\e340" +} + +.fa-btc:before { + content: "\f15a" +} + +.fa-buffer:before { + content: "\f837" +} + +.fa-buromobelexperte:before { + content: "\f37f" +} + +.fa-buy-n-large:before { + content: "\f8a6" +} + +.fa-buysellads:before { + content: "\f20d" +} + +.fa-canadian-maple-leaf:before { + content: "\f785" +} + +.fa-cc-amazon-pay:before { + content: "\f42d" +} + +.fa-cc-amex:before { + content: "\f1f3" +} + +.fa-cc-apple-pay:before { + content: "\f416" +} + +.fa-cc-diners-club:before { + content: "\f24c" +} + +.fa-cc-discover:before { + content: "\f1f2" +} + +.fa-cc-jcb:before { + content: "\f24b" +} + +.fa-cc-mastercard:before { + content: "\f1f1" +} + +.fa-cc-paypal:before { + content: "\f1f4" +} + +.fa-cc-stripe:before { + content: "\f1f5" +} + +.fa-cc-visa:before { + content: "\f1f0" +} + +.fa-centercode:before { + content: "\f380" +} + +.fa-centos:before { + content: "\f789" +} + +.fa-chrome:before { + content: "\f268" +} + +.fa-chromecast:before { + content: "\f838" +} + +.fa-cloudflare:before { + content: "\e07d" +} + +.fa-cloudscale:before { + content: "\f383" +} + +.fa-cloudsmith:before { + content: "\f384" +} + +.fa-cloudversify:before { + content: "\f385" +} + +.fa-cmplid:before { + content: "\e360" +} + +.fa-codepen:before { + content: "\f1cb" +} + +.fa-codiepie:before { + content: "\f284" +} + +.fa-confluence:before { + content: "\f78d" +} + +.fa-connectdevelop:before { + content: "\f20e" +} + +.fa-contao:before { + content: "\f26d" +} + +.fa-cotton-bureau:before { + content: "\f89e" +} + +.fa-cpanel:before { + content: "\f388" +} + +.fa-creative-commons:before { + content: "\f25e" +} + +.fa-creative-commons-by:before { + content: "\f4e7" +} + +.fa-creative-commons-nc:before { + content: "\f4e8" +} + +.fa-creative-commons-nc-eu:before { + content: "\f4e9" +} + +.fa-creative-commons-nc-jp:before { + content: "\f4ea" +} + +.fa-creative-commons-nd:before { + content: "\f4eb" +} + +.fa-creative-commons-pd:before { + content: "\f4ec" +} + +.fa-creative-commons-pd-alt:before { + content: "\f4ed" +} + +.fa-creative-commons-remix:before { + content: "\f4ee" +} + +.fa-creative-commons-sa:before { + content: "\f4ef" +} + +.fa-creative-commons-sampling:before { + content: "\f4f0" +} + +.fa-creative-commons-sampling-plus:before { + content: "\f4f1" +} + +.fa-creative-commons-share:before { + content: "\f4f2" +} + +.fa-creative-commons-zero:before { + content: "\f4f3" +} + +.fa-critical-role:before { + content: "\f6c9" +} + +.fa-css3:before { + content: "\f13c" +} + +.fa-css3-alt:before { + content: "\f38b" +} + +.fa-cuttlefish:before { + content: "\f38c" +} + +.fa-d-and-d:before { + content: "\f38d" +} + +.fa-d-and-d-beyond:before { + content: "\f6ca" +} + +.fa-dailymotion:before { + content: "\e052" +} + +.fa-dashcube:before { + content: "\f210" +} + +.fa-deezer:before { + content: "\e077" +} + +.fa-delicious:before { + content: "\f1a5" +} + +.fa-deploydog:before { + content: "\f38e" +} + +.fa-deskpro:before { + content: "\f38f" +} + +.fa-dev:before { + content: "\f6cc" +} + +.fa-deviantart:before { + content: "\f1bd" +} + +.fa-dhl:before { + content: "\f790" +} + +.fa-diaspora:before { + content: "\f791" +} + +.fa-digg:before { + content: "\f1a6" +} + +.fa-digital-ocean:before { + content: "\f391" +} + +.fa-discord:before { + content: "\f392" +} + +.fa-discourse:before { + content: "\f393" +} + +.fa-dochub:before { + content: "\f394" +} + +.fa-docker:before { + content: "\f395" +} + +.fa-draft2digital:before { + content: "\f396" +} + +.fa-dribbble:before { + content: "\f17d" +} + +.fa-dribbble-square:before { + content: "\f397" +} + +.fa-dropbox:before { + content: "\f16b" +} + +.fa-drupal:before { + content: "\f1a9" +} + +.fa-dyalog:before { + content: "\f399" +} + +.fa-earlybirds:before { + content: "\f39a" +} + +.fa-ebay:before { + content: "\f4f4" +} + +.fa-edge:before { + content: "\f282" +} + +.fa-edge-legacy:before { + content: "\e078" +} + +.fa-elementor:before { + content: "\f430" +} + +.fa-ello:before { + content: "\f5f1" +} + +.fa-ember:before { + content: "\f423" +} + +.fa-empire:before { + content: "\f1d1" +} + +.fa-envira:before { + content: "\f299" +} + +.fa-erlang:before { + content: "\f39d" +} + +.fa-ethereum:before { + content: "\f42e" +} + +.fa-etsy:before { + content: "\f2d7" +} + +.fa-evernote:before { + content: "\f839" +} + +.fa-expeditedssl:before { + content: "\f23e" +} + +.fa-facebook:before { + content: "\f09a" +} + +.fa-facebook-f:before { + content: "\f39e" +} + +.fa-facebook-messenger:before { + content: "\f39f" +} + +.fa-facebook-square:before { + content: "\f082" +} + +.fa-fantasy-flight-games:before { + content: "\f6dc" +} + +.fa-fedex:before { + content: "\f797" +} + +.fa-fedora:before { + content: "\f798" +} + +.fa-figma:before { + content: "\f799" +} + +.fa-firefox:before { + content: "\f269" +} + +.fa-firefox-browser:before { + content: "\e007" +} + +.fa-first-order:before { + content: "\f2b0" +} + +.fa-first-order-alt:before { + content: "\f50a" +} + +.fa-firstdraft:before { + content: "\f3a1" +} + +.fa-flickr:before { + content: "\f16e" +} + +.fa-flipboard:before { + content: "\f44d" +} + +.fa-fly:before { + content: "\f417" +} + +.fa-font-awesome-flag:before,.fa-font-awesome-logo-full:before,.fa-font-awesome:before { + content: "\f2b4" +} + +.fa-fonticons:before { + content: "\f280" +} + +.fa-fonticons-fi:before { + content: "\f3a2" +} + +.fa-fort-awesome:before { + content: "\f286" +} + +.fa-fort-awesome-alt:before { + content: "\f3a3" +} + +.fa-forumbee:before { + content: "\f211" +} + +.fa-foursquare:before { + content: "\f180" +} + +.fa-free-code-camp:before { + content: "\f2c5" +} + +.fa-freebsd:before { + content: "\f3a4" +} + +.fa-fulcrum:before { + content: "\f50b" +} + +.fa-galactic-republic:before { + content: "\f50c" +} + +.fa-galactic-senate:before { + content: "\f50d" +} + +.fa-get-pocket:before { + content: "\f265" +} + +.fa-gg:before { + content: "\f260" +} + +.fa-gg-circle:before { + content: "\f261" +} + +.fa-git:before { + content: "\f1d3" +} + +.fa-git-alt:before { + content: "\f841" +} + +.fa-git-square:before { + content: "\f1d2" +} + +.fa-github:before { + content: "\f09b" +} + +.fa-github-alt:before { + content: "\f113" +} + +.fa-github-square:before { + content: "\f092" +} + +.fa-gitkraken:before { + content: "\f3a6" +} + +.fa-gitlab:before { + content: "\f296" +} + +.fa-gitter:before { + content: "\f426" +} + +.fa-glide:before { + content: "\f2a5" +} + +.fa-glide-g:before { + content: "\f2a6" +} + +.fa-gofore:before { + content: "\f3a7" +} + +.fa-golang:before { + content: "\e40f" +} + +.fa-goodreads:before { + content: "\f3a8" +} + +.fa-goodreads-g:before { + content: "\f3a9" +} + +.fa-google:before { + content: "\f1a0" +} + +.fa-google-drive:before { + content: "\f3aa" +} + +.fa-google-pay:before { + content: "\e079" +} + +.fa-google-play:before { + content: "\f3ab" +} + +.fa-google-plus:before { + content: "\f2b3" +} + +.fa-google-plus-g:before { + content: "\f0d5" +} + +.fa-google-plus-square:before { + content: "\f0d4" +} + +.fa-google-wallet:before { + content: "\f1ee" +} + +.fa-gratipay:before { + content: "\f184" +} + +.fa-grav:before { + content: "\f2d6" +} + +.fa-gripfire:before { + content: "\f3ac" +} + +.fa-grunt:before { + content: "\f3ad" +} + +.fa-guilded:before { + content: "\e07e" +} + +.fa-gulp:before { + content: "\f3ae" +} + +.fa-hacker-news:before { + content: "\f1d4" +} + +.fa-hacker-news-square:before { + content: "\f3af" +} + +.fa-hackerrank:before { + content: "\f5f7" +} + +.fa-hashnode:before { + content: "\e499" +} + +.fa-hips:before { + content: "\f452" +} + +.fa-hire-a-helper:before { + content: "\f3b0" +} + +.fa-hive:before { + content: "\e07f" +} + +.fa-hooli:before { + content: "\f427" +} + +.fa-hornbill:before { + content: "\f592" +} + +.fa-hotjar:before { + content: "\f3b1" +} + +.fa-houzz:before { + content: "\f27c" +} + +.fa-html5:before { + content: "\f13b" +} + +.fa-hubspot:before { + content: "\f3b2" +} + +.fa-ideal:before { + content: "\e013" +} + +.fa-imdb:before { + content: "\f2d8" +} + +.fa-instagram:before { + content: "\f16d" +} + +.fa-instagram-square:before { + content: "\e055" +} + +.fa-instalod:before { + content: "\e081" +} + +.fa-intercom:before { + content: "\f7af" +} + +.fa-internet-explorer:before { + content: "\f26b" +} + +.fa-invision:before { + content: "\f7b0" +} + +.fa-ioxhost:before { + content: "\f208" +} + +.fa-itch-io:before { + content: "\f83a" +} + +.fa-itunes:before { + content: "\f3b4" +} + +.fa-itunes-note:before { + content: "\f3b5" +} + +.fa-java:before { + content: "\f4e4" +} + +.fa-jedi-order:before { + content: "\f50e" +} + +.fa-jenkins:before { + content: "\f3b6" +} + +.fa-jira:before { + content: "\f7b1" +} + +.fa-joget:before { + content: "\f3b7" +} + +.fa-joomla:before { + content: "\f1aa" +} + +.fa-js:before { + content: "\f3b8" +} + +.fa-js-square:before { + content: "\f3b9" +} + +.fa-jsfiddle:before { + content: "\f1cc" +} + +.fa-kaggle:before { + content: "\f5fa" +} + +.fa-keybase:before { + content: "\f4f5" +} + +.fa-keycdn:before { + content: "\f3ba" +} + +.fa-kickstarter:before { + content: "\f3bb" +} + +.fa-kickstarter-k:before { + content: "\f3bc" +} + +.fa-korvue:before { + content: "\f42f" +} + +.fa-laravel:before { + content: "\f3bd" +} + +.fa-lastfm:before { + content: "\f202" +} + +.fa-lastfm-square:before { + content: "\f203" +} + +.fa-leanpub:before { + content: "\f212" +} + +.fa-less:before { + content: "\f41d" +} + +.fa-line:before { + content: "\f3c0" +} + +.fa-linkedin:before { + content: "\f08c" +} + +.fa-linkedin-in:before { + content: "\f0e1" +} + +.fa-linode:before { + content: "\f2b8" +} + +.fa-linux:before { + content: "\f17c" +} + +.fa-lyft:before { + content: "\f3c3" +} + +.fa-magento:before { + content: "\f3c4" +} + +.fa-mailchimp:before { + content: "\f59e" +} + +.fa-mandalorian:before { + content: "\f50f" +} + +.fa-markdown:before { + content: "\f60f" +} + +.fa-mastodon:before { + content: "\f4f6" +} + +.fa-maxcdn:before { + content: "\f136" +} + +.fa-mdb:before { + content: "\f8ca" +} + +.fa-medapps:before { + content: "\f3c6" +} + +.fa-medium-m:before,.fa-medium:before { + content: "\f23a" +} + +.fa-medrt:before { + content: "\f3c8" +} + +.fa-meetup:before { + content: "\f2e0" +} + +.fa-megaport:before { + content: "\f5a3" +} + +.fa-mendeley:before { + content: "\f7b3" +} + +.fa-microblog:before { + content: "\e01a" +} + +.fa-microsoft:before { + content: "\f3ca" +} + +.fa-mix:before { + content: "\f3cb" +} + +.fa-mixcloud:before { + content: "\f289" +} + +.fa-mixer:before { + content: "\e056" +} + +.fa-mizuni:before { + content: "\f3cc" +} + +.fa-modx:before { + content: "\f285" +} + +.fa-monero:before { + content: "\f3d0" +} + +.fa-napster:before { + content: "\f3d2" +} + +.fa-neos:before { + content: "\f612" +} + +.fa-nimblr:before { + content: "\f5a8" +} + +.fa-node:before { + content: "\f419" +} + +.fa-node-js:before { + content: "\f3d3" +} + +.fa-npm:before { + content: "\f3d4" +} + +.fa-ns8:before { + content: "\f3d5" +} + +.fa-nutritionix:before { + content: "\f3d6" +} + +.fa-octopus-deploy:before { + content: "\e082" +} + +.fa-odnoklassniki:before { + content: "\f263" +} + +.fa-odnoklassniki-square:before { + content: "\f264" +} + +.fa-old-republic:before { + content: "\f510" +} + +.fa-opencart:before { + content: "\f23d" +} + +.fa-openid:before { + content: "\f19b" +} + +.fa-opera:before { + content: "\f26a" +} + +.fa-optin-monster:before { + content: "\f23c" +} + +.fa-orcid:before { + content: "\f8d2" +} + +.fa-osi:before { + content: "\f41a" +} + +.fa-padlet:before { + content: "\e4a0" +} + +.fa-page4:before { + content: "\f3d7" +} + +.fa-pagelines:before { + content: "\f18c" +} + +.fa-palfed:before { + content: "\f3d8" +} + +.fa-patreon:before { + content: "\f3d9" +} + +.fa-paypal:before { + content: "\f1ed" +} + +.fa-perbyte:before { + content: "\e083" +} + +.fa-periscope:before { + content: "\f3da" +} + +.fa-phabricator:before { + content: "\f3db" +} + +.fa-phoenix-framework:before { + content: "\f3dc" +} + +.fa-phoenix-squadron:before { + content: "\f511" +} + +.fa-php:before { + content: "\f457" +} + +.fa-pied-piper:before { + content: "\f2ae" +} + +.fa-pied-piper-alt:before { + content: "\f1a8" +} + +.fa-pied-piper-hat:before { + content: "\f4e5" +} + +.fa-pied-piper-pp:before { + content: "\f1a7" +} + +.fa-pied-piper-square:before { + content: "\e01e" +} + +.fa-pinterest:before { + content: "\f0d2" +} + +.fa-pinterest-p:before { + content: "\f231" +} + +.fa-pinterest-square:before { + content: "\f0d3" +} + +.fa-pix:before { + content: "\e43a" +} + +.fa-playstation:before { + content: "\f3df" +} + +.fa-product-hunt:before { + content: "\f288" +} + +.fa-pushed:before { + content: "\f3e1" +} + +.fa-python:before { + content: "\f3e2" +} + +.fa-qq:before { + content: "\f1d6" +} + +.fa-quinscape:before { + content: "\f459" +} + +.fa-quora:before { + content: "\f2c4" +} + +.fa-r-project:before { + content: "\f4f7" +} + +.fa-raspberry-pi:before { + content: "\f7bb" +} + +.fa-ravelry:before { + content: "\f2d9" +} + +.fa-react:before { + content: "\f41b" +} + +.fa-reacteurope:before { + content: "\f75d" +} + +.fa-readme:before { + content: "\f4d5" +} + +.fa-rebel:before { + content: "\f1d0" +} + +.fa-red-river:before { + content: "\f3e3" +} + +.fa-reddit:before { + content: "\f1a1" +} + +.fa-reddit-alien:before { + content: "\f281" +} + +.fa-reddit-square:before { + content: "\f1a2" +} + +.fa-redhat:before { + content: "\f7bc" +} + +.fa-renren:before { + content: "\f18b" +} + +.fa-replyd:before { + content: "\f3e6" +} + +.fa-researchgate:before { + content: "\f4f8" +} + +.fa-resolving:before { + content: "\f3e7" +} + +.fa-rev:before { + content: "\f5b2" +} + +.fa-rocketchat:before { + content: "\f3e8" +} + +.fa-rockrms:before { + content: "\f3e9" +} + +.fa-rust:before { + content: "\e07a" +} + +.fa-safari:before { + content: "\f267" +} + +.fa-salesforce:before { + content: "\f83b" +} + +.fa-sass:before { + content: "\f41e" +} + +.fa-schlix:before { + content: "\f3ea" +} + +.fa-scribd:before { + content: "\f28a" +} + +.fa-searchengin:before { + content: "\f3eb" +} + +.fa-sellcast:before { + content: "\f2da" +} + +.fa-sellsy:before { + content: "\f213" +} + +.fa-servicestack:before { + content: "\f3ec" +} + +.fa-shirtsinbulk:before { + content: "\f214" +} + +.fa-shopify:before { + content: "\e057" +} + +.fa-shopware:before { + content: "\f5b5" +} + +.fa-simplybuilt:before { + content: "\f215" +} + +.fa-sistrix:before { + content: "\f3ee" +} + +.fa-sith:before { + content: "\f512" +} + +.fa-sitrox:before { + content: "\e44a" +} + +.fa-sketch:before { + content: "\f7c6" +} + +.fa-skyatlas:before { + content: "\f216" +} + +.fa-skype:before { + content: "\f17e" +} + +.fa-slack-hash:before,.fa-slack:before { + content: "\f198" +} + +.fa-slideshare:before { + content: "\f1e7" +} + +.fa-snapchat-ghost:before,.fa-snapchat:before { + content: "\f2ab" +} + +.fa-snapchat-square:before { + content: "\f2ad" +} + +.fa-soundcloud:before { + content: "\f1be" +} + +.fa-sourcetree:before { + content: "\f7d3" +} + +.fa-speakap:before { + content: "\f3f3" +} + +.fa-speaker-deck:before { + content: "\f83c" +} + +.fa-spotify:before { + content: "\f1bc" +} + +.fa-square-font-awesome:before { + content: "\f425" +} + +.fa-font-awesome-alt:before,.fa-square-font-awesome-stroke:before { + content: "\f35c" +} + +.fa-squarespace:before { + content: "\f5be" +} + +.fa-stack-exchange:before { + content: "\f18d" +} + +.fa-stack-overflow:before { + content: "\f16c" +} + +.fa-stackpath:before { + content: "\f842" +} + +.fa-staylinked:before { + content: "\f3f5" +} + +.fa-steam:before { + content: "\f1b6" +} + +.fa-steam-square:before { + content: "\f1b7" +} + +.fa-steam-symbol:before { + content: "\f3f6" +} + +.fa-sticker-mule:before { + content: "\f3f7" +} + +.fa-strava:before { + content: "\f428" +} + +.fa-stripe:before { + content: "\f429" +} + +.fa-stripe-s:before { + content: "\f42a" +} + +.fa-studiovinari:before { + content: "\f3f8" +} + +.fa-stumbleupon:before { + content: "\f1a4" +} + +.fa-stumbleupon-circle:before { + content: "\f1a3" +} + +.fa-superpowers:before { + content: "\f2dd" +} + +.fa-supple:before { + content: "\f3f9" +} + +.fa-suse:before { + content: "\f7d6" +} + +.fa-swift:before { + content: "\f8e1" +} + +.fa-symfony:before { + content: "\f83d" +} + +.fa-teamspeak:before { + content: "\f4f9" +} + +.fa-telegram-plane:before,.fa-telegram:before { + content: "\f2c6" +} + +.fa-tencent-weibo:before { + content: "\f1d5" +} + +.fa-the-red-yeti:before { + content: "\f69d" +} + +.fa-themeco:before { + content: "\f5c6" +} + +.fa-themeisle:before { + content: "\f2b2" +} + +.fa-think-peaks:before { + content: "\f731" +} + +.fa-tiktok:before { + content: "\e07b" +} + +.fa-trade-federation:before { + content: "\f513" +} + +.fa-trello:before { + content: "\f181" +} + +.fa-tumblr:before { + content: "\f173" +} + +.fa-tumblr-square:before { + content: "\f174" +} + +.fa-twitch:before { + content: "\f1e8" +} + +.fa-twitter:before { + content: "\f099" +} + +.fa-twitter-square:before { + content: "\f081" +} + +.fa-typo3:before { + content: "\f42b" +} + +.fa-uber:before { + content: "\f402" +} + +.fa-ubuntu:before { + content: "\f7df" +} + +.fa-uikit:before { + content: "\f403" +} + +.fa-umbraco:before { + content: "\f8e8" +} + +.fa-uncharted:before { + content: "\e084" +} + +.fa-uniregistry:before { + content: "\f404" +} + +.fa-unity:before { + content: "\e049" +} + +.fa-unsplash:before { + content: "\e07c" +} + +.fa-untappd:before { + content: "\f405" +} + +.fa-ups:before { + content: "\f7e0" +} + +.fa-usb:before { + content: "\f287" +} + +.fa-usps:before { + content: "\f7e1" +} + +.fa-ussunnah:before { + content: "\f407" +} + +.fa-vaadin:before { + content: "\f408" +} + +.fa-viacoin:before { + content: "\f237" +} + +.fa-viadeo:before { + content: "\f2a9" +} + +.fa-viadeo-square:before { + content: "\f2aa" +} + +.fa-viber:before { + content: "\f409" +} + +.fa-vimeo:before { + content: "\f40a" +} + +.fa-vimeo-square:before { + content: "\f194" +} + +.fa-vimeo-v:before { + content: "\f27d" +} + +.fa-vine:before { + content: "\f1ca" +} + +.fa-vk:before { + content: "\f189" +} + +.fa-vnv:before { + content: "\f40b" +} + +.fa-vuejs:before { + content: "\f41f" +} + +.fa-watchman-monitoring:before { + content: "\e087" +} + +.fa-waze:before { + content: "\f83f" +} + +.fa-weebly:before { + content: "\f5cc" +} + +.fa-weibo:before { + content: "\f18a" +} + +.fa-weixin:before { + content: "\f1d7" +} + +.fa-whatsapp:before { + content: "\f232" +} + +.fa-whatsapp-square:before { + content: "\f40c" +} + +.fa-whmcs:before { + content: "\f40d" +} + +.fa-wikipedia-w:before { + content: "\f266" +} + +.fa-windows:before { + content: "\f17a" +} + +.fa-wirsindhandwerk:before,.fa-wsh:before { + content: "\e2d0" +} + +.fa-wix:before { + content: "\f5cf" +} + +.fa-wizards-of-the-coast:before { + content: "\f730" +} + +.fa-wodu:before { + content: "\e088" +} + +.fa-wolf-pack-battalion:before { + content: "\f514" +} + +.fa-wordpress:before { + content: "\f19a" +} + +.fa-wordpress-simple:before { + content: "\f411" +} + +.fa-wpbeginner:before { + content: "\f297" +} + +.fa-wpexplorer:before { + content: "\f2de" +} + +.fa-wpforms:before { + content: "\f298" +} + +.fa-wpressr:before { + content: "\f3e4" +} + +.fa-xbox:before { + content: "\f412" +} + +.fa-xing:before { + content: "\f168" +} + +.fa-xing-square:before { + content: "\f169" +} + +.fa-y-combinator:before { + content: "\f23b" +} + +.fa-yahoo:before { + content: "\f19e" +} + +.fa-yammer:before { + content: "\f840" +} + +.fa-yandex:before { + content: "\f413" +} + +.fa-yandex-international:before { + content: "\f414" +} + +.fa-yarn:before { + content: "\f7e3" +} + +.fa-yelp:before { + content: "\f1e9" +} + +.fa-yoast:before { + content: "\f2b1" +} + +.fa-youtube:before { + content: "\f167" +} + +.fa-youtube-square:before { + content: "\f431" +} + +.fa-zhihu:before { + content: "\f63f" +} + +:host,:root { + --fa-font-regular: normal 400 1em/1 "Font Awesome 6 Free" +} + +@font-face { + font-family: "Font Awesome 6 Free"; + font-style: normal; + font-weight: 400; + font-display: block; + src: url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype") +} + +.fa-regular,.far { + font-family: "Font Awesome 6 Free"; + font-weight: 400 +} + +:host,:root { + --fa-font-solid: normal 900 1em/1 "Font Awesome 6 Free" +} + +@font-face { + font-family: "Font Awesome 6 Free"; + font-style: normal; + font-weight: 900; + font-display: block; + src: url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype") +} + +.fa-solid,.fas { + font-family: "Font Awesome 6 Free"; + font-weight: 900 +} + +@font-face { + font-family: "Font Awesome 5 Brands"; + font-display: block; + font-weight: 400; + src: url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype") +} + +@font-face { + font-family: "Font Awesome 5 Free"; + font-display: block; + font-weight: 900; + src: url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype") +} + +@font-face { + font-family: "Font Awesome 5 Free"; + font-display: block; + font-weight: 400; + src: url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype") +} + +@font-face { + font-family: "FontAwesome"; + font-display: block; + src: url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype") +} + +@font-face { + font-family: "FontAwesome"; + font-display: block; + src: url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype") +} + +@font-face { + font-family: "FontAwesome"; + font-display: block; + src: url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype"); + unicode-range: u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc +} + +@font-face { + font-family: "FontAwesome"; + font-display: block; + src: url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype"); + unicode-range: u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f250,u+f252,u+f27a +} diff --git a/static/css/animate.min.css b/static/css/animate.min.css new file mode 100644 index 0000000..e69de29 diff --git a/static/css/bootstrap.min.css b/static/css/bootstrap.min.css new file mode 100644 index 0000000..653c3cc --- /dev/null +++ b/static/css/bootstrap.min.css @@ -0,0 +1,13181 @@ +@charset "UTF-8";/*! + * Bootstrap v5.3.0-alpha1 (https://getbootstrap.com/) + * Copyright 2011-2022 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: #0a58ca; + --bs-secondary-text: #6c757d; + --bs-success-text: #146c43; + --bs-info-text: #087990; + --bs-warning-text: #997404; + --bs-danger-text: #b02a37; + --bs-light-text: #6c757d; + --bs-dark-text: #495057; + --bs-primary-bg-subtle: #cfe2ff; + --bs-secondary-bg-subtle: #f8f9fa; + --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: #e9ecef; + --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-body-color-rgb: 33,37,41; + --bs-body-bg-rgb: 255,255,255; + --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, 0.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-emphasis-color: #000; + --bs-emphasis-color-rgb: 0,0,0; + --bs-secondary-color: rgba(33, 37, 41, 0.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, 0.5); + --bs-tertiary-color-rgb: 33,37,41; + --bs-tertiary-bg: #f8f9fa; + --bs-tertiary-bg-rgb: 248,249,250; + --bs-body-bg: #fff; + --bs-body-bg-rgb: 255,255,255; + --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-bg: #fff3cd; + --bs-border-width: 1px; + --bs-border-style: solid; + --bs-border-color: #dee2e6; + --bs-border-color-translucent: rgba(0, 0, 0, 0.175); + --bs-border-radius: 0.375rem; + --bs-border-radius-sm: 0.25rem; + --bs-border-radius-lg: 0.5rem; + --bs-border-radius-xl: 1rem; + --bs-border-radius-2xl: 2rem; + --bs-border-radius-pill: 50rem; + --bs-box-shadow: 0 0.5rem 1rem rgba(var(--bs-body-color-rgb), 0.15); + --bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(var(--bs-body-color-rgb), 0.075); + --bs-box-shadow-lg: 0 1rem 3rem rgba(var(--bs-body-color-rgb), 0.175); + --bs-box-shadow-inset: inset 0 1px 2px rgba(var(--bs-body-color-rgb), 0.075); + --bs-emphasis-color: #000; + --bs-form-control-bg: var(--bs-body-bg); + --bs-form-control-disabled-bg: var(--bs-secondary-bg); + --bs-highlight-bg: #fff3cd; + --bs-breakpoint-xs: 0; + --bs-breakpoint-sm: 576px; + --bs-breakpoint-md: 768px; + --bs-breakpoint-lg: 992px; + --bs-breakpoint-xl: 1200px; + --bs-breakpoint-xxl: 1400px +} + +[data-bs-theme=dark] { + --bs-body-color: #adb5bd; + --bs-body-color-rgb: 173,181,189; + --bs-body-bg: #212529; + --bs-body-bg-rgb: 33,37,41; + --bs-emphasis-color: #f8f9fa; + --bs-emphasis-color-rgb: 248,249,250; + --bs-secondary-color: rgba(173, 181, 189, 0.75); + --bs-secondary-color-rgb: 173,181,189; + --bs-secondary-bg: #343a40; + --bs-secondary-bg-rgb: 52,58,64; + --bs-tertiary-color: rgba(173, 181, 189, 0.5); + --bs-tertiary-color-rgb: 173,181,189; + --bs-tertiary-bg: #2b3035; + --bs-tertiary-bg-rgb: 43,48,53; + --bs-emphasis-color: #fff; + --bs-primary-text: #6ea8fe; + --bs-secondary-text: #dee2e6; + --bs-success-text: #75b798; + --bs-info-text: #6edff6; + --bs-warning-text: #ffda6a; + --bs-danger-text: #ea868f; + --bs-light-text: #f8f9fa; + --bs-dark-text: #dee2e6; + --bs-primary-bg-subtle: #031633; + --bs-secondary-bg-subtle: #212529; + --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: #495057; + --bs-success-border-subtle: #0f5132; + --bs-info-border-subtle: #055160; + --bs-warning-border-subtle: #664d03; + --bs-danger-border-subtle: #842029; + --bs-light-border-subtle: #495057; + --bs-dark-border-subtle: #343a40; + --bs-heading-color: #fff; + --bs-link-color: #6ea8fe; + --bs-link-hover-color: #9ec5fe; + --bs-link-color-rgb: 110,168,254; + --bs-link-hover-color-rgb: 158,197,254; + --bs-code-color: #e685b5; + --bs-border-color: #495057; + --bs-border-color-translucent: rgba(255, 255, 255, 0.15) +} + +*,::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,inherit) +} + +.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; + 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; + font-size: calc(1.275rem + .3vw); + line-height: inherit +} + +@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] { + outline-offset: -2px; + -webkit-appearance: textfield +} + +::-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-size: calc(1.625rem + 4.5vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-1 { + font-size:5rem + } +} + +.display-2 { + font-size: calc(1.575rem + 3.9vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-2 { + font-size:4.5rem + } +} + +.display-3 { + font-size: calc(1.525rem + 3.3vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-3 { + font-size:4rem + } +} + +.display-4 { + font-size: calc(1.475rem + 2.7vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-4 { + font-size:3.5rem + } +} + +.display-5 { + font-size: calc(1.425rem + 2.1vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-5 { + font-size:3rem + } +} + +.display-6 { + font-size: calc(1.375rem + 1.5vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-6 { + font-size:2.5rem + } +} + +.list-unstyled { + padding-left: 0; + list-style: none +} + +.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 + } +} + +.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.3333333333% +} + +.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.6666666667% +} + +.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: 0.25rem +} + +.g-1,.gy-1 { + --bs-gutter-y: 0.25rem +} + +.g-2,.gx-2 { + --bs-gutter-x: 0.5rem +} + +.g-2,.gy-2 { + --bs-gutter-y: 0.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.3333333333% + } + + .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.6666666667% + } + + .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: 0.25rem + } + + .g-sm-1,.gy-sm-1 { + --bs-gutter-y: 0.25rem + } + + .g-sm-2,.gx-sm-2 { + --bs-gutter-x: 0.5rem + } + + .g-sm-2,.gy-sm-2 { + --bs-gutter-y: 0.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.3333333333% + } + + .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.6666666667% + } + + .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: 0.25rem + } + + .g-md-1,.gy-md-1 { + --bs-gutter-y: 0.25rem + } + + .g-md-2,.gx-md-2 { + --bs-gutter-x: 0.5rem + } + + .g-md-2,.gy-md-2 { + --bs-gutter-y: 0.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.3333333333% + } + + .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.6666666667% + } + + .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: 0.25rem + } + + .g-lg-1,.gy-lg-1 { + --bs-gutter-y: 0.25rem + } + + .g-lg-2,.gx-lg-2 { + --bs-gutter-x: 0.5rem + } + + .g-lg-2,.gy-lg-2 { + --bs-gutter-y: 0.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.3333333333% + } + + .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.6666666667% + } + + .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: 0.25rem + } + + .g-xl-1,.gy-xl-1 { + --bs-gutter-y: 0.25rem + } + + .g-xl-2,.gx-xl-2 { + --bs-gutter-x: 0.5rem + } + + .g-xl-2,.gy-xl-2 { + --bs-gutter-y: 0.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.3333333333% + } + + .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.6666666667% + } + + .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: 0.25rem + } + + .g-xxl-1,.gy-xxl-1 { + --bs-gutter-y: 0.25rem + } + + .g-xxl-2,.gx-xxl-2 { + --bs-gutter-x: 0.5rem + } + + .g-xxl-2,.gy-xxl-2 { + --bs-gutter-y: 0.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: var(--bs-body-color); + --bs-table-bg: transparent; + --bs-table-border-color: var(--bs-border-color); + --bs-table-accent-bg: transparent; + --bs-table-striped-color: var(--bs-body-color); + --bs-table-striped-bg: rgba(0, 0, 0, 0.05); + --bs-table-active-color: var(--bs-body-color); + --bs-table-active-bg: rgba(0, 0, 0, 0.1); + --bs-table-hover-color: var(--bs-body-color); + --bs-table-hover-bg: rgba(0, 0, 0, 0.075); + width: 100%; + margin-bottom: 1rem; + color: var(--bs-table-color); + vertical-align: top; + border-color: var(--bs-table-border-color) +} + +.table>:not(caption)>*>* { + padding: .5rem .5rem; + background-color: var(--bs-table-bg); + border-bottom-width: var(--bs-border-width); + box-shadow: inset 0 0 0 9999px 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 .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-accent-bg: var(--bs-table-striped-bg); + color: var(--bs-table-striped-color) +} + +.table-striped-columns>:not(caption)>tr>:nth-child(2n) { + --bs-table-accent-bg: var(--bs-table-striped-bg); + color: var(--bs-table-striped-color) +} + +.table-active { + --bs-table-accent-bg: var(--bs-table-active-bg); + color: var(--bs-table-active-color) +} + +.table-hover>tbody>tr:hover>* { + --bs-table-accent-bg: var(--bs-table-hover-bg); + color: var(--bs-table-hover-color) +} + +.table-primary { + --bs-table-color: #000; + --bs-table-bg: #cfe2ff; + --bs-table-border-color: #bacbe6; + --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: #cbccce; + --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: #bcd0c7; + --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: #badce3; + --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: #e6dbb9; + --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: #dfc2c4; + --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: #dfe0e1; + --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: #373b3e; + --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); + background-color: var(--bs-form-control-bg); + background-clip: padding-box; + border: var(--bs-border-width) solid var(--bs-border-color); + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: .375rem; + 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-form-control-bg); + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 .25rem rgba(13,110,253,.25) +} + +.form-control::-webkit-date-and-time-value { + height: 1.5em +} + +.form-control::-webkit-datetime-edit { + display: block; + padding: 0 +} + +.form-control::-moz-placeholder { + color: var(--bs-secondary-color); + opacity: 1 +} + +.form-control::placeholder { + color: var(--bs-secondary-color); + opacity: 1 +} + +.form-control:disabled { + background-color: var(--bs-form-control-disabled-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: .25rem +} + +.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: .5rem +} + +.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: .375rem +} + +.form-control-color::-webkit-color-swatch { + border-radius: .375rem +} + +.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; + -moz-padding-start: calc(0.75rem - 3px); + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: var(--bs-body-color); + background-color: var(--bs-form-control-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: .375rem; + transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none +} + +@media (prefers-reduced-motion:reduce) { + .form-select { + transition: none + } +} + +.form-select:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 .25rem rgba(13,110,253,.25) +} + +.form-select[multiple],.form-select[size]:not([size="1"]) { + padding-right: .75rem; + background-image: none +} + +.form-select:disabled { + background-color: var(--bs-form-control-disabled-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: .25rem +} + +.form-select-lg { + padding-top: .5rem; + padding-bottom: .5rem; + padding-left: 1rem; + font-size: 1.25rem; + border-radius: .5rem +} + +[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='%23adb5bd' 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-form-control-bg); + width: 1em; + height: 1em; + margin-top: .25em; + vertical-align: top; + 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-appearance: none; + -moz-appearance: none; + appearance: none; + -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 rgba(13,110,253,.25) +} + +.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; + background-color: transparent; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none +} + +.form-range:focus { + outline: 0 +} + +.form-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25) +} + +.form-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25) +} + +.form-range::-moz-focus-outer { + border: 0 +} + +.form-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -.25rem; + 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; + -webkit-appearance: none; + appearance: none +} + +@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-tertiary-bg); + border-color: transparent; + border-radius: 1rem +} + +.form-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + 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; + -moz-appearance: none; + appearance: none +} + +@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-tertiary-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::before:not(.form-control:disabled) { + position: absolute; + top: var(--bs-border-width); + left: var(--bs-border-width); + width: calc(100% - (calc(calc(.375em + .1875rem) + calc(.75em + .375rem)))); + height: 1.875em; + content: ""; + background-color: var(--bs-form-control-bg); + border-radius: .375rem +} + +.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select { + height: calc(3.5rem + calc(var(--bs-border-width) * 2)); + line-height: 1.25 +} + +.form-floating>label { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + padding: 1rem .75rem; + overflow: hidden; + 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::-moz-placeholder,.form-floating>.form-control::-moz-placeholder { + color: transparent +} + +.form-floating>.form-control-plaintext::placeholder,.form-floating>.form-control::placeholder { + color: transparent +} + +.form-floating>.form-control-plaintext:not(:-moz-placeholder-shown),.form-floating>.form-control:not(:-moz-placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: .625rem +} + +.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 +} + +.form-floating>.form-control:not(:-moz-placeholder-shown)~label { + opacity: .65; + transform: scale(.85) translateY(-.5rem) translateX(.15rem) +} + +.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 { + opacity: .65; + transform: scale(.85) translateY(-.5rem) translateX(.15rem) +} + +.form-floating>.form-control:-webkit-autofill~label { + opacity: .65; + transform: scale(.85) translateY(-.5rem) translateX(.15rem) +} + +.form-floating>.form-control-plaintext~label { + border-width: var(--bs-border-width) 0 +} + +.form-floating>.form-control: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: .375rem +} + +.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: .5rem +} + +.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: .25rem +} + +.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(var(--bs-border-width) * -1); + 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-success-text) +} + +.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-success); + 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.1z'/%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-success); + 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-success) +} + +.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.1z'/%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-success); + 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(3rem + calc(1.5em + .75rem)) +} + +.form-check-input.is-valid,.was-validated .form-check-input:valid { + border-color: var(--bs-success) +} + +.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked { + background-color: var(--bs-success-text) +} + +.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-success-text) +} + +.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-danger-text) +} + +.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-danger); + 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-danger); + 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-danger) +} + +.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-danger); + 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(3rem + calc(1.5em + .75rem)) +} + +.form-check-input.is-invalid,.was-validated .form-check-input:invalid { + border-color: var(--bs-danger) +} + +.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked { + background-color: var(--bs-danger-text) +} + +.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-danger-text) +} + +.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: 0.75rem; + --bs-btn-padding-y: 0.375rem; + --bs-btn-font-family: ; + --bs-btn-font-size: 1rem; + --bs-btn-font-weight: 400; + --bs-btn-line-height: 1.5; + --bs-btn-color: #212529; + --bs-btn-bg: transparent; + --bs-btn-border-width: var(--bs-border-width); + --bs-btn-border-color: transparent; + --bs-btn-border-radius: 0.375rem; + --bs-btn-hover-border-color: transparent; + --bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15),0 1px 1px rgba(0, 0, 0, 0.075); + --bs-btn-disabled-opacity: 0.65; + --bs-btn-focus-box-shadow: 0 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.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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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: none; + --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: 0.5rem; + --bs-btn-padding-x: 1rem; + --bs-btn-font-size: 1.25rem; + --bs-btn-border-radius: 0.5rem +} + +.btn-group-sm>.btn,.btn-sm { + --bs-btn-padding-y: 0.25rem; + --bs-btn-padding-x: 0.5rem; + --bs-btn-font-size: 0.875rem; + --bs-btn-border-radius: 0.25rem +} + +.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: 0.5rem; + --bs-dropdown-spacer: 0.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: 0.375rem; + --bs-dropdown-border-width: var(--bs-border-width); + --bs-dropdown-inner-border-radius: calc(0.375rem - var(--bs-border-width)); + --bs-dropdown-divider-bg: var(--bs-border-color-translucent); + --bs-dropdown-divider-margin-y: 0.5rem; + --bs-dropdown-box-shadow: 0 0.5rem 1rem rgba(var(--bs-body-color-rgb), 0.15); + --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: #adb5bd; + --bs-dropdown-item-padding-x: 1rem; + --bs-dropdown-item-padding-y: 0.25rem; + --bs-dropdown-header-color: #6c757d; + --bs-dropdown-header-padding-x: 1rem; + --bs-dropdown-header-padding-y: 0.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, 0.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: .375rem +} + +.btn-group>.btn-group:not(:first-child),.btn-group>:not(.btn-check:first-child)+.btn { + margin-left: calc(var(--bs-border-width) * -1) +} + +.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(var(--bs-border-width) * -1) +} + +.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~.btn { + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +.nav { + --bs-nav-link-padding-x: 1rem; + --bs-nav-link-padding-y: 0.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; + 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.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)); + background: 0 0; + 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-link.disabled,.nav-tabs .nav-link:disabled { + color: var(--bs-nav-link-disabled-color); + background-color: transparent; + border-color: transparent +} + +.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: 0.375rem; + --bs-nav-pills-link-active-color: #fff; + --bs-nav-pills-link-active-bg: #0d6efd +} + +.nav-pills .nav-link { + background: 0 0; + border: 0; + border-radius: var(--bs-nav-pills-border-radius) +} + +.nav-pills .nav-link:disabled { + color: var(--bs-nav-link-disabled-color); + background-color: transparent; + border-color: transparent +} + +.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-fill .nav-item,.nav-fill>.nav-link { + flex: 1 1 auto; + text-align: center +} + +.nav-justified .nav-item,.nav-justified>.nav-link { + flex-basis: 0; + flex-grow: 1; + text-align: center +} + +.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: 0.5rem; + --bs-navbar-color: rgba(var(--bs-emphasis-color-rgb), 0.65); + --bs-navbar-hover-color: rgba(var(--bs-emphasis-color-rgb), 0.8); + --bs-navbar-disabled-color: rgba(var(--bs-emphasis-color-rgb), 0.3); + --bs-navbar-active-color: rgba(var(--bs-emphasis-color-rgb), 1); + --bs-navbar-brand-padding-y: 0.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: 0.5rem; + --bs-navbar-toggler-padding-y: 0.25rem; + --bs-navbar-toggler-padding-x: 0.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), 0.15); + --bs-navbar-toggler-border-radius: 0.375rem; + --bs-navbar-toggler-focus-width: 0.25rem; + --bs-navbar-toggler-transition: box-shadow 0.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: 0.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 .show>.nav-link { + 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-basis: 100%; + flex-grow: 1; + 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 { + --bs-navbar-color: rgba(255, 255, 255, 0.55); + --bs-navbar-hover-color: rgba(255, 255, 255, 0.75); + --bs-navbar-disabled-color: rgba(255, 255, 255, 0.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, 0.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 { + --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: 0.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: 0.5rem; + --bs-card-cap-padding-x: 1rem; + --bs-card-cap-bg: rgba(var(--bs-body-color-rgb), 0.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: 0.75rem; + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + height: var(--bs-card-height); + 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 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out,border-radius 0.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='%23212529'%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-.708z'/%3e%3c/svg%3e"); + --bs-accordion-btn-icon-width: 1.25rem; + --bs-accordion-btn-icon-transform: rotate(-180deg); + --bs-accordion-btn-icon-transition: transform 0.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='%230a58ca'%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-.708z'/%3e%3c/svg%3e"); + --bs-accordion-btn-focus-border-color: #86b7fe; + --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + --bs-accordion-body-padding-x: 1.25rem; + --bs-accordion-body-padding-y: 1rem; + --bs-accordion-active-color: var(--bs-primary-text); + --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; + border-color: var(--bs-accordion-btn-focus-border-color); + 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-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-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-collapse { + border-width: 0 +} + +.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-button,.accordion-flush .accordion-item .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-.708z'/%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-.708z'/%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: 0.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: 0.75rem; + --bs-pagination-padding-y: 0.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 0.25rem rgba(13, 110, 253, 0.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(var(--bs-border-width) * -1) +} + +.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: 0.75rem; + --bs-pagination-font-size: 1.25rem; + --bs-pagination-border-radius: 0.5rem +} + +.pagination-sm { + --bs-pagination-padding-x: 0.5rem; + --bs-pagination-padding-y: 0.25rem; + --bs-pagination-font-size: 0.875rem; + --bs-pagination-border-radius: 0.25rem +} + +.badge { + --bs-badge-padding-x: 0.65em; + --bs-badge-padding-y: 0.35em; + --bs-badge-font-size: 0.75em; + --bs-badge-font-weight: 700; + --bs-badge-color: #fff; + --bs-badge-border-radius: 0.375rem; + 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: 0.375rem; + --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); + --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) +} + +.alert-secondary { + --bs-alert-color: var(--bs-secondary-text); + --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) +} + +.alert-success { + --bs-alert-color: var(--bs-success-text); + --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) +} + +.alert-info { + --bs-alert-color: var(--bs-info-text); + --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) +} + +.alert-warning { + --bs-alert-color: var(--bs-warning-text); + --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) +} + +.alert-danger { + --bs-alert-color: var(--bs-danger-text); + --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) +} + +.alert-light { + --bs-alert-color: var(--bs-light-text); + --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) +} + +.alert-dark { + --bs-alert-color: var(--bs-dark-text); + --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) +} + +@keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem + } +} + +.progress,.progress-stacked { + --bs-progress-height: 1rem; + --bs-progress-font-size: 0.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 0.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: 0.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-action { + width: 100%; + color: var(--bs-list-group-action-color); + text-align: inherit +} + +.list-group-item-action:focus,.list-group-item-action: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:active { + color: var(--bs-list-group-action-active-color); + background-color: var(--bs-list-group-action-active-bg) +} + +.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-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); + --bs-list-group-bg: var(--bs-primary-bg-subtle); + --bs-list-group-border-color: var(--bs-primary-border-subtle) +} + +.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover { + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-primary-border-subtle) +} + +.list-group-item-primary.list-group-item-action:active { + --bs-list-group-active-color: var(--bs-emphasis-color); + --bs-list-group-active-bg: var(--bs-primary-text); + --bs-list-group-active-border-color: var(--bs-primary-text) +} + +.list-group-item-secondary { + --bs-list-group-color: var(--bs-secondary-text); + --bs-list-group-bg: var(--bs-secondary-bg-subtle); + --bs-list-group-border-color: var(--bs-secondary-border-subtle) +} + +.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover { + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-secondary-border-subtle) +} + +.list-group-item-secondary.list-group-item-action:active { + --bs-list-group-active-color: var(--bs-emphasis-color); + --bs-list-group-active-bg: var(--bs-secondary-text); + --bs-list-group-active-border-color: var(--bs-secondary-text) +} + +.list-group-item-success { + --bs-list-group-color: var(--bs-success-text); + --bs-list-group-bg: var(--bs-success-bg-subtle); + --bs-list-group-border-color: var(--bs-success-border-subtle) +} + +.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover { + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-success-border-subtle) +} + +.list-group-item-success.list-group-item-action:active { + --bs-list-group-active-color: var(--bs-emphasis-color); + --bs-list-group-active-bg: var(--bs-success-text); + --bs-list-group-active-border-color: var(--bs-success-text) +} + +.list-group-item-info { + --bs-list-group-color: var(--bs-info-text); + --bs-list-group-bg: var(--bs-info-bg-subtle); + --bs-list-group-border-color: var(--bs-info-border-subtle) +} + +.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover { + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-info-border-subtle) +} + +.list-group-item-info.list-group-item-action:active { + --bs-list-group-active-color: var(--bs-emphasis-color); + --bs-list-group-active-bg: var(--bs-info-text); + --bs-list-group-active-border-color: var(--bs-info-text) +} + +.list-group-item-warning { + --bs-list-group-color: var(--bs-warning-text); + --bs-list-group-bg: var(--bs-warning-bg-subtle); + --bs-list-group-border-color: var(--bs-warning-border-subtle) +} + +.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover { + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-warning-border-subtle) +} + +.list-group-item-warning.list-group-item-action:active { + --bs-list-group-active-color: var(--bs-emphasis-color); + --bs-list-group-active-bg: var(--bs-warning-text); + --bs-list-group-active-border-color: var(--bs-warning-text) +} + +.list-group-item-danger { + --bs-list-group-color: var(--bs-danger-text); + --bs-list-group-bg: var(--bs-danger-bg-subtle); + --bs-list-group-border-color: var(--bs-danger-border-subtle) +} + +.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover { + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-danger-border-subtle) +} + +.list-group-item-danger.list-group-item-action:active { + --bs-list-group-active-color: var(--bs-emphasis-color); + --bs-list-group-active-bg: var(--bs-danger-text); + --bs-list-group-active-border-color: var(--bs-danger-text) +} + +.list-group-item-light { + --bs-list-group-color: var(--bs-light-text); + --bs-list-group-bg: var(--bs-light-bg-subtle); + --bs-list-group-border-color: var(--bs-light-border-subtle) +} + +.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover { + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-light-border-subtle) +} + +.list-group-item-light.list-group-item-action:active { + --bs-list-group-active-color: var(--bs-emphasis-color); + --bs-list-group-active-bg: var(--bs-light-text); + --bs-list-group-active-border-color: var(--bs-light-text) +} + +.list-group-item-dark { + --bs-list-group-color: var(--bs-dark-text); + --bs-list-group-bg: var(--bs-dark-bg-subtle); + --bs-list-group-border-color: var(--bs-dark-border-subtle) +} + +.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover { + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-dark-border-subtle) +} + +.list-group-item-dark.list-group-item-action:active { + --bs-list-group-active-color: var(--bs-emphasis-color); + --bs-list-group-active-bg: var(--bs-dark-text); + --bs-list-group-active-border-color: var(--bs-dark-text) +} + +.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.414z'/%3e%3c/svg%3e"); + --bs-btn-close-opacity: 0.5; + --bs-btn-close-hover-opacity: 0.75; + --bs-btn-close-focus-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + --bs-btn-close-focus-opacity: 1; + --bs-btn-close-disabled-opacity: 0.25; + --bs-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%); + box-sizing: content-box; + width: 1em; + height: 1em; + padding: .25em .25em; + color: var(--bs-btn-close-color); + background: transparent var(--bs-btn-close-bg) center/1em auto no-repeat; + 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 { + filter: var(--bs-btn-close-white-filter) +} + +[data-bs-theme=dark] .btn-close { + filter: var(--bs-btn-close-white-filter) +} + +.toast { + --bs-toast-zindex: 1090; + --bs-toast-padding-x: 0.75rem; + --bs-toast-padding-y: 0.5rem; + --bs-toast-spacing: 1.5rem; + --bs-toast-max-width: 350px; + --bs-toast-font-size: 0.875rem; + --bs-toast-color: ; + --bs-toast-bg: rgba(var(--bs-body-bg-rgb), 0.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), 0.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: 0.5rem; + --bs-modal-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: 0 0.125rem 0.25rem rgba(var(--bs-body-color-rgb), 0.075); + --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: 0.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 { + transition: transform .3s ease-out; + transform: translate(0,-50px) +} + +@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: 0.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; + justify-content: space-between; + 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: calc(-.5 * var(--bs-modal-header-padding-y)) calc(-.5 * var(--bs-modal-header-padding-x)) calc(-.5 * var(--bs-modal-header-padding-y)) 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: 0 0.5rem 1rem rgba(var(--bs-body-color-rgb), 0.15) + } + + .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: 0.5rem; + --bs-tooltip-padding-y: 0.25rem; + --bs-tooltip-margin: ; + --bs-tooltip-font-size: 0.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: 0.9; + --bs-tooltip-arrow-width: 0.8rem; + --bs-tooltip-arrow-height: 0.4rem; + z-index: var(--bs-tooltip-zindex); + display: block; + padding: var(--bs-tooltip-arrow-height); + 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: 0 +} + +.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: 0; + 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: 0 +} + +.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: 0; + 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: 0.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: 0 0.5rem 1rem rgba(var(--bs-body-color-rgb), 0.15); + --bs-popover-header-padding-x: 1rem; + --bs-popover-header-padding-y: 0.5rem; + --bs-popover-header-font-size: 1rem; + --bs-popover-header-color: ; + --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: 0.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: translateX(100%) +} + +.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end) { + transform: translateX(-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; + 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 0z'/%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-.708z'/%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%; + list-style: none +} + +.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: #fff; + 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: #fff; + text-align: center +} + +.carousel-dark .carousel-control-next-icon,.carousel-dark .carousel-control-prev-icon { + filter: invert(1) grayscale(100) +} + +.carousel-dark .carousel-indicators [data-bs-target] { + background-color: #000 +} + +.carousel-dark .carousel-caption { + color: #000 +} + +[data-bs-theme=dark] .carousel .carousel-control-next-icon,[data-bs-theme=dark] .carousel .carousel-control-prev-icon { + filter: invert(1) grayscale(100) +} + +[data-bs-theme=dark] .carousel .carousel-indicators [data-bs-target] { + background-color: #000 +} + +[data-bs-theme=dark] .carousel .carousel-caption { + color: #000 +} + +.spinner-border,.spinner-grow { + display: inline-block; + 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: -0.125em; + --bs-spinner-border-width: 0.25em; + --bs-spinner-animation-speed: 0.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: 0.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: -0.125em; + --bs-spinner-animation-speed: 0.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: 0 0.125rem 0.25rem rgba(var(--bs-body-color-rgb), 0.075); + --bs-offcanvas-transition: transform 0.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: translateX(-100%) + } +} + +@media (max-width: 575.98px) { + .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: translateX(100%) + } +} + +@media (max-width: 575.98px) { + .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%) + } +} + +@media (max-width: 575.98px) { + .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%) + } +} + +@media (max-width: 575.98px) { + .offcanvas-sm.show:not(.hiding),.offcanvas-sm.showing { + transform:none + } +} + +@media (max-width: 575.98px) { + .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: translateX(-100%) + } +} + +@media (max-width: 767.98px) { + .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: translateX(100%) + } +} + +@media (max-width: 767.98px) { + .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%) + } +} + +@media (max-width: 767.98px) { + .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%) + } +} + +@media (max-width: 767.98px) { + .offcanvas-md.show:not(.hiding),.offcanvas-md.showing { + transform:none + } +} + +@media (max-width: 767.98px) { + .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: translateX(-100%) + } +} + +@media (max-width: 991.98px) { + .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: translateX(100%) + } +} + +@media (max-width: 991.98px) { + .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%) + } +} + +@media (max-width: 991.98px) { + .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%) + } +} + +@media (max-width: 991.98px) { + .offcanvas-lg.show:not(.hiding),.offcanvas-lg.showing { + transform:none + } +} + +@media (max-width: 991.98px) { + .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: translateX(-100%) + } +} + +@media (max-width: 1199.98px) { + .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: translateX(100%) + } +} + +@media (max-width: 1199.98px) { + .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%) + } +} + +@media (max-width: 1199.98px) { + .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%) + } +} + +@media (max-width: 1199.98px) { + .offcanvas-xl.show:not(.hiding),.offcanvas-xl.showing { + transform:none + } +} + +@media (max-width: 1199.98px) { + .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: translateX(-100%) + } +} + +@media (max-width: 1399.98px) { + .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: translateX(100%) + } +} + +@media (max-width: 1399.98px) { + .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%) + } +} + +@media (max-width: 1399.98px) { + .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%) + } +} + +@media (max-width: 1399.98px) { + .offcanvas-xxl.show:not(.hiding),.offcanvas-xxl.showing { + transform:none + } +} + +@media (max-width: 1399.98px) { + .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: translateX(-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: translateX(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; + justify-content: space-between; + 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)) +} + +.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,0.8) 75%,#000 95%); + mask-image: linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%); + -webkit-mask-size: 200% 100%; + mask-size: 200% 100%; + animation: placeholder-wave 2s linear infinite +} + +@keyframes placeholder-wave { + 100% { + -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(13,110,253,var(--bs-bg-opacity,1))!important +} + +.text-bg-secondary { + color: #fff!important; + background-color: RGBA(108,117,125,var(--bs-bg-opacity,1))!important +} + +.text-bg-success { + color: #fff!important; + background-color: RGBA(25,135,84,var(--bs-bg-opacity,1))!important +} + +.text-bg-info { + color: #000!important; + background-color: RGBA(13,202,240,var(--bs-bg-opacity,1))!important +} + +.text-bg-warning { + color: #000!important; + background-color: RGBA(255,193,7,var(--bs-bg-opacity,1))!important +} + +.text-bg-danger { + color: #fff!important; + background-color: RGBA(220,53,69,var(--bs-bg-opacity,1))!important +} + +.text-bg-light { + color: #000!important; + background-color: RGBA(248,249,250,var(--bs-bg-opacity,1))!important +} + +.text-bg-dark { + color: #fff!important; + background-color: RGBA(33,37,41,var(--bs-bg-opacity,1))!important +} + +.link-primary { + color: #0d6efd!important +} + +.link-primary:focus,.link-primary:hover { + color: #0a58ca!important +} + +.link-secondary { + color: #6c757d!important +} + +.link-secondary:focus,.link-secondary:hover { + color: #565e64!important +} + +.link-success { + color: #198754!important +} + +.link-success:focus,.link-success:hover { + color: #146c43!important +} + +.link-info { + color: #0dcaf0!important +} + +.link-info:focus,.link-info:hover { + color: #3dd5f3!important +} + +.link-warning { + color: #ffc107!important +} + +.link-warning:focus,.link-warning:hover { + color: #ffcd39!important +} + +.link-danger { + color: #dc3545!important +} + +.link-danger:focus,.link-danger:hover { + color: #b02a37!important +} + +.link-light { + color: #f8f9fa!important +} + +.link-light:focus,.link-light:hover { + color: #f9fafb!important +} + +.link-dark { + color: #212529!important +} + +.link-dark:focus,.link-dark:hover { + color: #1a1e21!important +} + +.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) { + position: absolute!important; + 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 +} + +.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: 1px; + 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-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: 0 .5rem 1rem rgba(var(--bs-body-color-rgb),.15)!important +} + +.shadow-sm { + box-shadow: 0 .125rem .25rem rgba(var(--bs-body-color-rgb),.075)!important +} + +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(var(--bs-body-color-rgb),.175)!important +} + +.shadow-none { + box-shadow: none!important +} + +.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: translateX(-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-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 { + --bs-border-width: 1px +} + +.border-2 { + --bs-border-width: 2px +} + +.border-3 { + --bs-border-width: 3px +} + +.border-4 { + --bs-border-width: 4px +} + +.border-5 { + --bs-border-width: 5px +} + +.border-opacity-10 { + --bs-border-opacity: 0.1 +} + +.border-opacity-25 { + --bs-border-opacity: 0.25 +} + +.border-opacity-50 { + --bs-border-opacity: 0.5 +} + +.border-opacity-75 { + --bs-border-opacity: 0.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: 0.25rem!important; + column-gap: .25rem!important +} + +.column-gap-2 { + -moz-column-gap: 0.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: rgba(0,0,0,.5)!important +} + +.text-white-50 { + --bs-text-opacity: 1; + color: rgba(255,255,255,.5)!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: 0.25 +} + +.text-opacity-50 { + --bs-text-opacity: 0.5 +} + +.text-opacity-75 { + --bs-text-opacity: 0.75 +} + +.text-opacity-100 { + --bs-text-opacity: 1 +} + +.text-primary-emphasis { + color: var(--bs-primary-text)!important +} + +.text-secondary-emphasis { + color: var(--bs-secondary-text)!important +} + +.text-success-emphasis { + color: var(--bs-success-text)!important +} + +.text-info-emphasis { + color: var(--bs-info-text)!important +} + +.text-warning-emphasis { + color: var(--bs-warning-text)!important +} + +.text-danger-emphasis { + color: var(--bs-danger-text)!important +} + +.text-light-emphasis { + color: var(--bs-light-text)!important +} + +.text-dark-emphasis { + color: var(--bs-dark-text)!important +} + +.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-body-emphasis { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-emphasis-bg-rgb),var(--bs-bg-opacity))!important +} + +.bg-opacity-10 { + --bs-bg-opacity: 0.1 +} + +.bg-opacity-25 { + --bs-bg-opacity: 0.25 +} + +.bg-opacity-50 { + --bs-bg-opacity: 0.5 +} + +.bg-opacity-75 { + --bs-bg-opacity: 0.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-2xl)!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-2xl)!important; + border-top-right-radius: var(--bs-border-radius-2xl)!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-2xl)!important; + border-bottom-right-radius: var(--bs-border-radius-2xl)!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-2xl)!important; + border-bottom-left-radius: var(--bs-border-radius-2xl)!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-2xl)!important; + border-top-left-radius: var(--bs-border-radius-2xl)!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-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: 0.25rem!important; + column-gap: .25rem!important + } + + .column-gap-sm-2 { + -moz-column-gap: 0.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-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: 0.25rem!important; + column-gap: .25rem!important + } + + .column-gap-md-2 { + -moz-column-gap: 0.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-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: 0.25rem!important; + column-gap: .25rem!important + } + + .column-gap-lg-2 { + -moz-column-gap: 0.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-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: 0.25rem!important; + column-gap: .25rem!important + } + + .column-gap-xl-2 { + -moz-column-gap: 0.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-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: 0.25rem!important; + column-gap: .25rem!important + } + + .column-gap-xxl-2 { + -moz-column-gap: 0.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-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 + } +} + +/*# sourceMappingURL=bootstrap.min.css.map */ diff --git a/static/css/css2 b/static/css/css2 new file mode 100644 index 0000000..b59b08f --- /dev/null +++ b/static/css/css2 @@ -0,0 +1,315 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7W0Q5nw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7W0Q5nw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7W0Q5nw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7W0Q5nw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7W0Q5n-wU.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v18/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7W0Q5nw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/static/css/styles.css b/static/css/styles.css new file mode 100644 index 0000000..8c42eb8 --- /dev/null +++ b/static/css/styles.css @@ -0,0 +1,991 @@ +body { + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + font-family: 'Inter', system-ui, -apple-system, sans-serif; + color: #212529; + min-height: 100vh; +} + +/* 组合相似的选择器,减少重复 */ +.card, .table, .alert { + border-radius: 12px; + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08); + overflow: hidden; +} + +.card { + border: none; + transition: all 0.3s ease; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); +} + +.card-header { + background: rgba(255, 255, 255, 0.9); + border-bottom: 1px solid rgba(0, 0, 0, 0.08); + font-weight: 600; + color: #111827; +} + +/* 优化按钮相关样式 */ +.btn { + transition: all 0.3s ease; + position: relative; + overflow: hidden; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.btn:hover { + transform: translateY(-2px); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.15); +} + +.btn:active { + transform: translateY(1px); +} + +/* 优化按钮波纹效果 */ +.btn::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 5px; + height: 5px; + background: rgba(255, 255, 255, 0.5); + opacity: 0; + border-radius: 100%; + transform: scale(1) translate(-50%, -50%); + transform-origin: 0 0; +} + +.btn:focus:not(:active)::after { + animation: ripple 1s ease-out; +} + +@keyframes ripple { + 0% { transform: scale(0); opacity: 0.6; } + 100% { transform: scale(25); opacity: 0; } +} + +/* 优化表格样式 */ +.table { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); + width: 100%; + margin-bottom: 1rem; +} + +.table td, .table th { + padding: 0.75rem 1rem; + vertical-align: middle; +} + +/* 简化表格悬停效果 */ +.table tbody tr:hover { + background-color: rgba(241, 245, 249, 0.7); + transform: scale(1.01); +} + +/* 合并加载遮罩样式 */ +.loading-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + display: none; + justify-content: center; + align-items: center; + z-index: 10000; + pointer-events: none; +} + +.loading-overlay.show { + display: flex; + pointer-events: auto; +} + +.spinner-container { + background-color: white; + padding: 20px; + border-radius: 10px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + text-align: center; +} + +.stat-number { + font-size: 2rem; + font-weight: 700; + background: linear-gradient(120deg, #4f46e5, #7c3aed); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + margin-bottom: 5px; +} + +.stat-label { + font-size: 0.9rem; + color: #1f2937; + font-weight: 500; +} + +.badge { + font-weight: 500; + padding: 0.35em 0.6em; + border-radius: 4px; +} + +.operation-column .btn { + margin: 0.15rem; + padding: 0.25rem 0.5rem; + border-radius: 4px; +} + +.email-column { + max-width: 250px; + word-break: break-all; +} + +.password-cell, .token-cell { + position: relative; +} + +.copy-btn { + margin-left: 0.25rem !important; +} + +.container { + max-width: 1400px; + padding: 1.5rem; +} + +.table th { + background-color: #f3f4f6; + font-weight: 600; + color: #111827; + border-top: none; +} + +.table tbody tr { + transition: all 0.2s ease; +} + +#fireworks-canvas { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 9999; + pointer-events: none; + display: none; +} + +#alert-container { + position: fixed; + top: 20px; + right: 20px; + z-index: 10000; + max-width: 400px; +} + +.alert { + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15); + border-radius: 10px; + border-left: 4px solid; +} + +.alert-success { + border-left-color: #10b981; +} + +.alert-danger { + border-left-color: #ef4444; +} + +.special-alert { + background: linear-gradient(135deg, #10b981, #059669); + color: white; + font-weight: 500; + transform-origin: center; +} + +.text-muted { + color: #6c757d !important; +} + +/* 调整卡片内部间距,使内容更紧凑 */ +.card-body { + padding: 1.25rem; +} + +/* 调整统计图表容器高度 */ +#usage-chart-container { + height: 200px; /* 从250px减小到200px */ +} + +/* 调整任务控制详情部分 */ +#task-details .card { + margin-bottom: 0.5rem; /* 减小底部边距 */ +} + +#task-details .card .card-body { + padding: 0.5rem; /* 减小内部填充 */ +} + +/* 调整操作按钮大小和间距 */ +.task-control-buttons .btn { + padding: 0.375rem 0.75rem; +} + +/* 调整任务状态信息间距 */ +.task-status-info { + margin-bottom: 0.75rem; +} + +/* 调整图表大小 */ +#usage-chart { + max-height: 160px; /* 从200px减小到160px */ +} + +/* 使用情况进度条样式更新 */ +.usage-progress-container { + display: flex; + flex-direction: column; + width: 100%; + margin-bottom: 5px; +} + +/* 使用情况列样式优化 */ +.usage-info { + min-width: 140px; +} + +.usage-numbers { + font-size: 0.8rem; + margin-bottom: 3px; + white-space: nowrap; +} + +.used-count { + font-weight: 500; + color: #333; +} + +.total-count { + color: #666; +} + +.remaining-count { + font-size: 0.75rem; + color: #28a745; + margin-left: 4px; +} + +/* 修改进度条背景为灰色 */ +.usage-progress { + height: 8px; + background-color: #e9ecef; + border-radius: 4px; + overflow: hidden; +} + +/* 修改进度条填充颜色为浅红色 */ +.usage-progress-bar { + height: 100%; + background: linear-gradient(90deg, #ff8a8a, #ffb3b3); + border-radius: 4px; + transition: width 0.5s ease; +} + +/* 调整表格列宽 */ +.usage-column { + min-width: 180px; +} + +.email-column { + max-width: 220px; + overflow: hidden; + text-overflow: ellipsis; +} + +/* 高亮显示当前行 */ +.table tbody tr.active { + background-color: rgba(79, 70, 229, 0.05); +} + +/* 调整使用量查询按钮 */ +.get-usage-btn { + white-space: nowrap; +} + +/* 保留操作列样式,但可以调整 */ +.operation-column { + min-width: 120px; /* 由于按钮组,宽度需要调整 */ + white-space: nowrap; +} + +/* 标题和面板间距优化 */ +h2, h3, h4, h5 { + margin-bottom: 1rem; + font-weight: 600; +} + +/* 添加鼠标悬停手形光标效果 */ +.copy-btn, +.toggle-password, +.toggle-token, +.toggle-username, +.btn, +.status-action, +.get-usage-btn, +.delete-account-btn { + cursor: pointer; +} + +/* 为复制和显示/隐藏图标添加悬停效果 */ +.copy-btn:hover, +.toggle-password:hover, +.toggle-token:hover, +.toggle-username:hover { + color: #4f46e5; + transform: scale(1.1); + transition: all 0.2s ease; +} + +/* 添加额度进度条样式 */ +.battery-progress { + display: flex; + width: 100%; + height: 20px; + /* background-color: #e9ecef; */ + border-radius: 5px; + overflow: hidden; + position: relative; + /* border: 1px solid #dee2e6; */ +} + +/* 电池内部格子线 */ +.battery-grid { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + pointer-events: none; +} + +/* 电池格子 */ +.battery-cell { + flex: 1; + height: 2px; + border-right: 1px solid rgba(0,0,0,0.1); +} + +.battery-cell:last-child { + border-right: none; +} + +/* 已使用的部分 - 浅红色 */ +.battery-used { + height: 100%; + background: linear-gradient(90deg, #ff8a8a, #ffb3b3); + transition: width 0.5s ease; +} + +/* 额度信息文本 */ +.usage-text { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 0.75rem; + font-weight: 600; + color: #495057; + text-shadow: 0 0 2px rgba(255,255,255,0.7); + white-space: nowrap; +} + +/* 使用量显示样式 */ +.usage-display { + width: 100%; +} + +.usage-text { + font-weight: 500; + font-size: 0.9rem; +} + +.progress { + height: 8px !important; + border-radius: 4px; + background-color: transparent !important; + overflow: hidden; +} + +/* 自定义颜色 */ +.bg-danger-soft { + background-color: #ffcccc !important; +} + +.bg-success-soft { + background-color: #d1ffd1 !important; +} + +/* 新的额度显示样式 - 参考图片精确复刻 */ +.usage-bar-container { + display: flex; + align-items: center; + width: 100%; + padding: 10px 0; +} + +.usage-bar { + flex-grow: 1; + height: 15px; + background-color: #e8f7e8; /* 浅绿背景 */ + border-radius: 10px; + margin-right: 15px; + position: relative; + overflow: hidden; +} + +.usage-bar-used { + position: absolute; + left: 0; + top: 0; + height: 100%; + background-color: #ffcccc; /* 浅红色 */ + border-radius: 10px 0 0 10px; +} + +.usage-percent { + font-size: 14px; + color: #666; + font-weight: normal; + white-space: nowrap; + min-width: 55px; + text-align: right; +} + +/* 使用情况列样式 */ +.usage-info { + white-space: nowrap; +} + +.usage-numbers { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 4px; + margin-bottom: 5px; +} + +.used-count { + font-weight: 600; + color: #0d6efd; +} + +.separator { + color: #6c757d; +} + +.total-count { + font-weight: 600; + color: #212529; +} + +.remaining-count { + color: #28a745; + font-size: 0.85em; + margin-left: 5px; +} + +/* 电池式进度指示器 - 修改颜色逻辑 */ +.battery-progress { + display: flex; + align-items: center; + gap: 8px; +} +.battery-bars { + display: flex; + gap: 2px; + align-items: center; + position: relative; + padding: 0 2px; +} + +.battery-bars::before { + content: ''; + position: absolute; + left: -3px; + height: 8px; + width: 3px; + background-color: #adb5bd; + border-radius: 2px 0 0 2px; +} + +.battery-bar { + width: 6px; + height: 14px; + background-color: rgba(40, 167, 69, 0.2); /* 默认未使用为浅绿色 */ + display: inline-block; + border-radius: 1px; + transition: background-color 0.3s ease; +} + +/* 根据进度点亮电池条 - 反转逻辑,显示已用部分 */ +.battery-progress[data-percent="0"] .battery-bar:nth-child(n) { + background-color: rgba(40, 167, 69, 0.2); /* 全未用 - 全部浅绿色 */ +} + +/* 已使用部分为浅红色 */ +.battery-progress[data-percent="10"] .battery-bar:nth-child(1), +.battery-progress[data-percent="20"] .battery-bar:nth-child(-n+2), +.battery-progress[data-percent="30"] .battery-bar:nth-child(-n+3), +.battery-progress[data-percent="40"] .battery-bar:nth-child(-n+4), +.battery-progress[data-percent="50"] .battery-bar:nth-child(-n+5), +.battery-progress[data-percent="60"] .battery-bar:nth-child(-n+6), +.battery-progress[data-percent="70"] .battery-bar:nth-child(-n+7), +.battery-progress[data-percent="80"] .battery-bar:nth-child(-n+8), +.battery-progress[data-percent="90"] .battery-bar:nth-child(-n+9), +.battery-progress[data-percent="100"] .battery-bar:nth-child(-n+10) { + background-color: rgba(220, 53, 69, 0.2); /* 浅红色表示已使用 */ +} + +/* 删除旧的根据进度值设置颜色的规则,因为现在使用统一的红绿对比 */ +.battery-percent { + font-size: 0.75rem; + color: #6c757d; + min-width: 40px; +} +#registration-status { + padding: 0.25rem 0.5rem; + border-radius: 0.25rem; +} + +/* 添加侧边栏菜单样式 */ +.app-layout { + display: flex; + min-height: 100vh; +} + +#sidebar { + width: 250px; + background: #f8f9fa; + border-right: 1px solid #dee2e6; + height: 100vh; + position: fixed; + left: 0; + top: 0; + z-index: 1000; + box-shadow: 0 0 10px rgba(0,0,0,0.05); +} + +.sidebar-header { + padding: 15px; + text-align: center; + border-bottom: 1px solid #dee2e6; +} + +.sidebar-header h4 { + margin: 0; + font-size: 1.2rem; + color: #343a40; +} + +.nav-menu { + list-style: none; + padding: 15px 0; + margin: 0; +} + +.nav-item { + margin: 5px 0; +} + +.nav-link { + display: flex; + align-items: center; + padding: 10px 15px; + color: #495057; + text-decoration: none; + border-left: 3px solid transparent; + transition: all 0.2s; +} + +.nav-link:hover, .nav-link.active { + background: #e9ecef; + color: #0d6efd; + border-left-color: #0d6efd; +} + +.nav-link i { + margin-right: 10px; + width: 20px; + text-align: center; +} + +#content { + flex: 1; + margin-left: 250px; + padding: 20px; +} + +.page-content { + display: none; +} + +.page-content.active { + display: block; +} + +/* 响应式样式 */ +@media (max-width: 768px) { + #sidebar { + width: 70px; + } + + #content { + margin-left: 70px; + } + + .sidebar-header h4, .nav-link span { + display: none; + } + + .nav-link { + justify-content: center; + padding: 15px; + } + + .nav-link i { + margin-right: 0; + } +} + +@media (max-width: 576px) { + #sidebar { + width: 0; + overflow: hidden; + } + + #content { + margin-left: 0; + } +} + +/* 侧边栏底部文案样式 */ +.sidebar-footer { + padding: 15px; + text-align: center; + position: absolute; + bottom: 0; + width: 100%; + border-top: 1px solid #dee2e6; + background-color: #f8f9fa; + font-size: 0.8rem; + color: #6c757d; +} + +/* 调整侧边栏内容区域,为底部文案留出空间 */ +.nav-menu { + padding-bottom: 60px; /* 确保内容不会被底部文案遮挡 */ +} + +/* 在响应式布局中隐藏/显示footer文本 */ +@media (max-width: 768px) { + .sidebar-footer { + padding: 10px 5px; + font-size: 0.7rem; + } + + .sidebar-footer span { + display: none; + } +} + +@media (min-width: 769px) { + .sidebar-footer span { + display: inline-block; + } +} + +/* 更新编辑配置按钮样式 - 占满一行 */ +#edit-config-btn { + display: block; + width: 100%; + padding: 0.75rem 1rem; + margin-bottom: 0.25rem; + font-weight: 500; + font-size: 1.05rem; + text-align: center; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); + transition: all 0.3s ease; + border: none; +} + +#edit-config-btn:hover { + transform: translateY(-2px); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2); +} + +#edit-config-btn:active { + transform: translateY(1px); + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); +} + +/* 调整徽章位置,使其更加合理 */ +#edit-config-btn .position-absolute { + top: -8px !important; + right: -8px !important; + left: auto !important; + transform: none !important; +} + +/* 卡片标题与按钮的对齐 */ +.card-header.bg-white.d-flex { + padding: 1rem 1.25rem; +} + +/* 配置按钮样式 */ +.config-actions button { + padding: 0.75rem 1rem; + font-weight: 500; + transition: all 0.3s ease; +} + +#cancel-config-btn { + background-color: #6c757d; + border: none; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.12); +} + +#cancel-config-btn:hover { + background-color: #5a6268; + transform: translateY(-2px); + box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15); +} + +#save-config-btn { + background-color: #198754; + border: none; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.12); +} + +#save-config-btn:hover { + background-color: #157347; + transform: translateY(-2px); + box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15); +} + +/* 分页控件样式优化 */ +.pagination { + border-radius: 30px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08); + background-color: #fff; + overflow: hidden; +} + +.pagination .page-item:first-child .page-link, +.pagination .page-item:last-child .page-link { + border-radius: 0; +} + +.pagination .page-item .page-link { + border: none; + font-weight: 500; + color: #6c757d; + min-width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + padding: 0; + margin: 0; +} + +.pagination .page-item.active .page-link { + background-color: #4285f4; + color: white; + font-weight: 600; + box-shadow: 0 2px 5px rgba(66, 133, 244, 0.3); +} + +.pagination .page-item .page-link:hover:not(.disabled) { + background-color: #f5f5f5; + color: #4285f4; + z-index: 1; +} + +.pagination .page-item.disabled .page-link { + color: #ccc; + background-color: #f8f9fa; +} + +/* 分页容器样式 */ +.pagination-container { + background-color: #f8f9fa; + border-radius: 8px; + padding: 12px 16px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); +} + +.per-page-selector .form-select { + border-radius: 20px; + font-size: 0.9rem; + padding: 0.375rem 2rem 0.375rem 1rem; + border: 1px solid #dee2e6; + background-color: white; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04); +} + +.pagination-info { + font-size: 0.9rem; + color: #6c757d; +} + +/* 添加表头排序图标样式 */ +.sortable { + cursor: pointer; + position: relative; +} + +.sortable:after { + content: '\f0dc'; + font-family: 'Font Awesome 5 Free'; + font-weight: 900; + margin-left: 5px; + color: #ccc; + font-size: 0.8em; +} + +.sortable.asc:after { + content: '\f0de'; + color: #0d6efd; +} + +.sortable.desc:after { + content: '\f0dd'; + color: #0d6efd; +} + +/* 代理配置样式 */ +#proxy-settings { + background-color: #f8f9fa; + padding: 15px; + border-radius: 6px; + border: 1px solid #e9ecef; + margin-top: 10px; + transition: all 0.3s ease; +} + +.form-check-input:checked + .form-check-label { + font-weight: 600; + color: #0d6efd; +} + +/* 代理类型下拉框样式 */ +#proxy-type { + border-color: #ced4da; + border-radius: 4px; + padding: 0.375rem 0.75rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +#proxy-type:focus { + border-color: #86b7fe; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +/* 系统维护按钮样式 - 更新蓝色按钮样式 */ +.config-section .btn-danger, +.config-section .btn-primary { + transition: all 0.3s ease; + font-weight: 500; +} + +.config-section .btn-primary { + background-color: #0b5ed7; + border-color: #0a58ca; +} + +.config-section .btn-danger:hover { + background-color: #dc2626; + box-shadow: 0 4px 8px rgba(220, 38, 38, 0.3); + transform: translateY(-2px); +} + +.config-section .btn-primary:hover { + background-color: #0a4fbf; + box-shadow: 0 4px 8px rgba(11, 94, 215, 0.3); + transform: translateY(-2px); +} + +/* 系统维护卡片强调 */ +.config-section.card { + border-color: #e2e8f0; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); +} + +/* 更新所有余量按钮样式 */ +#update-all-usage { + margin-right: 10px; +} + +#update-all-usage .fa-sync-alt { + transition: transform 0.3s ease; +} + +#update-all-usage:active .fa-sync-alt { + transform: rotate(180deg); +} + +/* 按钮加载状态 */ +.btn-loading { + position: relative; + pointer-events: none; + color: transparent !important; +} + +.btn-loading:after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 1em; + height: 1em; + margin-top: -0.5em; + margin-left: -0.5em; + border-radius: 50%; + border: 2px solid currentColor; + border-right-color: transparent; + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +/* 更新余量按钮样式 */ +.btn-purple { + color: #fff; + background-color: #6f42c1; + border-color: #6610f2; +} + +.btn-purple:hover { + color: #fff; + background-color: #5a32a3; + border-color: #5a32a3; +} + +.btn-purple:focus { + box-shadow: 0 0 0 0.25rem rgba(111, 66, 193, 0.25); +} + +.btn-purple:active { + background-color: #4c2888; + border-color: #4c2888; +} diff --git a/static/js/app.js b/static/js/app.js new file mode 100644 index 0000000..54b7bdf --- /dev/null +++ b/static/js/app.js @@ -0,0 +1,1903 @@ +// 全局变量 +const REFRESH_INTERVAL = 60000; // 10秒 +let currentPage = 1; +let totalPages = 1; +let itemsPerPage = 10; +let currentSortField = 'created_at'; +let currentSortOrder = 'desc'; + +// 页面加载完成后执行 +$(document).ready(function() { + // 初始化应用 + initializeApplication(); +}); + +// 应用初始化函数 - 提高代码组织性 +function initializeApplication() { + // 绑定分页事件必须在DOM准备好后立即执行 + bindPaginationEvents(); + + // 绑定排序事件 + bindSortEvents(); + + // 确保不使用ID排序 + if (currentSortField === 'id') { + currentSortField = 'created_at'; + } + + // 加载配置 + loadConfig(); + + // 初始加载数据 + loadAccounts(1, itemsPerPage); + + // 设置定时刷新 + setupTaskRefresh(); + + // 绑定所有事件处理函数 + bindEventHandlers(); +} + +// 事件处理绑定函数 - 将所有事件绑定集中在一起 +function bindEventHandlers() { + // 按钮事件监听 + $("#refresh-btn").click(function() { + showLoading(); + loadAccounts(1, itemsPerPage, $("#search-input").val()); + }); + + $("#start-registration").click(function() { + startTaskManually(); + }); + + $("#stop-registration").click(function() { + stopTaskManually(); + }); + + $("#search-btn").click(function() { + filterAccounts(); + }); + + $("#search-input").keypress(function(e) { + if (e.which === 13) { + filterAccounts(); + } + }); + + // 可以添加更多事件绑定... + + // 在bindEventHandlers函数中添加配置相关事件 + $("#edit-config-btn").click(function(e) { + e.preventDefault(); // 明确阻止任何默认行为 + console.log("点击编辑配置按钮"); + enableConfigForm(true); + }); + + $("#cancel-config-btn").click(function(e) { + e.preventDefault(); + console.log("取消编辑配置"); + enableConfigForm(false); + loadConfig(); // 重新加载原始配置 + }); + + $("#config-form").submit(function(e) { + console.log("click config-form submit"); + e.preventDefault(); + saveConfig(); + }); + + // 代理设置切换事件 + $("#use-proxy").change(function() { + toggleProxySettings(); + }); + + // 重启服务按钮事件 + $("#restart-service-btn").click(function() { + showConfirmDialog( + '重启服务', + '确定要重启服务吗?重启过程可能需要几秒钟,期间服务将不可用。', + function() { + restartService(); + } + ); + }); + + // 重置机器ID按钮事件 + $("#reset-machine-btn").click(function() { + showConfirmDialog( + '重置机器ID', + '确定要重置机器ID吗?这将解除当前设备的绑定限制,但可能需要重新登录所有账号。', + function() { + resetMachineId(); + } + ); + }); + + // 导出账号按钮点击事件 + $("#export-accounts-btn").click(function() { + exportAccounts(); + }); + + // 导入账号按钮点击事件 + $("#import-accounts-btn").click(function() { + $("#import-file-input").click(); + }); + + // 导入文件选择事件 + $("#import-file-input").change(function(e) { + if (e.target.files.length > 0) { + const file = e.target.files[0]; + + // 读取文件预览内容 + const reader = new FileReader(); + reader.onload = function(event) { + try { + const data = JSON.parse(event.target.result); + + if (Array.isArray(data)) { + // 显示导入确认对话框 + $("#import-count").text(data.length); + const importModal = new bootstrap.Modal(document.getElementById('import-confirm-modal')); + importModal.show(); + + // 存储文件引用,用于后续导入 + window.fileToImport = file; + } else { + showAlert('danger', '无效的数据格式:必须是账号对象的数组'); + } + } catch (err) { + showAlert('danger', '解析JSON文件失败:' + err.message); + } + + // 重置文件输入,允许再次选择同一文件 + $("#import-file-input").val(''); + }; + + reader.readAsText(file); + } + }); + + // 确认导入按钮点击事件 + $("#confirm-import-btn").click(function() { + if (window.fileToImport) { + importAccounts(window.fileToImport); + bootstrap.Modal.getInstance(document.getElementById('import-confirm-modal')).hide(); + } + }); + + // 在适当的位置添加更新所有余量按钮(例如在账号列表上方的工具栏) + function renderAccountControls() { + // ... existing code ... + + // 添加更新所有余量按钮 + const updateAllButton = ` + + `; + + // 将按钮添加到工具栏中 + $("#account-controls").append(updateAllButton); + + // ... existing code ... + } + + // 在文档加载完成或初始化函数中调用 + renderAccountControls(); + + // 为更新所有余量按钮添加点击事件 + $(document).on('click', '#update-all-usage', function() { + updateAllAccountsUsage(); + }); + + // 添加更新余量按钮到导出账号按钮旁边 + const updateBalanceButton = ` + + `; + + // 将按钮添加到导出账号按钮后面 + $("#exportAccountsBtn").after(updateBalanceButton); + + // 为更新余量按钮添加点击事件 + $(document).on('click', '#update-all-usage', function() { + // 添加按钮加载状态 + const $btn = $(this); + const originalText = $btn.html(); + $btn.html(' 更新中...'); + $btn.prop('disabled', true); + + updateAllAccountsUsage().finally(() => { + // 恢复按钮状态 + $btn.html(originalText); + $btn.prop('disabled', false); + }); + }); +} + +// 全局变量 +let accounts = []; +let filteredAccounts = []; +let refreshTimer; + +// 显示加载遮罩 +function showLoading(message = '加载中,请稍候...') { + const loadingOverlay = document.getElementById('loading-overlay'); + loadingOverlay.classList.add('show'); + $("#loading-overlay p").text(message); +} + +// 隐藏加载遮罩 +function hideLoading() { + const loadingOverlay = document.getElementById('loading-overlay'); + loadingOverlay.classList.remove('show'); +} + +// 加载账号数据 +function loadAccounts(page = 1, perPage = itemsPerPage, search = '', sortField = currentSortField, sortOrder = currentSortOrder) { + showLoading(); + + // 构建URL查询参数 + let params = new URLSearchParams({ + page: page, + per_page: perPage, + sort_by: sortField, + order: sortOrder + }); + + if (search) { + params.append('search', search); + } + + const url = `/accounts?${params.toString()}`; + + $.ajax({ + url: url, + method: 'GET', + success: function(response) { + if (response.success) { + accounts = response.data; + + // 更新分页和排序信息 + currentPage = response.pagination.page; + totalPages = response.pagination.total_pages; + itemsPerPage = response.pagination.per_page; + currentSortField = response.sort.field; + currentSortOrder = response.sort.order; + + // 新增:更新账号统计信息 + const totalAccounts = response.pagination.total_count || 0; + const maxAccounts = parseInt($("#max-accounts").text()) || 10; + const remainingSlots = Math.max(0, maxAccounts - totalAccounts); + + $("#current-count").text(totalAccounts); + $("#remaining-slots").text(`剩余: ${remainingSlots}`); + + // 计算使用百分比 + const usagePercent = maxAccounts > 0 ? Math.round((totalAccounts / maxAccounts) * 100) : 0; + + // 更新进度条 + $(".battery-progress").attr("data-percent", usagePercent); + $(".battery-percent").text(`${usagePercent}%`); + + // 更新排序控件 + $("#sort-field").val(currentSortField); + $("#sort-order").val(currentSortOrder); + + // 添加淡入效果 + $("#accounts-table").css("opacity", 0); + + // 更新UI + updateAccountsTable(accounts); + updatePagination(currentPage, totalPages); + $("#total-accounts").text(response.pagination.total_count); + + // 更新每页记录数下拉框 + $("#per-page").val(itemsPerPage); + + // 淡入表格 + $("#accounts-table").animate({opacity: 1}, 300); + + hideLoading(); + } else { + showAlert('danger', '加载账号失败: ' + response.message); + hideLoading(); + } + }, + error: function(xhr) { + hideLoading(); + showAlert('加载账号失败: ' + (xhr.responseJSON?.detail || xhr.statusText)); + } + }); +} + +// 更新分页控件 +function updatePagination(currentPage, totalPages) { + // 清除现有页码 + $(".pagination .page-number").remove(); + + // 决定显示哪些页码 + let pages = []; + + // 限制显示的页码数量,使UI更加紧凑 + if (totalPages <= 5) { + // 总页数少于5,显示所有页码 + for (let i = 1; i <= totalPages; i++) { + pages.push(i); + } + } else { + // 总页数大于5,使用更紧凑的布局 + + // 总是显示第一页 + pages.push(1); + + // 当前页在前3页 + if (currentPage <= 3) { + pages.push(2, 3, 4, '...', totalPages); + } + // 当前页在后3页 + else if (currentPage >= totalPages - 2) { + pages.push('...', totalPages-3, totalPages-2, totalPages-1, totalPages); + } + // 当前页在中间 + else { + pages.push('...', currentPage-1, currentPage, currentPage+1, '...', totalPages); + } + } + + // 创建页码元素 - 简化HTML生成 + let pageElements = ''; + + pages.forEach(page => { + if (page === '...') { + pageElements += `
  • `; + } else { + const isActive = page === currentPage ? 'active' : ''; + pageElements += `
  • ${page}
  • `; + } + }); + + // 使用insertBefore而不是after,确保顺序正确 + $(pageElements).insertBefore("#next-page"); + + // 更新上一页/下一页按钮状态 + $("#prev-page").toggleClass('disabled', currentPage === 1); + $("#next-page").toggleClass('disabled', currentPage === totalPages); + + // 更新分页信息文本 + $("#current-page").text(currentPage); + $("#total-pages").text(totalPages); +} + +// 修复分页事件绑定 - 确保在DOM加载完成后绑定 +function bindPaginationEvents() { + // 上一页按钮 - 使用事件委托 + $(document).on('click', "#prev-page:not(.disabled) a", function(e) { + e.preventDefault(); + if (currentPage > 1) { + loadAccounts(currentPage - 1, itemsPerPage, $("#search-input").val()); + } + }); + + // 下一页按钮 - 使用事件委托 + $(document).on('click', "#next-page:not(.disabled) a", function(e) { + e.preventDefault(); + if (currentPage < totalPages) { + loadAccounts(currentPage + 1, itemsPerPage, $("#search-input").val()); + } + }); + + // 页码点击 - 使用事件委托确保动态生成的元素也能响应 + $(document).on('click', '.page-number:not(.disabled) .page-link', function(e) { + e.preventDefault(); + const page = parseInt($(this).attr('data-page')); + if (!isNaN(page)) { + loadAccounts(page, itemsPerPage, $("#search-input").val()); + } + }); + + // 每页显示记录数变更 + $(document).on('change', "#per-page", function() { + itemsPerPage = parseInt($(this).val()); + loadAccounts(1, itemsPerPage, $("#search-input").val()); + }); +} + +// 修改搜索函数 +function filterAccounts() { + const searchTerm = $("#search-input").val().trim(); + loadAccounts(1, itemsPerPage, searchTerm); +} + +// 更新账号表格 +function updateAccountsTable(accounts) { + const accountsBody = $('#accounts-tbody'); + accountsBody.empty(); + + if (accounts.length === 0) { + // 添加空状态提示 + accountsBody.html(` + + +
    + +

    暂无账号数据

    +
    + + + `); + return; + } + + // 渲染每行数据 + accounts.forEach((account, index) => { + // 完整的行模板,包含所有单元格内容 + const row = ` + + + ${account.email} + + ${account.status === 'active' ? '正常' : account.status === 'disabled' ? '停用' : '删除'} + + + + ${maskPassword(account.password)} + + + + ${renderTokenColumn(account.token, account.id, account.email)} + ${renderUsageProgress(account.usage_limit)} + + ${account.created_at || '未知'} + + +
    + +
    + + +
    + ${account.status !== 'active' ? + `` : ''} + + ${account.status !== 'disabled' ? + `` : ''} + + ${account.status !== 'deleted' ? + `` : ''} + + +
    + + + `; + accountsBody.append(row); + }); + + // 绑定事件 + bindTableEvents(); + + // 更新表头排序指示 + $('.sortable').removeClass('asc desc'); + $(`.sortable[data-field="${currentSortField}"]`).addClass(currentSortOrder); +} + +// 渲染账号表格 +function renderAccountsTable() { + const accountsBody = $('#accounts-tbody'); + accountsBody.empty(); + + if (filteredAccounts.length === 0) { + // 添加空状态提示 + accountsBody.html(` + + +
    + +

    暂无账号数据

    +
    + + + `); + return; + } + + // 计算当前页的数据 + const startIndex = (currentPage - 1) * itemsPerPage; + const endIndex = Math.min(startIndex + itemsPerPage, filteredAccounts.length); + const currentPageData = filteredAccounts.slice(startIndex, endIndex); + + console.log(`当前页数据: ${currentPageData.length}条 (第${currentPage}页)`); + + // 渲染每行数据 + currentPageData.forEach((account, index) => { + // 完整的行模板,包含所有单元格内容 + const row = ` + + ${startIndex + index + 1} + + ${account.email} + + ${account.status === 'active' ? '正常' : account.status === 'disabled' ? '停用' : '删除'} + + + + ${maskPassword(account.password)} + + + + ${renderTokenColumn(account.token, account.id)} + ${renderUsageProgress(account.usage_limit)} + + ${account.created_at || '未知'} + + +
    + +
    + + +
    + ${account.status !== 'active' ? + `` : ''} + + ${account.status !== 'disabled' ? + `` : ''} + + ${account.status !== 'deleted' ? + `` : ''} + + +
    + + + `; + accountsBody.append(row); + }); + + // 绑定事件 + bindTableEvents(); + renderPagination(); +} + +// 渲染分页 +function renderPagination() { + const totalPages = Math.ceil(filteredAccounts.length / itemsPerPage); + const pagination = $("#pagination"); + pagination.empty(); + + if (totalPages <= 1) { + return; + } + + const paginationNav = $(''); + const paginationUl = $('
      '); + + // 上一页按钮 + paginationUl.append(` +
    • + + + +
    • + `); + + // 页码按钮 + for (let i = 1; i <= totalPages; i++) { + paginationUl.append(` +
    • + ${i} +
    • · + `); + } + + // 下一页按钮 + paginationUl.append(` +
    • + + + +
    • + `); + + paginationNav.append(paginationUl); + pagination.append(paginationNav); +} + +// 更改页码 +function changePage(page) { + currentPage = page; + renderAccountsTable(); +} + +// 获取账号用量详情并更新数据库 +function getAccountUsage(email) { + showLoading(); + fetch(`/account/${encodeURIComponent(email)}/usage`) + .then(res => res.json()) + .then(data => { + hideLoading(); + if (data.success) { + // 创建并显示用量信息模态框 + const modal = $(` + + `); + + $('body').append(modal); + const modalInstance = new bootstrap.Modal(modal[0]); + modalInstance.show(); + + // 模态框关闭时移除DOM + modal[0].addEventListener('hidden.bs.modal', function() { + modal.remove(); + }); + } + }) + .catch(error => { + console.error('获取账号用量失败:', error); + showAlert('获取账号用量失败', 'danger'); + hideLoading(); + }); +} + +// 更新账号用量到数据库 +function updateAccountUsageLimit(email, usageLimit) { + fetch(`/account/${encodeURIComponent(email)}/update-usage`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ usage_limit: usageLimit }) + }) + .then(res => res.json()) + .then(data => { + if (data.success) { + console.log(`账号 ${email} 用量数据已更新到数据库`); + } else { + console.error(`更新账号 ${email} 用量数据失败:`, data.message); + } + }) + .catch(error => { + console.error(`更新账号 ${email} 用量数据时发生错误:`, error); + }); +} + +// 修复任务状态更新问题 +function startTaskManually() { + showLoading(); + fetch('/registration/start', { + method: 'GET' + }) + .then(res => res.json()) + .then(data => { + hideLoading(); + if (data.success) { + showAlert('定时任务已成功启动', 'success'); + checkTaskStatus(); + } else { + showAlert(`启动任务失败: ${data.message || '未知错误'}`, 'danger'); + } + }) + .catch(error => { + console.error('启动任务时发生错误:', error); + hideLoading(); + showAlert('启动任务失败,请稍后重试', 'danger'); + }); +} + +// 同样添加到停止任务函数 +function stopTaskManually() { + showLoading(); + fetch('/registration/stop', { + method: 'GET' + }) + .then(res => res.json()) + .then(data => { + hideLoading(); + if (data.success) { + showAlert('定时任务已成功停止', 'success'); + + // 立即更新任务状态 - 添加这段代码 + fetch('/registration/status') + .then(res => res.json()) + .then(statusData => { + updateTaskStatusUI(statusData); + }); + } else { + showAlert(`停止任务失败: ${data.message || '未知错误'}`, 'danger'); + } + }) + .catch(error => { + console.error('停止任务时发生错误:', error); + hideLoading(); + showAlert('停止任务失败,请稍后重试', 'danger'); + }); +} + +// 复制到剪贴板 +function copyToClipboard(text) { + navigator.clipboard.writeText(text).then(() => { + showAlert('复制成功,Token已复制到剪贴板', 'success'); + }).catch(err => { + console.error('复制失败:', err); + showAlert('复制失败', 'danger'); + }); +} + +// 显示通知 +function showAlert(message, type, isSpecial = false) { + const alertId = 'alert-' + Date.now(); + const alertClass = isSpecial ? + `alert-${type} special-alert animate__animated animate__bounceIn` : + `alert-${type} animate__animated animate__fadeInRight`; + + const alert = $(` + + `); + + $("#alert-container").append(alert); + + // 5秒后自动消失 + setTimeout(() => { + $(`#${alertId}`).alert('close'); + }, 5000); +} + +// 日期时间格式化 +function formatDateTime(dateTimeString) { + if (!dateTimeString) return '-'; + + try { + const date = new Date(dateTimeString); + if (isNaN(date.getTime())) return dateTimeString; + + const year = date.getFullYear(); + const month = (date.getMonth() + 1).toString().padStart(2, '0'); + const day = date.getDate().toString().padStart(2, '0'); + const hours = date.getHours().toString().padStart(2, '0'); + const minutes = date.getMinutes().toString().padStart(2, '0'); + const seconds = date.getSeconds().toString().padStart(2, '0'); + + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + } catch (error) { + return dateTimeString; + } +} + +// 修改掩码函数,增加对用户名的特殊处理 +function maskText(text, showChars = 6, isUsername = false) { + if (!text) return ''; + + // 用户名特殊处理 - 只显示前1/3 + if (isUsername) { + const showLength = Math.ceil(text.length / 3); + if (text.length <= showLength) return text; + return `${text.substring(0, showLength)}...`; + } + + // 其他文本使用标准处理 + if (text.length <= showChars) return text; + return `${text.substring(0, showChars)}...`; +} + +// 隐藏密码 +function maskPassword(password) { + if (!password) return ''; + return '•'.repeat(password.length); +} + +// 新增函数 - 更新所有账号的使用量 +function updateAllAccountsUsage() { + showLoading('正在更新所有账户余量...'); + + return fetch('/update_all_usage', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }) + .then(response => response.json()) + .then(data => { + hideLoading(); + if (data.success) { + showAlert('所有账户余量更新成功', 'success'); + // 刷新整个页面而不仅仅是账户列表 + location.reload(); + } else { + showAlert(`更新失败: ${data.message || '未知错误'}`, 'danger'); + } + }) + .catch(error => { + console.error('更新所有账户余量时发生错误:', error); + hideLoading(); + showAlert('更新失败,请稍后重试', 'danger'); + }); +} + +// 页面加载动画 +document.addEventListener('DOMContentLoaded', function() { + // 修改动画类添加代码,删除对已删除元素的引用 + const elements = [ + {selector: '.card', animation: 'animate__fadeIn', delay: 0.2} + ]; + + elements.forEach(item => { + const elems = document.querySelectorAll(item.selector); + elems.forEach((el, index) => { + el.classList.add('animate__animated', item.animation); + + if (item.delay) { + const delay = item.stagger ? item.delay * (index + 1) : item.delay; + el.style.animationDelay = `${delay}s`; + } + }); + }); +}); + +// 烟花动画实现 +const Fireworks = { + canvas: null, + ctx: null, + particles: [], + + init: function() { + this.canvas = document.getElementById('fireworks-canvas'); + this.ctx = this.canvas.getContext('2d'); + this.resizeCanvas(); + window.addEventListener('resize', () => this.resizeCanvas()); + }, + + resizeCanvas: function() { + this.canvas.width = window.innerWidth; + this.canvas.height = window.innerHeight; + }, + + start: function() { + this.canvas.style.display = 'block'; + this.particles = []; + + // 创建5次烟花,间隔300ms + for (let i = 0; i < 5; i++) { + setTimeout(() => { + const x = Math.random() * this.canvas.width; + const y = Math.random() * this.canvas.height * 0.6; + this.createParticles(x, y); + }, i * 300); + } + + this.animate(); + + // 5秒后停止动画 + setTimeout(() => { + this.canvas.style.display = 'none'; + }, 5000); + }, + + createParticles: function(x, y) { + const colors = ['#ff595e', '#ffca3a', '#8ac926', '#1982c4', '#6a4c93']; + + for (let i = 0; i < 80; i++) { + const particle = { + x: x, + y: y, + size: Math.random() * 4 + 1, + color: colors[Math.floor(Math.random() * colors.length)], + velocity: { + x: (Math.random() - 0.5) * 8, + y: (Math.random() - 0.5) * 8 + }, + alpha: 1, + decay: Math.random() * 0.02 + 0.01 + }; + + this.particles.push(particle); + } + }, + + animate: function() { + if (this.particles.length === 0) return; + + requestAnimationFrame(() => this.animate()); + + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + + for (let i = 0; i < this.particles.length; i++) { + const p = this.particles[i]; + + // 添加重力 + p.velocity.y += 0.05; + + // 更新位置 + p.x += p.velocity.x; + p.y += p.velocity.y; + + // 减少透明度 + p.alpha -= p.decay; + + // 绘制粒子 + this.ctx.save(); + this.ctx.globalAlpha = p.alpha; + this.ctx.fillStyle = p.color; + this.ctx.beginPath(); + this.ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); + this.ctx.fill(); + this.ctx.restore(); + + // 移除消失的粒子 + if (p.alpha <= 0) { + this.particles.splice(i, 1); + i--; + } + } + } +}; + +// 初始化烟花 +Fireworks.init(); + +// 绑定表格交互事件 +function bindTableEvents() { + // 显示/隐藏用户名 + $('.toggle-username').off('click').on('click', function() { + const username = $(this).data('username'); + const usernameText = $(this).prev('.username-text'); + + if (usernameText.text() === username) { + usernameText.text(maskText(username, 6, true)); + } else { + usernameText.text(username); + } + }); + + // 显示/隐藏密码 + $('.toggle-password').off('click').on('click', function() { + const password = $(this).data('password'); + const passwordText = $(this).prev('.password-text'); + + if (passwordText.text() === password) { + passwordText.text(maskPassword(password)); + } else { + passwordText.text(password); + } + }); + + // 显示/隐藏Token + $('.toggle-token').off('click').on('click', function() { + const token = $(this).data('token'); + const tokenText = $(this).prev('.token-text'); + + if (tokenText.text() === token) { + tokenText.text(maskText(token)); + } else { + tokenText.text(token); + } + }); + + // 复制按钮 + $('.copy-btn').off('click').on('click', function() { + const textToCopy = $('#tokenFullText').val(); + copyToClipboard(textToCopy); + }); + + // 获取用量按钮 + $('.get-usage-btn').off('click').on('click', function() { + const email = $(this).data('email'); + getAccountUsage(email); + }); + + // 查看使用记录按钮 + $('.view-records-btn').off('click').on('click', function() { + const email = $(this).data('email'); + const id = $(this).data('id'); + getAccountUsageRecords(email, id); + }); + + // 删除按钮 + $('.delete-account-btn').off('click').on('click', function() { + const email = $(this).data('email'); + const id = $(this).data('id'); + $('#deleteEmailConfirm').text(email); + $('#deleteIdConfirm').text(id || '无'); + + // 重置并重新绑定确认删除按钮事件 + $('#confirmDeleteBtn').off('click').on('click', function() { + deleteAccount(email, id, true); + }); + + const deleteModal = new bootstrap.Modal(document.getElementById('deleteConfirmModal')); + deleteModal.show(); + }); + + // 状态操作按钮 + $('.status-action').off('click').on('click', function(e) { + e.preventDefault(); + const email = $(this).data('email'); + const id = $(this).data('id'); + const status = $(this).data('status'); + updateAccountStatus(email, id, status); + }); + + // 查看Token按钮 + $('.view-token-btn').off('click').on('click', function() { + const token = $(this).data('token'); + const accountId = $(this).data('account-id'); + $('#tokenFullText').val(token); + $('#useTokenBtn').data('account-id', accountId); + new bootstrap.Modal(document.getElementById('tokenViewModal')).show(); + }); + + // 使用Token按钮 + $('#useTokenBtn').off('click').on('click', function() { + const accountId = $(this).data('account-id'); + const resetMachineId = $('#resetMachineIdCheck').prop('checked'); + + // 显示加载中提示 + showLoading('正在更新Token...'); + + // 发送请求到后端 + $.ajax({ + url: `/account/use-token/${accountId}?reset_machine_id=${resetMachineId}`, + type: 'POST', + success: function(response) { + hideLoading(); + if (response.success) { + showSuccess(response.message); + } else { + showError(response.message); + } + }, + error: function() { + hideLoading(); + showError('更新Token失败,请检查网络连接'); + } + }); + }); +} + +// 更新删除确认按钮事件处理 +$('#confirmDeleteBtn').click(function() { + const email = $(this).data('email'); + const id = $(this).data('id'); + deleteAccount(email, id, true); +}); + +// 修改updateAccountStatus函数,确保正确发送请求体 +function updateAccountStatus(email, id, status) { + showLoading(); + // 优先使用ID API,如果ID存在的话 + const apiUrl = id ? + `/account/id/${id}/status` : + `/account/${encodeURIComponent(email)}/status`; + + fetch(apiUrl, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ status: status }) // 确保这里的字段名是status + }) + .then(res => res.json()) + .then(data => { + hideLoading(); + if (data.success) { + let statusText = ''; + if (status === 'active') statusText = '正常'; + else if (status === 'disabled') statusText = '停用'; + else if (status === 'deleted') statusText = '删除'; + + showAlert(`账号${id ? '(ID:'+id+')' : ''} ${email} 已成功设置为${statusText}状态`, 'success'); + loadAccounts(1, itemsPerPage); + } else { + showAlert(`更新账号状态失败: ${data.message || '未知错误'}`, 'danger'); + } + }) + .catch(error => { + console.error('更新账号状态时发生错误:', error); + hideLoading(); + showAlert('更新账号状态失败,请稍后重试', 'danger'); + }); +} + +// 修改deleteAccount函数,支持通过ID删除 +function deleteAccount(email, id, hardDelete = true) { + showLoading(); + // 优先使用ID API,如果ID存在的话 + const apiUrl = id ? + `/account/id/${id}${hardDelete ? '?hard_delete=true' : ''}` : + `/account/${encodeURIComponent(email)}${hardDelete ? '?hard_delete=true' : ''}`; + + fetch(apiUrl, { + method: 'DELETE' + }) + .then(res => res.json()) + .then(data => { + hideLoading(); + if (data.success) { + showAlert(`账号${id ? '(ID:'+id+')' : ''} ${email} 已成功删除`, 'success'); + // 关闭模态框 + $('#deleteConfirmModal').modal('hide'); + // 重新加载账号列表 + loadAccounts(1, itemsPerPage); + } else { + showAlert(`删除账号失败: ${data.message || '未知错误'}`, 'danger'); + } + }) + .catch(error => { + console.error('删除账号时发生错误:', error); + hideLoading(); + showAlert('删除账号失败,请稍后重试', 'danger'); + }); +} + + +// 完全重构额度显示函数,精确匹配参考代码 +function renderUsageProgress(usageLimit) { + // 计算使用进度 + const premiumUsed = 150 - usageLimit; + const premiumTotal = 150; + const premiumRemaining = premiumTotal - premiumUsed; + const premiumPercent = Math.round((premiumUsed / premiumTotal) * 100); + + return ` + +
      + ${premiumUsed} + / + ${premiumTotal} + (剩余: ${premiumRemaining}) +
      +
      +
      + + + + + + + + + + +
      + ${premiumPercent}% +
      + + `; +} + +// 修改Token列的渲染方式 +function renderTokenColumn(token, accountId, email) { + return ` + + + + + `; +} + +// 加载配置函数 +function loadConfig() { + showLoading(); + $.ajax({ + url: '/config', + method: 'GET', + success: function(response) { + if (response.success) { + const config = response.data; + + // 现有字段设置... + + // 设置代理配置 + $("#use-proxy").prop("checked", config.USE_PROXY === "True"); + $("#proxy-type").val(config.PROXY_TYPE || "http"); + $("#proxy-host").val(config.PROXY_HOST || ""); + $("#proxy-port").val(config.PROXY_PORT || ""); + $("#proxy-timeout").val(config.PROXY_TIMEOUT || "10"); + $("#proxy-username").val(config.PROXY_USERNAME || ""); + $("#proxy-password").val(config.PROXY_PASSWORD || ""); + + // 触发动态UA的change事件 + $("#dynamic-useragent").trigger('change'); + // 根据是否启用代理来显示/隐藏代理设置 + toggleProxySettings(); + + $("#browser-useragent").val(config.BROWSER_USER_AGENT); + $("#accounts-limit").val(config.MAX_ACCOUNTS); + $("#captcha-method").val(config.EMAIL_CODE_TYPE || "API"); + $("#email-domains").val(config.EMAIL_DOMAINS); + $("#email-username").val(config.EMAIL_USERNAME); + $("#email-pin").val(config.EMAIL_PIN); + $("#browser-path").val(config.BROWSER_PATH || ''); + $("#cursor-path").val(config.CURSOR_PATH || ''); + + if (config.EMAIL_DOMAIN) { + // 获取第一个域名作为示例 + const firstDomain = config.EMAIL_DOMAIN; + // 更新输入框提示 + $('#email-username').attr('placeholder', `仅输入用户名部分,例如:ddcat28(完整地址将是 ddcat28@${firstDomain})`); + // 添加域名显示标签 + if (!$('#email-domain-suffix').length) { + $('#email-username').after(`@${firstDomain}`); + // 将输入框和域名标签包装在input-group中 + $('#email-username, #email-domain-suffix').wrapAll('
      '); + } else { + $('#email-domain-suffix').text(`@${firstDomain}`); + } + } + + $("#email-type").val(config.EMAIL_TYPE); + $("#email-proxy-enabled").prop('checked', config.EMAIL_PROXY_ENABLED || false); + if (config.EMAIL_PROXY_ENABLED) { + $("#email-proxy-address").val(config.EMAIL_PROXY_ADDRESS); + $("#email-api").val(config.EMAIL_API); + } + if (config.EMAIL_TYPE == "tempemail") { + $("#tempemail-fields").show(); + $("#zmail-fields").hide(); + } else if (config.EMAIL_TYPE == "zmail") { + $("#tempemail-fields").hide(); + $("#zmail-fields").show(); + } + + hideLoading(); + + } else { + showAlert('danger', '加载配置失败: ' + response.message); + hideLoading(); + } + }, + error: function(xhr) { + hideLoading(); + showAlert('danger', '加载配置失败: ' + xhr.statusText); + } + }); +} + +// 添加代理设置的显示/隐藏控制 +function toggleProxySettings() { + if ($("#use-proxy").is(":checked")) { + $("#proxy-settings").show(); + } else { + $("#proxy-settings").hide(); + } +} + +// 添加配置保存回调,支持重启 +function saveConfig() { + showLoading(); + const isDynamicUA = $(this).prop('checked'); + const configData = { + BROWSER_HEADLESS: $("#browser-headless").val() === 'true', + DYNAMIC_USERAGENT: isDynamicUA, + BROWSER_USER_AGENT: isDynamicUA ? "" : $("#browser-useragent").val(), + MAX_ACCOUNTS: parseInt($("#accounts-limit").val()), + EMAIL_CODE_TYPE: $("#captcha-method").val(), + EMAIL_DOMAINS: $("#email-domains").val(), + EMAIL_USERNAME: $("#email-username").val(), + EMAIL_PIN: $("#email-pin").val(), + BROWSER_PATH: $("#browser-path").val(), + CURSOR_PATH: $("#cursor-path").val(), + // 代理设置(确保这些字段存在) + USE_PROXY: $("#use-proxy").is(":checked"), + PROXY_TYPE: $("#proxy-type").val(), + PROXY_HOST: $("#proxy-host").val(), + PROXY_PORT: $("#proxy-port").val(), + PROXY_TIMEOUT: parseInt($("#proxy-timeout").val()) || 10, + PROXY_USERNAME: $("#proxy-username").val(), + PROXY_PASSWORD: $("#proxy-password").val() + }; + + $.ajax({ + url: '/config', + method: 'POST', + contentType: 'application/json', + data: JSON.stringify(configData), + success: function(response) { + hideLoading(); + if (response.success) { + // 添加重启询问提示 + showConfirmDialog( + '配置已成功保存', + '需要重启服务才能使更改生效。是否立即重启服务?', + function() { + // 确认重启 + restartService(); + } + ); + enableConfigForm(false); + } else { + showAlert('danger', '保存配置失败: ' + response.message); + } + }, + error: function(xhr) { + hideLoading(); + showAlert('danger', '保存配置失败: ' + xhr.statusText); + } + }); +} + +// 添加确认对话框函数 +function showConfirmDialog(title, message, confirmCallback) { + // 如果已存在对话框,先移除 + if ($("#confirm-dialog").length) { + $("#confirm-dialog").remove(); + } + + const dialogHTML = ` + + `; + + $('body').append(dialogHTML); + + const modal = new bootstrap.Modal(document.getElementById('confirm-dialog')); + modal.show(); + + $("#confirm-yes").click(function() { + modal.hide(); + if (typeof confirmCallback === 'function') { + confirmCallback(); + } + }); +} + +// 更新重启服务函数 +function restartService() { + showLoading('服务正在重新配置,请稍候...'); + + $.ajax({ + url: '/restart', + method: 'POST', + success: function(response) { + if (response.success) { + // 显示成功消息 + hideLoading(); + showAlert('success', response.message || '服务配置已更新,正在刷新页面...'); + + // 延迟3秒后刷新页面 + setTimeout(function() { + window.location.reload(); + }, 3000); + } else { + hideLoading(); + showAlert('danger', '重启服务失败: ' + (response.message || '未知错误')); + } + }, + error: function(xhr) { + hideLoading(); + showAlert('danger', '重启服务请求失败,请手动刷新页面'); + + // 延迟5秒后尝试刷新页面 + setTimeout(function() { + window.location.reload(); + }, 5000); + } + }); +} + +// 启用/禁用配置表单 +function enableConfigForm(enable) { + const inputs = $('#config-form select, #config-form input'); + if (enable) { + inputs.prop('disabled', false); + // 如果动态UA已启用,保持UA输入框禁用 + if ($("#dynamic-useragent").prop('checked')) { + $("#browser-useragent").prop('disabled', true); + } + // 显示按钮容器而不是单个按钮 + $('#config-actions').show(); + $('#edit-config-btn').hide(); + } else { + inputs.prop('disabled', true); + // 隐藏按钮容器 + $('#config-actions').hide(); + $('#edit-config-btn').show(); + } +} + +// 动态User-Agent切换逻辑 +$("#dynamic-useragent").change(function() { + const isDynamicUA = $(this).prop('checked'); + if (isDynamicUA) { + $("#browser-useragent").prop('disabled', true); + $("#useragent-input-container").addClass('text-muted'); + } else { + // 只有在编辑模式下才启用输入框 + const isEditMode = !$("#edit-config-btn").is(":visible"); + $("#browser-useragent").prop('disabled', !isEditMode); + $("#useragent-input-container").removeClass('text-muted'); + } +}); + +// 修改任务状态显示函数,保留状态处理逻辑 +function updateTaskStatusDisplay(statusData) { + // 获取UI元素引用 + const statusBadge = $("#registration-status"); + const taskStatusText = $("#task-status-text"); + const taskIcon = $("#task-status i"); + + // 直接使用服务器返回的统计数据 + const stats = statusData; + + // 计算实际使用的账号数量 + const usedCount = stats.active_count || 0; + const maxAccounts = stats.max_accounts || 10; + const remainingSlots = Math.max(0, maxAccounts - usedCount); + // 更新显示 + $("#current-count").text(usedCount); + $("#max-accounts").text(maxAccounts); + $("#remaining-slots").text(`剩余: ${remainingSlots}`); + // 计算使用百分比 + const usagePercent = maxAccounts > 0 ? Math.round((usedCount / maxAccounts) * 100) : 0; + + // 更新进度条 + $(".battery-progress").attr("data-percent", usagePercent); + $(".battery-percent").text(`${usagePercent}%`); + + // 更新任务详情 + if (statusData.registration_details) { + const details = statusData.registration_details; + // 更新统计信息 + if (details.statistics) { + $("#total-runs").text(details.statistics.total_runs); + $("#successful-runs").text(details.statistics.successful_runs); + $("#failed-runs").text(details.statistics.failed_runs); + $("#success-rate").text(details.statistics.success_rate); + } + } + + // 根据任务状态更新UI + switch(statusData.task_status) { + case "running": + statusBadge.removeClass("bg-success bg-warning bg-danger").addClass("bg-primary"); + statusBadge.text("运行中"); + taskStatusText.text(statusData.status_message || "任务正在运行中"); + taskIcon.removeClass("fa-check-circle fa-pause-circle fa-times-circle").addClass("fa-spinner fa-spin"); + taskIcon.removeClass("text-success text-warning text-danger").addClass("text-primary"); + + // 显示/隐藏按钮 + $("#start-registration").hide(); + $("#stop-registration").show(); + $("#registration-details").show(); + break; + + case "stopped": + default: + statusBadge.removeClass("bg-primary bg-warning bg-danger").addClass("bg-success"); + statusBadge.text("空闲中"); + taskStatusText.text(statusData.status_message || "系统空闲中,可以开始新任务"); + taskIcon.removeClass("fa-spinner fa-spin fa-pause-circle fa-times-circle").addClass("fa-check-circle"); + taskIcon.removeClass("text-primary text-warning text-danger").addClass("text-success"); + + // 显示/隐藏按钮 + $("#start-registration").show(); + $("#stop-registration").hide(); + $("#registration-details").hide(); + break; + } + +} + +// 绑定排序事件 +function bindSortEvents() { + // 字段排序变化 + $("#sort-field").change(function() { + currentSortField = $(this).val(); + loadAccounts(1, itemsPerPage, $("#search-input").val(), currentSortField, currentSortOrder); + }); + + // 排序方向变化 + $("#sort-order").change(function() { + currentSortOrder = $(this).val(); + loadAccounts(1, itemsPerPage, $("#search-input").val(), currentSortField, currentSortOrder); + }); +} + +// 修改表头排序配置,移除ID相关设置 +function addTableHeaderSorting() { + // 可排序的列 - 移除ID相关配置 + const sortableColumns = { + 'th-email': 'email', + 'th-date': 'created_at', + 'th-usage': 'usage_limit' + }; + + // 为表头添加排序类和点击事件 + Object.keys(sortableColumns).forEach(thId => { + const $th = $(`#${thId}`); + $th.addClass('sortable'); + + // 设置初始排序指示 + if (sortableColumns[thId] === currentSortField) { + $th.addClass(currentSortOrder); + } + + $th.click(function() { + const field = sortableColumns[thId]; + + // 如果点击当前排序列,切换排序方向 + if (field === currentSortField) { + currentSortOrder = currentSortOrder === 'asc' ? 'desc' : 'asc'; + } else { + // 否则,切换排序列并设置默认为降序 + currentSortField = field; + currentSortOrder = 'desc'; + } + + // 更新排序控件 + $("#sort-field").val(currentSortField); + $("#sort-order").val(currentSortOrder); + + // 重新加载数据 + loadAccounts(1, itemsPerPage, $("#search-input").val(), currentSortField, currentSortOrder); + }); + }); +} + +// 设置定时任务刷新 +function setupTaskRefresh() { + // 清除可能存在的旧定时器 + if (refreshTimer) { + clearInterval(refreshTimer); + } + // 设置新的定时刷新 + refreshTimer = setInterval(function() { + // 检查任务状态 + checkTaskStatus(); + + // 如果在账号管理页面,刷新账号列表 + if ($("#tasks-accounts").hasClass('active')) { + loadAccounts(currentPage, itemsPerPage, $("#search-input").val(), currentSortField, currentSortOrder); + } + }, REFRESH_INTERVAL); + + // 初始加载任务状态 + checkTaskStatus(); +} + +// 检查任务状态 +function checkTaskStatus() { + fetch('/registration/status') + .then(response => response.json()) + .then(data => { + // 确保有账号统计数据 + updateTaskStatusDisplay(data); + + // 更新任务运行时间和下次运行时间 + let registration_details = data.registration_details; + if (registration_details.last_run) { + $("#last-run").text(formatDateTime(data.registration_details.last_run)); + } + + if (data.registration_details.next_run) { + const nextRunTime = new Date(registration_details.next_run * 1000); + const now = new Date(); + const timeLeft = Math.max(0, Math.floor((nextRunTime - now) / 1000)); + + if (timeLeft > 0) { + $("#next-run").text(`${formatDateTime(registration_details.next_run * 1000)} (还有${formatTimeLeft(timeLeft)})`); + } else { + $("#next-run").text(`${formatDateTime(registration_details.next_run * 1000)}`); + } + } else { + $("#next-run").text("未排程"); + } + + // 更新注册进度和消息 + if (registration_details.registration_progress) { + $("#registration-progress").text(registration_details.registration_progress); + } + + if (registration_details.registration_message) { + $("#registration-message").text(registration_details.registration_message); + } + }) + .catch(error => { + console.error('获取任务状态出错:', error); + }); +} + +// 格式化日期时间 +function formatDateTime(timestamp) { + const date = new Date(timestamp); + return date.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + hour12: false + }); +} + +// 格式化剩余时间 +function formatTimeLeft(seconds) { + if (seconds < 60) { + return `${seconds}秒`; + } else if (seconds < 3600) { + return `${Math.floor(seconds / 60)}分${seconds % 60}秒`; + } else { + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + return `${hours}小时${minutes}分`; + } +} + +// 添加重置机器ID函数 +function resetMachineId() { + showLoading(); + + $.ajax({ + url: '/reset-machine', + method: 'GET', + success: function(response) { + hideLoading(); + if (response.success) { + showAlert('success', '成功重置机器ID。' + (response.message || '')); + + // 询问是否需要重启服务以应用更改 + setTimeout(function() { + showConfirmDialog( + '重启服务', + '机器ID已重置,建议重启服务以确保更改生效。是否立即重启?', + function() { + restartService(); + } + ); + }, 1000); + } else { + showAlert('danger', '重置机器ID失败: ' + (response.message || '未知错误')); + } + }, + error: function(xhr) { + hideLoading(); + showAlert('danger', '重置机器ID失败: ' + (xhr.responseJSON?.message || xhr.statusText || '未知错误')); + } + }); +} + +// 导出账号函数 +function exportAccounts() { + showLoading(); + + // 直接使用浏览器下载功能 + const downloadLink = document.createElement('a'); + downloadLink.href = '/accounts/export'; + downloadLink.download = 'cursor_accounts.json'; + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); + + setTimeout(() => { + hideLoading(); + showAlert('success', '账号导出请求已发送,文件将自动下载'); + }, 1000); +} + +// 导入账号函数 +function importAccounts(file) { + showLoading(); + + const formData = new FormData(); + formData.append('file', file); + + // 发送导入请求 + $.ajax({ + url: '/accounts/import', + method: 'POST', + data: formData, + processData: false, + contentType: false, + success: function(response) { + hideLoading(); + if (response.success) { + showAlert('success', response.message); + + // 刷新账号列表 + loadAccounts(1, itemsPerPage); + } else { + showAlert('danger', '导入账号失败: ' + response.message); + } + }, + error: function(xhr) { + hideLoading(); + showAlert('danger', '导入账号失败: ' + (xhr.responseJSON?.detail || xhr.statusText)); + } + }); +} + +// 获取账号使用记录 +function getAccountUsageRecords(email, id) { + showLoading(); + + // 设置模态框中的账号邮箱 + $('#recordEmail').text(email); + + // 清空记录列表 + $('#usageRecordBody').empty(); + + fetch(`/account/${id}/usage-records`) + .then(response => response.json()) + .then(data => { + hideLoading(); + + if (data.success) { + const records = data.records; + + if (records && records.length > 0) { + // 隐藏无记录提示 + $('#no-records').hide(); + + // 显示记录 + records.forEach(record => { + const row = ` + + ${formatDateTime(record.created_at)} + ${record.ip || '-'} + + ${record.user_agent || '-'} + + + `; + $('#usageRecordBody').append(row); + }); + } else { + // 显示无记录提示 + $('#usageRecordBody').empty(); + $('#no-records').show(); + } + + // 显示模态框 + new bootstrap.Modal(document.getElementById('usageRecordModal')).show(); + } else { + showAlert(`获取使用记录失败: ${data.message || '未知错误'}`, 'danger'); + } + }) + .catch(error => { + console.error('获取使用记录时发生错误:', error); + hideLoading(); + showAlert('获取使用记录失败,请稍后重试', 'danger'); + }); +} + +// 为更新余量按钮添加点击事件处理 +$(document).on('click', '.update-usage-btn', function() { + const email = $(this).data('email'); + updateAccountUsage(email); +}); + +// 添加更新所有账户余量的函数 +function updateAllAccountsUsage() { + showLoading('正在更新所有账户余量...'); + + return fetch('/update_all_usage', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }) + .then(response => response.json()) + .then(data => { + hideLoading(); + if (data.success) { + showAlert('所有账户余量更新成功', 'success'); + // 刷新整个页面而不仅仅是账户列表 + location.reload(); + } else { + showAlert(`更新失败: ${data.message || '未知错误'}`, 'danger'); + } + }) + .catch(error => { + console.error('更新所有账户余量时发生错误:', error); + hideLoading(); + showAlert('更新失败,请稍后重试', 'danger'); + }); +} + +// 为更新所有账户余量按钮添加点击事件 +$(document).on('click', '#update-all-usage-btn', function() { + updateAllAccountsUsage(); +}); + +// 新增函数 - 更新账号使用量 +function updateAccountUsage(email) { + // 显示加载指示器 + showLoading(); + + // 调用获取账号用量的API + fetch(`/account/${encodeURIComponent(email)}/usage`) + .then(res => res.json()) + .then(data => { + hideLoading(); + if (data.success) { + // 显示成功提示 + showToast('余量更新成功', 'success'); + + // 刷新账号列表以显示更新后的数据 + loadAccounts(currentPage); + } else { + showToast(`更新失败: ${data.message}`, 'error'); + } + }) + .catch(error => { + hideLoading(); + showToast('更新余量时发生错误', 'error'); + console.error('更新余量出错:', error); + }); +} \ No newline at end of file diff --git a/static/js/bootstrap.bundle.min.js b/static/js/bootstrap.bundle.min.js new file mode 100644 index 0000000..4f63628 --- /dev/null +++ b/static/js/bootstrap.bundle.min.js @@ -0,0 +1,3881 @@ +/*! + * Bootstrap v5.3.0-alpha1 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t, e) { + "object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).bootstrap = e() +}(this, (function() { + "use strict"; + const t = "transitionend" + , e = t => (t && window.CSS && window.CSS.escape && (t = t.replace(/#([^\s"#']+)/g, ( (t, e) => `#${CSS.escape(e)}`))), + t) + , i = e => { + e.dispatchEvent(new Event(t)) + } + , n = t => !(!t || "object" != typeof t) && (void 0 !== t.jquery && (t = t[0]), + void 0 !== t.nodeType) + , s = t => n(t) ? t.jquery ? t[0] : t : "string" == typeof t && t.length > 0 ? document.querySelector(e(t)) : null + , o = t => { + if (!n(t) || 0 === t.getClientRects().length) + return !1; + const e = "visible" === getComputedStyle(t).getPropertyValue("visibility") + , i = t.closest("details:not([open])"); + if (!i) + return e; + if (i !== t) { + const e = t.closest("summary"); + if (e && e.parentNode !== i) + return !1; + if (null === e) + return !1 + } + return e + } + , r = t => !t || t.nodeType !== Node.ELEMENT_NODE || !!t.classList.contains("disabled") || (void 0 !== t.disabled ? t.disabled : t.hasAttribute("disabled") && "false" !== t.getAttribute("disabled")) + , a = t => { + if (!document.documentElement.attachShadow) + return null; + if ("function" == typeof t.getRootNode) { + const e = t.getRootNode(); + return e instanceof ShadowRoot ? e : null + } + return t instanceof ShadowRoot ? t : t.parentNode ? a(t.parentNode) : null + } + , l = () => {} + , c = t => { + t.offsetHeight + } + , h = () => window.jQuery && !document.body.hasAttribute("data-bs-no-jquery") ? window.jQuery : null + , d = [] + , u = () => "rtl" === document.documentElement.dir + , f = t => { + var e; + e = () => { + const e = h(); + if (e) { + const i = t.NAME + , n = e.fn[i]; + e.fn[i] = t.jQueryInterface, + e.fn[i].Constructor = t, + e.fn[i].noConflict = () => (e.fn[i] = n, + t.jQueryInterface) + } + } + , + "loading" === document.readyState ? (d.length || document.addEventListener("DOMContentLoaded", ( () => { + for (const t of d) + t() + } + )), + d.push(e)) : e() + } + , p = (t, e=[], i=t) => "function" == typeof t ? t(...e) : i + , m = (e, n, s=!0) => { + if (!s) + return void p(e); + const o = (t => { + if (!t) + return 0; + let {transitionDuration: e, transitionDelay: i} = window.getComputedStyle(t); + const n = Number.parseFloat(e) + , s = Number.parseFloat(i); + return n || s ? (e = e.split(",")[0], + i = i.split(",")[0], + 1e3 * (Number.parseFloat(e) + Number.parseFloat(i))) : 0 + } + )(n) + 5; + let r = !1; + const a = ({target: i}) => { + i === n && (r = !0, + n.removeEventListener(t, a), + p(e)) + } + ; + n.addEventListener(t, a), + setTimeout(( () => { + r || i(n) + } + ), o) + } + , g = (t, e, i, n) => { + const s = t.length; + let o = t.indexOf(e); + return -1 === o ? !i && n ? t[s - 1] : t[0] : (o += i ? 1 : -1, + n && (o = (o + s) % s), + t[Math.max(0, Math.min(o, s - 1))]) + } + , _ = /[^.]*(?=\..*)\.|.*/ + , b = /\..*/ + , v = /::\d+$/ + , y = {}; + let w = 1; + const A = { + mouseenter: "mouseover", + mouseleave: "mouseout" + } + , E = 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 T(t, e) { + return e && `${e}::${w++}` || t.uidEvent || w++ + } + function C(t) { + const e = T(t); + return t.uidEvent = e, + y[e] = y[e] || {}, + y[e] + } + function O(t, e, i=null) { + return Object.values(t).find((t => t.callable === e && t.delegationSelector === i)) + } + function x(t, e, i) { + const n = "string" == typeof e + , s = n ? i : e || i; + let o = D(t); + return E.has(o) || (o = t), + [n, s, o] + } + function k(t, e, i, n, s) { + if ("string" != typeof e || !t) + return; + let[o,r,a] = x(e, i, n); + if (e in A) { + const t = t => function(e) { + if (!e.relatedTarget || e.relatedTarget !== e.delegateTarget && !e.delegateTarget.contains(e.relatedTarget)) + return t.call(this, e) + } + ; + r = t(r) + } + const l = C(t) + , c = l[a] || (l[a] = {}) + , h = O(c, r, o ? i : null); + if (h) + return void (h.oneOff = h.oneOff && s); + const d = T(r, e.replace(_, "")) + , u = o ? function(t, e, i) { + return function n(s) { + const o = t.querySelectorAll(e); + for (let {target: r} = s; r && r !== this; r = r.parentNode) + for (const a of o) + if (a === r) + return N(s, { + delegateTarget: r + }), + n.oneOff && I.off(t, s.type, e, i), + i.apply(r, [s]) + } + }(t, i, r) : function(t, e) { + return function i(n) { + return N(n, { + delegateTarget: t + }), + i.oneOff && I.off(t, n.type, e), + e.apply(t, [n]) + } + }(t, r); + u.delegationSelector = o ? i : null, + u.callable = r, + u.oneOff = s, + u.uidEvent = d, + c[d] = u, + t.addEventListener(a, u, o) + } + function L(t, e, i, n, s) { + const o = O(e[i], n, s); + o && (t.removeEventListener(i, o, Boolean(s)), + delete e[i][o.uidEvent]) + } + function S(t, e, i, n) { + const s = e[i] || {}; + for (const [o,r] of Object.entries(s)) + o.includes(n) && L(t, e, i, r.callable, r.delegationSelector) + } + function D(t) { + return t = t.replace(b, ""), + A[t] || t + } + const I = { + on(t, e, i, n) { + k(t, e, i, n, !1) + }, + one(t, e, i, n) { + k(t, e, i, n, !0) + }, + off(t, e, i, n) { + if ("string" != typeof e || !t) + return; + const [s,o,r] = x(e, i, n) + , a = r !== e + , l = C(t) + , c = l[r] || {} + , h = e.startsWith("."); + if (void 0 === o) { + if (h) + for (const i of Object.keys(l)) + S(t, l, i, e.slice(1)); + for (const [i,n] of Object.entries(c)) { + const s = i.replace(v, ""); + a && !e.includes(s) || L(t, l, r, n.callable, n.delegationSelector) + } + } else { + if (!Object.keys(c).length) + return; + L(t, l, r, o, s ? i : null) + } + }, + trigger(t, e, i) { + if ("string" != typeof e || !t) + return null; + const n = h(); + let s = null + , o = !0 + , r = !0 + , a = !1; + e !== D(e) && n && (s = n.Event(e, i), + n(t).trigger(s), + o = !s.isPropagationStopped(), + r = !s.isImmediatePropagationStopped(), + a = s.isDefaultPrevented()); + let l = new Event(e,{ + bubbles: o, + cancelable: !0 + }); + return l = N(l, i), + a && l.preventDefault(), + r && t.dispatchEvent(l), + l.defaultPrevented && s && s.preventDefault(), + l + } + }; + function N(t, e={}) { + for (const [i,n] of Object.entries(e)) + try { + t[i] = n + } catch (e) { + Object.defineProperty(t, i, { + configurable: !0, + get: () => n + }) + } + return t + } + const P = new Map + , j = { + set(t, e, i) { + P.has(t) || P.set(t, new Map); + const n = P.get(t); + n.has(e) || 0 === n.size ? n.set(e, i) : console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`) + }, + get: (t, e) => P.has(t) && P.get(t).get(e) || null, + remove(t, e) { + if (!P.has(t)) + return; + const i = P.get(t); + i.delete(e), + 0 === i.size && P.delete(t) + } + }; + function M(t) { + if ("true" === t) + return !0; + if ("false" === t) + return !1; + if (t === Number(t).toString()) + return Number(t); + if ("" === t || "null" === t) + return null; + if ("string" != typeof t) + return t; + try { + return JSON.parse(decodeURIComponent(t)) + } catch (e) { + return t + } + } + function F(t) { + return t.replace(/[A-Z]/g, (t => `-${t.toLowerCase()}`)) + } + const H = { + setDataAttribute(t, e, i) { + t.setAttribute(`data-bs-${F(e)}`, i) + }, + removeDataAttribute(t, e) { + t.removeAttribute(`data-bs-${F(e)}`) + }, + getDataAttributes(t) { + if (!t) + return {}; + const e = {} + , i = Object.keys(t.dataset).filter((t => t.startsWith("bs") && !t.startsWith("bsConfig"))); + for (const n of i) { + let i = n.replace(/^bs/, ""); + i = i.charAt(0).toLowerCase() + i.slice(1, i.length), + e[i] = M(t.dataset[n]) + } + return e + }, + getDataAttribute: (t, e) => M(t.getAttribute(`data-bs-${F(e)}`)) + }; + class $ { + 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(t) { + return t = this._mergeConfigObj(t), + t = this._configAfterMerge(t), + this._typeCheckConfig(t), + t + } + _configAfterMerge(t) { + return t + } + _mergeConfigObj(t, e) { + const i = n(e) ? H.getDataAttribute(e, "config") : {}; + return { + ...this.constructor.Default, + ..."object" == typeof i ? i : {}, + ...n(e) ? H.getDataAttributes(e) : {}, + ..."object" == typeof t ? t : {} + } + } + _typeCheckConfig(t, e=this.constructor.DefaultType) { + for (const [s,o] of Object.entries(e)) { + const e = t[s] + , r = n(e) ? "element" : null == (i = e) ? `${i}` : Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase(); + if (!new RegExp(o).test(r)) + throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${s}" provided type "${r}" but expected type "${o}".`) + } + var i + } + } + class W extends $ { + constructor(t, e) { + super(), + (t = s(t)) && (this._element = t, + this._config = this._getConfig(e), + j.set(this._element, this.constructor.DATA_KEY, this)) + } + dispose() { + j.remove(this._element, this.constructor.DATA_KEY), + I.off(this._element, this.constructor.EVENT_KEY); + for (const t of Object.getOwnPropertyNames(this)) + this[t] = null + } + _queueCallback(t, e, i=!0) { + m(t, e, i) + } + _getConfig(t) { + return t = this._mergeConfigObj(t, this._element), + t = this._configAfterMerge(t), + this._typeCheckConfig(t), + t + } + static getInstance(t) { + return j.get(s(t), this.DATA_KEY) + } + static getOrCreateInstance(t, e={}) { + return this.getInstance(t) || new this(t,"object" == typeof e ? e : null) + } + static get VERSION() { + return "5.3.0-alpha1" + } + static get DATA_KEY() { + return `bs.${this.NAME}` + } + static get EVENT_KEY() { + return `.${this.DATA_KEY}` + } + static eventName(t) { + return `${t}${this.EVENT_KEY}` + } + } + const B = t => { + let i = t.getAttribute("data-bs-target"); + if (!i || "#" === i) { + let e = t.getAttribute("href"); + if (!e || !e.includes("#") && !e.startsWith(".")) + return null; + e.includes("#") && !e.startsWith("#") && (e = `#${e.split("#")[1]}`), + i = e && "#" !== e ? e.trim() : null + } + return e(i) + } + , z = { + find: (t, e=document.documentElement) => [].concat(...Element.prototype.querySelectorAll.call(e, t)), + findOne: (t, e=document.documentElement) => Element.prototype.querySelector.call(e, t), + children: (t, e) => [].concat(...t.children).filter((t => t.matches(e))), + parents(t, e) { + const i = []; + let n = t.parentNode.closest(e); + for (; n; ) + i.push(n), + n = n.parentNode.closest(e); + return i + }, + prev(t, e) { + let i = t.previousElementSibling; + for (; i; ) { + if (i.matches(e)) + return [i]; + i = i.previousElementSibling + } + return [] + }, + next(t, e) { + let i = t.nextElementSibling; + for (; i; ) { + if (i.matches(e)) + return [i]; + i = i.nextElementSibling + } + return [] + }, + focusableChildren(t) { + const e = ["a", "button", "input", "textarea", "select", "details", "[tabindex]", '[contenteditable="true"]'].map((t => `${t}:not([tabindex^="-"])`)).join(","); + return this.find(e, t).filter((t => !r(t) && o(t))) + }, + getSelectorFromElement(t) { + const e = B(t); + return e && z.findOne(e) ? e : null + }, + getElementFromSelector(t) { + const e = B(t); + return e ? z.findOne(e) : null + }, + getMultipleElementsFromSelector(t) { + const e = B(t); + return e ? z.find(e) : [] + } + } + , R = (t, e="hide") => { + const i = `click.dismiss${t.EVENT_KEY}` + , n = t.NAME; + I.on(document, i, `[data-bs-dismiss="${n}"]`, (function(i) { + if (["A", "AREA"].includes(this.tagName) && i.preventDefault(), + r(this)) + return; + const s = z.getElementFromSelector(this) || this.closest(`.${n}`); + t.getOrCreateInstance(s)[e]() + } + )) + } + ; + class q extends W { + static get NAME() { + return "alert" + } + close() { + if (I.trigger(this._element, "close.bs.alert").defaultPrevented) + return; + this._element.classList.remove("show"); + const t = this._element.classList.contains("fade"); + this._queueCallback(( () => this._destroyElement()), this._element, t) + } + _destroyElement() { + this._element.remove(), + I.trigger(this._element, "closed.bs.alert"), + this.dispose() + } + static jQueryInterface(t) { + return this.each((function() { + const e = q.getOrCreateInstance(this); + if ("string" == typeof t) { + if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) + throw new TypeError(`No method named "${t}"`); + e[t](this) + } + } + )) + } + } + R(q, "close"), + f(q); + const V = '[data-bs-toggle="button"]'; + class K extends W { + static get NAME() { + return "button" + } + toggle() { + this._element.setAttribute("aria-pressed", this._element.classList.toggle("active")) + } + static jQueryInterface(t) { + return this.each((function() { + const e = K.getOrCreateInstance(this); + "toggle" === t && e[t]() + } + )) + } + } + I.on(document, "click.bs.button.data-api", V, (t => { + t.preventDefault(); + const e = t.target.closest(V); + K.getOrCreateInstance(e).toggle() + } + )), + f(K); + const Q = { + endCallback: null, + leftCallback: null, + rightCallback: null + } + , X = { + endCallback: "(function|null)", + leftCallback: "(function|null)", + rightCallback: "(function|null)" + }; + class Y extends $ { + constructor(t, e) { + super(), + this._element = t, + t && Y.isSupported() && (this._config = this._getConfig(e), + this._deltaX = 0, + this._supportPointerEvents = Boolean(window.PointerEvent), + this._initEvents()) + } + static get Default() { + return Q + } + static get DefaultType() { + return X + } + static get NAME() { + return "swipe" + } + dispose() { + I.off(this._element, ".bs.swipe") + } + _start(t) { + this._supportPointerEvents ? this._eventIsPointerPenTouch(t) && (this._deltaX = t.clientX) : this._deltaX = t.touches[0].clientX + } + _end(t) { + this._eventIsPointerPenTouch(t) && (this._deltaX = t.clientX - this._deltaX), + this._handleSwipe(), + p(this._config.endCallback) + } + _move(t) { + this._deltaX = t.touches && t.touches.length > 1 ? 0 : t.touches[0].clientX - this._deltaX + } + _handleSwipe() { + const t = Math.abs(this._deltaX); + if (t <= 40) + return; + const e = t / this._deltaX; + this._deltaX = 0, + e && p(e > 0 ? this._config.rightCallback : this._config.leftCallback) + } + _initEvents() { + this._supportPointerEvents ? (I.on(this._element, "pointerdown.bs.swipe", (t => this._start(t))), + I.on(this._element, "pointerup.bs.swipe", (t => this._end(t))), + this._element.classList.add("pointer-event")) : (I.on(this._element, "touchstart.bs.swipe", (t => this._start(t))), + I.on(this._element, "touchmove.bs.swipe", (t => this._move(t))), + I.on(this._element, "touchend.bs.swipe", (t => this._end(t)))) + } + _eventIsPointerPenTouch(t) { + return this._supportPointerEvents && ("pen" === t.pointerType || "touch" === t.pointerType) + } + static isSupported() { + return "ontouchstart"in document.documentElement || navigator.maxTouchPoints > 0 + } + } + const U = "next" + , G = "prev" + , J = "left" + , Z = "right" + , tt = "slid.bs.carousel" + , et = "carousel" + , it = "active" + , nt = { + ArrowLeft: Z, + ArrowRight: J + } + , st = { + interval: 5e3, + keyboard: !0, + pause: "hover", + ride: !1, + touch: !0, + wrap: !0 + } + , ot = { + interval: "(number|boolean)", + keyboard: "boolean", + pause: "(string|boolean)", + ride: "(boolean|string)", + touch: "boolean", + wrap: "boolean" + }; + class rt extends W { + constructor(t, e) { + super(t, e), + this._interval = null, + this._activeElement = null, + this._isSliding = !1, + this.touchTimeout = null, + this._swipeHelper = null, + this._indicatorsElement = z.findOne(".carousel-indicators", this._element), + this._addEventListeners(), + this._config.ride === et && this.cycle() + } + static get Default() { + return st + } + static get DefaultType() { + return ot + } + static get NAME() { + return "carousel" + } + next() { + this._slide(U) + } + nextWhenVisible() { + !document.hidden && o(this._element) && this.next() + } + prev() { + this._slide(G) + } + pause() { + this._isSliding && i(this._element), + this._clearInterval() + } + cycle() { + this._clearInterval(), + this._updateInterval(), + this._interval = setInterval(( () => this.nextWhenVisible()), this._config.interval) + } + _maybeEnableCycle() { + this._config.ride && (this._isSliding ? I.one(this._element, tt, ( () => this.cycle())) : this.cycle()) + } + to(t) { + const e = this._getItems(); + if (t > e.length - 1 || t < 0) + return; + if (this._isSliding) + return void I.one(this._element, tt, ( () => this.to(t))); + const i = this._getItemIndex(this._getActive()); + if (i === t) + return; + const n = t > i ? U : G; + this._slide(n, e[t]) + } + dispose() { + this._swipeHelper && this._swipeHelper.dispose(), + super.dispose() + } + _configAfterMerge(t) { + return t.defaultInterval = t.interval, + t + } + _addEventListeners() { + this._config.keyboard && I.on(this._element, "keydown.bs.carousel", (t => this._keydown(t))), + "hover" === this._config.pause && (I.on(this._element, "mouseenter.bs.carousel", ( () => this.pause())), + I.on(this._element, "mouseleave.bs.carousel", ( () => this._maybeEnableCycle()))), + this._config.touch && Y.isSupported() && this._addTouchEventListeners() + } + _addTouchEventListeners() { + for (const t of z.find(".carousel-item img", this._element)) + I.on(t, "dragstart.bs.carousel", (t => t.preventDefault())); + const t = { + leftCallback: () => this._slide(this._directionToOrder(J)), + rightCallback: () => this._slide(this._directionToOrder(Z)), + endCallback: () => { + "hover" === this._config.pause && (this.pause(), + this.touchTimeout && clearTimeout(this.touchTimeout), + this.touchTimeout = setTimeout(( () => this._maybeEnableCycle()), 500 + this._config.interval)) + } + }; + this._swipeHelper = new Y(this._element,t) + } + _keydown(t) { + if (/input|textarea/i.test(t.target.tagName)) + return; + const e = nt[t.key]; + e && (t.preventDefault(), + this._slide(this._directionToOrder(e))) + } + _getItemIndex(t) { + return this._getItems().indexOf(t) + } + _setActiveIndicatorElement(t) { + if (!this._indicatorsElement) + return; + const e = z.findOne(".active", this._indicatorsElement); + e.classList.remove(it), + e.removeAttribute("aria-current"); + const i = z.findOne(`[data-bs-slide-to="${t}"]`, this._indicatorsElement); + i && (i.classList.add(it), + i.setAttribute("aria-current", "true")) + } + _updateInterval() { + const t = this._activeElement || this._getActive(); + if (!t) + return; + const e = Number.parseInt(t.getAttribute("data-bs-interval"), 10); + this._config.interval = e || this._config.defaultInterval + } + _slide(t, e=null) { + if (this._isSliding) + return; + const i = this._getActive() + , n = t === U + , s = e || g(this._getItems(), i, n, this._config.wrap); + if (s === i) + return; + const o = this._getItemIndex(s) + , r = e => I.trigger(this._element, e, { + relatedTarget: s, + direction: this._orderToDirection(t), + from: this._getItemIndex(i), + to: o + }); + if (r("slide.bs.carousel").defaultPrevented) + return; + if (!i || !s) + return; + const a = Boolean(this._interval); + this.pause(), + this._isSliding = !0, + this._setActiveIndicatorElement(o), + this._activeElement = s; + const l = n ? "carousel-item-start" : "carousel-item-end" + , h = n ? "carousel-item-next" : "carousel-item-prev"; + s.classList.add(h), + c(s), + i.classList.add(l), + s.classList.add(l), + this._queueCallback(( () => { + s.classList.remove(l, h), + s.classList.add(it), + i.classList.remove(it, h, l), + this._isSliding = !1, + r(tt) + } + ), i, this._isAnimated()), + a && this.cycle() + } + _isAnimated() { + return this._element.classList.contains("slide") + } + _getActive() { + return z.findOne(".active.carousel-item", this._element) + } + _getItems() { + return z.find(".carousel-item", this._element) + } + _clearInterval() { + this._interval && (clearInterval(this._interval), + this._interval = null) + } + _directionToOrder(t) { + return u() ? t === J ? G : U : t === J ? U : G + } + _orderToDirection(t) { + return u() ? t === G ? J : Z : t === G ? Z : J + } + static jQueryInterface(t) { + return this.each((function() { + const e = rt.getOrCreateInstance(this, t); + if ("number" != typeof t) { + if ("string" == typeof t) { + if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) + throw new TypeError(`No method named "${t}"`); + e[t]() + } + } else + e.to(t) + } + )) + } + } + I.on(document, "click.bs.carousel.data-api", "[data-bs-slide], [data-bs-slide-to]", (function(t) { + const e = z.getElementFromSelector(this); + if (!e || !e.classList.contains(et)) + return; + t.preventDefault(); + const i = rt.getOrCreateInstance(e) + , n = this.getAttribute("data-bs-slide-to"); + return n ? (i.to(n), + void i._maybeEnableCycle()) : "next" === H.getDataAttribute(this, "slide") ? (i.next(), + void i._maybeEnableCycle()) : (i.prev(), + void i._maybeEnableCycle()) + } + )), + I.on(window, "load.bs.carousel.data-api", ( () => { + const t = z.find('[data-bs-ride="carousel"]'); + for (const e of t) + rt.getOrCreateInstance(e) + } + )), + f(rt); + const at = "show" + , lt = "collapse" + , ct = "collapsing" + , ht = '[data-bs-toggle="collapse"]' + , dt = { + parent: null, + toggle: !0 + } + , ut = { + parent: "(null|element)", + toggle: "boolean" + }; + class ft extends W { + constructor(t, e) { + super(t, e), + this._isTransitioning = !1, + this._triggerArray = []; + const i = z.find(ht); + for (const t of i) { + const e = z.getSelectorFromElement(t) + , i = z.find(e).filter((t => t === this._element)); + null !== e && i.length && this._triggerArray.push(t) + } + this._initializeChildren(), + this._config.parent || this._addAriaAndCollapsedClass(this._triggerArray, this._isShown()), + this._config.toggle && this.toggle() + } + static get Default() { + return dt + } + static get DefaultType() { + return ut + } + static get NAME() { + return "collapse" + } + toggle() { + this._isShown() ? this.hide() : this.show() + } + show() { + if (this._isTransitioning || this._isShown()) + return; + let t = []; + if (this._config.parent && (t = this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t => t !== this._element)).map((t => ft.getOrCreateInstance(t, { + toggle: !1 + })))), + t.length && t[0]._isTransitioning) + return; + if (I.trigger(this._element, "show.bs.collapse").defaultPrevented) + return; + for (const e of t) + e.hide(); + const e = this._getDimension(); + this._element.classList.remove(lt), + this._element.classList.add(ct), + this._element.style[e] = 0, + this._addAriaAndCollapsedClass(this._triggerArray, !0), + this._isTransitioning = !0; + const i = `scroll${e[0].toUpperCase() + e.slice(1)}`; + this._queueCallback(( () => { + this._isTransitioning = !1, + this._element.classList.remove(ct), + this._element.classList.add(lt, at), + this._element.style[e] = "", + I.trigger(this._element, "shown.bs.collapse") + } + ), this._element, !0), + this._element.style[e] = `${this._element[i]}px` + } + hide() { + if (this._isTransitioning || !this._isShown()) + return; + if (I.trigger(this._element, "hide.bs.collapse").defaultPrevented) + return; + const t = this._getDimension(); + this._element.style[t] = `${this._element.getBoundingClientRect()[t]}px`, + c(this._element), + this._element.classList.add(ct), + this._element.classList.remove(lt, at); + for (const t of this._triggerArray) { + const e = z.getElementFromSelector(t); + e && !this._isShown(e) && this._addAriaAndCollapsedClass([t], !1) + } + this._isTransitioning = !0, + this._element.style[t] = "", + this._queueCallback(( () => { + this._isTransitioning = !1, + this._element.classList.remove(ct), + this._element.classList.add(lt), + I.trigger(this._element, "hidden.bs.collapse") + } + ), this._element, !0) + } + _isShown(t=this._element) { + return t.classList.contains(at) + } + _configAfterMerge(t) { + return t.toggle = Boolean(t.toggle), + t.parent = s(t.parent), + t + } + _getDimension() { + return this._element.classList.contains("collapse-horizontal") ? "width" : "height" + } + _initializeChildren() { + if (!this._config.parent) + return; + const t = this._getFirstLevelChildren(ht); + for (const e of t) { + const t = z.getElementFromSelector(e); + t && this._addAriaAndCollapsedClass([e], this._isShown(t)) + } + } + _getFirstLevelChildren(t) { + const e = z.find(":scope .collapse .collapse", this._config.parent); + return z.find(t, this._config.parent).filter((t => !e.includes(t))) + } + _addAriaAndCollapsedClass(t, e) { + if (t.length) + for (const i of t) + i.classList.toggle("collapsed", !e), + i.setAttribute("aria-expanded", e) + } + static jQueryInterface(t) { + const e = {}; + return "string" == typeof t && /show|hide/.test(t) && (e.toggle = !1), + this.each((function() { + const i = ft.getOrCreateInstance(this, e); + if ("string" == typeof t) { + if (void 0 === i[t]) + throw new TypeError(`No method named "${t}"`); + i[t]() + } + } + )) + } + } + I.on(document, "click.bs.collapse.data-api", ht, (function(t) { + ("A" === t.target.tagName || t.delegateTarget && "A" === t.delegateTarget.tagName) && t.preventDefault(); + for (const t of z.getMultipleElementsFromSelector(this)) + ft.getOrCreateInstance(t, { + toggle: !1 + }).toggle() + } + )), + f(ft); + var pt = "top" + , mt = "bottom" + , gt = "right" + , _t = "left" + , bt = "auto" + , vt = [pt, mt, gt, _t] + , yt = "start" + , wt = "end" + , At = "clippingParents" + , Et = "viewport" + , Tt = "popper" + , Ct = "reference" + , Ot = vt.reduce((function(t, e) { + return t.concat([e + "-" + yt, e + "-" + wt]) + } + ), []) + , xt = [].concat(vt, [bt]).reduce((function(t, e) { + return t.concat([e, e + "-" + yt, e + "-" + wt]) + } + ), []) + , kt = "beforeRead" + , Lt = "read" + , St = "afterRead" + , Dt = "beforeMain" + , It = "main" + , Nt = "afterMain" + , Pt = "beforeWrite" + , jt = "write" + , Mt = "afterWrite" + , Ft = [kt, Lt, St, Dt, It, Nt, Pt, jt, Mt]; + function Ht(t) { + return t ? (t.nodeName || "").toLowerCase() : null + } + function $t(t) { + if (null == t) + return window; + if ("[object Window]" !== t.toString()) { + var e = t.ownerDocument; + return e && e.defaultView || window + } + return t + } + function Wt(t) { + return t instanceof $t(t).Element || t instanceof Element + } + function Bt(t) { + return t instanceof $t(t).HTMLElement || t instanceof HTMLElement + } + function zt(t) { + return "undefined" != typeof ShadowRoot && (t instanceof $t(t).ShadowRoot || t instanceof ShadowRoot) + } + const Rt = { + name: "applyStyles", + enabled: !0, + phase: "write", + fn: function(t) { + var e = t.state; + Object.keys(e.elements).forEach((function(t) { + var i = e.styles[t] || {} + , n = e.attributes[t] || {} + , s = e.elements[t]; + Bt(s) && Ht(s) && (Object.assign(s.style, i), + Object.keys(n).forEach((function(t) { + var e = n[t]; + !1 === e ? s.removeAttribute(t) : s.setAttribute(t, !0 === e ? "" : e) + } + ))) + } + )) + }, + effect: function(t) { + var e = t.state + , i = { + popper: { + position: e.options.strategy, + left: "0", + top: "0", + margin: "0" + }, + arrow: { + position: "absolute" + }, + reference: {} + }; + return Object.assign(e.elements.popper.style, i.popper), + e.styles = i, + e.elements.arrow && Object.assign(e.elements.arrow.style, i.arrow), + function() { + Object.keys(e.elements).forEach((function(t) { + var n = e.elements[t] + , s = e.attributes[t] || {} + , o = Object.keys(e.styles.hasOwnProperty(t) ? e.styles[t] : i[t]).reduce((function(t, e) { + return t[e] = "", + t + } + ), {}); + Bt(n) && Ht(n) && (Object.assign(n.style, o), + Object.keys(s).forEach((function(t) { + n.removeAttribute(t) + } + ))) + } + )) + } + }, + requires: ["computeStyles"] + }; + function qt(t) { + return t.split("-")[0] + } + var Vt = Math.max + , Kt = Math.min + , Qt = Math.round; + function Xt() { + var t = navigator.userAgentData; + return null != t && t.brands ? t.brands.map((function(t) { + return t.brand + "/" + t.version + } + )).join(" ") : navigator.userAgent + } + function Yt() { + return !/^((?!chrome|android).)*safari/i.test(Xt()) + } + function Ut(t, e, i) { + void 0 === e && (e = !1), + void 0 === i && (i = !1); + var n = t.getBoundingClientRect() + , s = 1 + , o = 1; + e && Bt(t) && (s = t.offsetWidth > 0 && Qt(n.width) / t.offsetWidth || 1, + o = t.offsetHeight > 0 && Qt(n.height) / t.offsetHeight || 1); + var r = (Wt(t) ? $t(t) : window).visualViewport + , a = !Yt() && i + , l = (n.left + (a && r ? r.offsetLeft : 0)) / s + , c = (n.top + (a && r ? r.offsetTop : 0)) / o + , h = n.width / s + , d = n.height / o; + return { + width: h, + height: d, + top: c, + right: l + h, + bottom: c + d, + left: l, + x: l, + y: c + } + } + function Gt(t) { + var e = Ut(t) + , i = t.offsetWidth + , n = t.offsetHeight; + return Math.abs(e.width - i) <= 1 && (i = e.width), + Math.abs(e.height - n) <= 1 && (n = e.height), + { + x: t.offsetLeft, + y: t.offsetTop, + width: i, + height: n + } + } + function Jt(t, e) { + var i = e.getRootNode && e.getRootNode(); + if (t.contains(e)) + return !0; + if (i && zt(i)) { + var n = e; + do { + if (n && t.isSameNode(n)) + return !0; + n = n.parentNode || n.host + } while (n) + } + return !1 + } + function Zt(t) { + return $t(t).getComputedStyle(t) + } + function te(t) { + return ["table", "td", "th"].indexOf(Ht(t)) >= 0 + } + function ee(t) { + return ((Wt(t) ? t.ownerDocument : t.document) || window.document).documentElement + } + function ie(t) { + return "html" === Ht(t) ? t : t.assignedSlot || t.parentNode || (zt(t) ? t.host : null) || ee(t) + } + function ne(t) { + return Bt(t) && "fixed" !== Zt(t).position ? t.offsetParent : null + } + function se(t) { + for (var e = $t(t), i = ne(t); i && te(i) && "static" === Zt(i).position; ) + i = ne(i); + return i && ("html" === Ht(i) || "body" === Ht(i) && "static" === Zt(i).position) ? e : i || function(t) { + var e = /firefox/i.test(Xt()); + if (/Trident/i.test(Xt()) && Bt(t) && "fixed" === Zt(t).position) + return null; + var i = ie(t); + for (zt(i) && (i = i.host); Bt(i) && ["html", "body"].indexOf(Ht(i)) < 0; ) { + var n = Zt(i); + if ("none" !== n.transform || "none" !== n.perspective || "paint" === n.contain || -1 !== ["transform", "perspective"].indexOf(n.willChange) || e && "filter" === n.willChange || e && n.filter && "none" !== n.filter) + return i; + i = i.parentNode + } + return null + }(t) || e + } + function oe(t) { + return ["top", "bottom"].indexOf(t) >= 0 ? "x" : "y" + } + function re(t, e, i) { + return Vt(t, Kt(e, i)) + } + function ae(t) { + return Object.assign({}, { + top: 0, + right: 0, + bottom: 0, + left: 0 + }, t) + } + function le(t, e) { + return e.reduce((function(e, i) { + return e[i] = t, + e + } + ), {}) + } + const ce = { + name: "arrow", + enabled: !0, + phase: "main", + fn: function(t) { + var e, i = t.state, n = t.name, s = t.options, o = i.elements.arrow, r = i.modifiersData.popperOffsets, a = qt(i.placement), l = oe(a), c = [_t, gt].indexOf(a) >= 0 ? "height" : "width"; + if (o && r) { + var h = function(t, e) { + return ae("number" != typeof (t = "function" == typeof t ? t(Object.assign({}, e.rects, { + placement: e.placement + })) : t) ? t : le(t, vt)) + }(s.padding, i) + , d = Gt(o) + , u = "y" === l ? pt : _t + , f = "y" === l ? mt : gt + , p = i.rects.reference[c] + i.rects.reference[l] - r[l] - i.rects.popper[c] + , m = r[l] - i.rects.reference[l] + , g = se(o) + , _ = g ? "y" === l ? g.clientHeight || 0 : g.clientWidth || 0 : 0 + , b = p / 2 - m / 2 + , v = h[u] + , y = _ - d[c] - h[f] + , w = _ / 2 - d[c] / 2 + b + , A = re(v, w, y) + , E = l; + i.modifiersData[n] = ((e = {})[E] = A, + e.centerOffset = A - w, + e) + } + }, + effect: function(t) { + var e = t.state + , i = t.options.element + , n = void 0 === i ? "[data-popper-arrow]" : i; + null != n && ("string" != typeof n || (n = e.elements.popper.querySelector(n))) && Jt(e.elements.popper, n) && (e.elements.arrow = n) + }, + requires: ["popperOffsets"], + requiresIfExists: ["preventOverflow"] + }; + function he(t) { + return t.split("-")[1] + } + var de = { + top: "auto", + right: "auto", + bottom: "auto", + left: "auto" + }; + function ue(t) { + var e, i = t.popper, n = t.popperRect, s = t.placement, o = t.variation, r = t.offsets, a = t.position, l = t.gpuAcceleration, c = t.adaptive, h = t.roundOffsets, d = t.isFixed, u = r.x, f = void 0 === u ? 0 : u, p = r.y, m = void 0 === p ? 0 : p, g = "function" == typeof h ? h({ + x: f, + y: m + }) : { + x: f, + y: m + }; + f = g.x, + m = g.y; + var _ = r.hasOwnProperty("x") + , b = r.hasOwnProperty("y") + , v = _t + , y = pt + , w = window; + if (c) { + var A = se(i) + , E = "clientHeight" + , T = "clientWidth"; + A === $t(i) && "static" !== Zt(A = ee(i)).position && "absolute" === a && (E = "scrollHeight", + T = "scrollWidth"), + (s === pt || (s === _t || s === gt) && o === wt) && (y = mt, + m -= (d && A === w && w.visualViewport ? w.visualViewport.height : A[E]) - n.height, + m *= l ? 1 : -1), + s !== _t && (s !== pt && s !== mt || o !== wt) || (v = gt, + f -= (d && A === w && w.visualViewport ? w.visualViewport.width : A[T]) - n.width, + f *= l ? 1 : -1) + } + var C, O = Object.assign({ + position: a + }, c && de), x = !0 === h ? function(t) { + var e = t.x + , i = t.y + , n = window.devicePixelRatio || 1; + return { + x: Qt(e * n) / n || 0, + y: Qt(i * n) / n || 0 + } + }({ + x: f, + y: m + }) : { + x: f, + y: m + }; + return f = x.x, + m = x.y, + l ? Object.assign({}, O, ((C = {})[y] = b ? "0" : "", + C[v] = _ ? "0" : "", + C.transform = (w.devicePixelRatio || 1) <= 1 ? "translate(" + f + "px, " + m + "px)" : "translate3d(" + f + "px, " + m + "px, 0)", + C)) : Object.assign({}, O, ((e = {})[y] = b ? m + "px" : "", + e[v] = _ ? f + "px" : "", + e.transform = "", + e)) + } + const fe = { + name: "computeStyles", + enabled: !0, + phase: "beforeWrite", + fn: function(t) { + var e = t.state + , i = t.options + , n = i.gpuAcceleration + , s = void 0 === n || n + , o = i.adaptive + , r = void 0 === o || o + , a = i.roundOffsets + , l = void 0 === a || a + , c = { + placement: qt(e.placement), + variation: he(e.placement), + popper: e.elements.popper, + popperRect: e.rects.popper, + gpuAcceleration: s, + isFixed: "fixed" === e.options.strategy + }; + null != e.modifiersData.popperOffsets && (e.styles.popper = Object.assign({}, e.styles.popper, ue(Object.assign({}, c, { + offsets: e.modifiersData.popperOffsets, + position: e.options.strategy, + adaptive: r, + roundOffsets: l + })))), + null != e.modifiersData.arrow && (e.styles.arrow = Object.assign({}, e.styles.arrow, ue(Object.assign({}, c, { + offsets: e.modifiersData.arrow, + position: "absolute", + adaptive: !1, + roundOffsets: l + })))), + e.attributes.popper = Object.assign({}, e.attributes.popper, { + "data-popper-placement": e.placement + }) + }, + data: {} + }; + var pe = { + passive: !0 + }; + const me = { + name: "eventListeners", + enabled: !0, + phase: "write", + fn: function() {}, + effect: function(t) { + var e = t.state + , i = t.instance + , n = t.options + , s = n.scroll + , o = void 0 === s || s + , r = n.resize + , a = void 0 === r || r + , l = $t(e.elements.popper) + , c = [].concat(e.scrollParents.reference, e.scrollParents.popper); + return o && c.forEach((function(t) { + t.addEventListener("scroll", i.update, pe) + } + )), + a && l.addEventListener("resize", i.update, pe), + function() { + o && c.forEach((function(t) { + t.removeEventListener("scroll", i.update, pe) + } + )), + a && l.removeEventListener("resize", i.update, pe) + } + }, + data: {} + }; + var ge = { + left: "right", + right: "left", + bottom: "top", + top: "bottom" + }; + function _e(t) { + return t.replace(/left|right|bottom|top/g, (function(t) { + return ge[t] + } + )) + } + var be = { + start: "end", + end: "start" + }; + function ve(t) { + return t.replace(/start|end/g, (function(t) { + return be[t] + } + )) + } + function ye(t) { + var e = $t(t); + return { + scrollLeft: e.pageXOffset, + scrollTop: e.pageYOffset + } + } + function we(t) { + return Ut(ee(t)).left + ye(t).scrollLeft + } + function Ae(t) { + var e = Zt(t) + , i = e.overflow + , n = e.overflowX + , s = e.overflowY; + return /auto|scroll|overlay|hidden/.test(i + s + n) + } + function Ee(t) { + return ["html", "body", "#document"].indexOf(Ht(t)) >= 0 ? t.ownerDocument.body : Bt(t) && Ae(t) ? t : Ee(ie(t)) + } + function Te(t, e) { + var i; + void 0 === e && (e = []); + var n = Ee(t) + , s = n === (null == (i = t.ownerDocument) ? void 0 : i.body) + , o = $t(n) + , r = s ? [o].concat(o.visualViewport || [], Ae(n) ? n : []) : n + , a = e.concat(r); + return s ? a : a.concat(Te(ie(r))) + } + function Ce(t) { + return Object.assign({}, t, { + left: t.x, + top: t.y, + right: t.x + t.width, + bottom: t.y + t.height + }) + } + function Oe(t, e, i) { + return e === Et ? Ce(function(t, e) { + var i = $t(t) + , n = ee(t) + , s = i.visualViewport + , o = n.clientWidth + , r = n.clientHeight + , a = 0 + , l = 0; + if (s) { + o = s.width, + r = s.height; + var c = Yt(); + (c || !c && "fixed" === e) && (a = s.offsetLeft, + l = s.offsetTop) + } + return { + width: o, + height: r, + x: a + we(t), + y: l + } + }(t, i)) : Wt(e) ? function(t, e) { + var i = Ut(t, !1, "fixed" === e); + return i.top = i.top + t.clientTop, + i.left = i.left + t.clientLeft, + i.bottom = i.top + t.clientHeight, + i.right = i.left + t.clientWidth, + i.width = t.clientWidth, + i.height = t.clientHeight, + i.x = i.left, + i.y = i.top, + i + }(e, i) : Ce(function(t) { + var e, i = ee(t), n = ye(t), s = null == (e = t.ownerDocument) ? void 0 : e.body, o = Vt(i.scrollWidth, i.clientWidth, s ? s.scrollWidth : 0, s ? s.clientWidth : 0), r = Vt(i.scrollHeight, i.clientHeight, s ? s.scrollHeight : 0, s ? s.clientHeight : 0), a = -n.scrollLeft + we(t), l = -n.scrollTop; + return "rtl" === Zt(s || i).direction && (a += Vt(i.clientWidth, s ? s.clientWidth : 0) - o), + { + width: o, + height: r, + x: a, + y: l + } + }(ee(t))) + } + function xe(t) { + var e, i = t.reference, n = t.element, s = t.placement, o = s ? qt(s) : null, r = s ? he(s) : null, a = i.x + i.width / 2 - n.width / 2, l = i.y + i.height / 2 - n.height / 2; + switch (o) { + case pt: + e = { + x: a, + y: i.y - n.height + }; + break; + case mt: + e = { + x: a, + y: i.y + i.height + }; + break; + case gt: + e = { + x: i.x + i.width, + y: l + }; + break; + case _t: + e = { + x: i.x - n.width, + y: l + }; + break; + default: + e = { + x: i.x, + y: i.y + } + } + var c = o ? oe(o) : null; + if (null != c) { + var h = "y" === c ? "height" : "width"; + switch (r) { + case yt: + e[c] = e[c] - (i[h] / 2 - n[h] / 2); + break; + case wt: + e[c] = e[c] + (i[h] / 2 - n[h] / 2) + } + } + return e + } + function ke(t, e) { + void 0 === e && (e = {}); + var i = e + , n = i.placement + , s = void 0 === n ? t.placement : n + , o = i.strategy + , r = void 0 === o ? t.strategy : o + , a = i.boundary + , l = void 0 === a ? At : a + , c = i.rootBoundary + , h = void 0 === c ? Et : c + , d = i.elementContext + , u = void 0 === d ? Tt : d + , f = i.altBoundary + , p = void 0 !== f && f + , m = i.padding + , g = void 0 === m ? 0 : m + , _ = ae("number" != typeof g ? g : le(g, vt)) + , b = u === Tt ? Ct : Tt + , v = t.rects.popper + , y = t.elements[p ? b : u] + , w = function(t, e, i, n) { + var s = "clippingParents" === e ? function(t) { + var e = Te(ie(t)) + , i = ["absolute", "fixed"].indexOf(Zt(t).position) >= 0 && Bt(t) ? se(t) : t; + return Wt(i) ? e.filter((function(t) { + return Wt(t) && Jt(t, i) && "body" !== Ht(t) + } + )) : [] + }(t) : [].concat(e) + , o = [].concat(s, [i]) + , r = o[0] + , a = o.reduce((function(e, i) { + var s = Oe(t, i, n); + return e.top = Vt(s.top, e.top), + e.right = Kt(s.right, e.right), + e.bottom = Kt(s.bottom, e.bottom), + e.left = Vt(s.left, e.left), + e + } + ), Oe(t, r, n)); + return a.width = a.right - a.left, + a.height = a.bottom - a.top, + a.x = a.left, + a.y = a.top, + a + }(Wt(y) ? y : y.contextElement || ee(t.elements.popper), l, h, r) + , A = Ut(t.elements.reference) + , E = xe({ + reference: A, + element: v, + strategy: "absolute", + placement: s + }) + , T = Ce(Object.assign({}, v, E)) + , C = u === Tt ? T : A + , O = { + top: w.top - C.top + _.top, + bottom: C.bottom - w.bottom + _.bottom, + left: w.left - C.left + _.left, + right: C.right - w.right + _.right + } + , x = t.modifiersData.offset; + if (u === Tt && x) { + var k = x[s]; + Object.keys(O).forEach((function(t) { + var e = [gt, mt].indexOf(t) >= 0 ? 1 : -1 + , i = [pt, mt].indexOf(t) >= 0 ? "y" : "x"; + O[t] += k[i] * e + } + )) + } + return O + } + function Le(t, e) { + void 0 === e && (e = {}); + var i = e + , n = i.placement + , s = i.boundary + , o = i.rootBoundary + , r = i.padding + , a = i.flipVariations + , l = i.allowedAutoPlacements + , c = void 0 === l ? xt : l + , h = he(n) + , d = h ? a ? Ot : Ot.filter((function(t) { + return he(t) === h + } + )) : vt + , u = d.filter((function(t) { + return c.indexOf(t) >= 0 + } + )); + 0 === u.length && (u = d); + var f = u.reduce((function(e, i) { + return e[i] = ke(t, { + placement: i, + boundary: s, + rootBoundary: o, + padding: r + })[qt(i)], + e + } + ), {}); + return Object.keys(f).sort((function(t, e) { + return f[t] - f[e] + } + )) + } + const Se = { + name: "flip", + enabled: !0, + phase: "main", + fn: function(t) { + var e = t.state + , i = t.options + , n = t.name; + if (!e.modifiersData[n]._skip) { + for (var s = i.mainAxis, o = void 0 === s || s, r = i.altAxis, a = void 0 === r || r, l = i.fallbackPlacements, c = i.padding, h = i.boundary, d = i.rootBoundary, u = i.altBoundary, f = i.flipVariations, p = void 0 === f || f, m = i.allowedAutoPlacements, g = e.options.placement, _ = qt(g), b = l || (_ !== g && p ? function(t) { + if (qt(t) === bt) + return []; + var e = _e(t); + return [ve(t), e, ve(e)] + }(g) : [_e(g)]), v = [g].concat(b).reduce((function(t, i) { + return t.concat(qt(i) === bt ? Le(e, { + placement: i, + boundary: h, + rootBoundary: d, + padding: c, + flipVariations: p, + allowedAutoPlacements: m + }) : i) + } + ), []), y = e.rects.reference, w = e.rects.popper, A = new Map, E = !0, T = v[0], C = 0; C < v.length; C++) { + var O = v[C] + , x = qt(O) + , k = he(O) === yt + , L = [pt, mt].indexOf(x) >= 0 + , S = L ? "width" : "height" + , D = ke(e, { + placement: O, + boundary: h, + rootBoundary: d, + altBoundary: u, + padding: c + }) + , I = L ? k ? gt : _t : k ? mt : pt; + y[S] > w[S] && (I = _e(I)); + var N = _e(I) + , P = []; + if (o && P.push(D[x] <= 0), + a && P.push(D[I] <= 0, D[N] <= 0), + P.every((function(t) { + return t + } + ))) { + T = O, + E = !1; + break + } + A.set(O, P) + } + if (E) + for (var j = function(t) { + var e = v.find((function(e) { + var i = A.get(e); + if (i) + return i.slice(0, t).every((function(t) { + return t + } + )) + } + )); + if (e) + return T = e, + "break" + }, M = p ? 3 : 1; M > 0 && "break" !== j(M); M--) + ; + e.placement !== T && (e.modifiersData[n]._skip = !0, + e.placement = T, + e.reset = !0) + } + }, + requiresIfExists: ["offset"], + data: { + _skip: !1 + } + }; + function De(t, e, i) { + return void 0 === i && (i = { + x: 0, + y: 0 + }), + { + top: t.top - e.height - i.y, + right: t.right - e.width + i.x, + bottom: t.bottom - e.height + i.y, + left: t.left - e.width - i.x + } + } + function Ie(t) { + return [pt, gt, mt, _t].some((function(e) { + return t[e] >= 0 + } + )) + } + const Ne = { + name: "hide", + enabled: !0, + phase: "main", + requiresIfExists: ["preventOverflow"], + fn: function(t) { + var e = t.state + , i = t.name + , n = e.rects.reference + , s = e.rects.popper + , o = e.modifiersData.preventOverflow + , r = ke(e, { + elementContext: "reference" + }) + , a = ke(e, { + altBoundary: !0 + }) + , l = De(r, n) + , c = De(a, s, o) + , h = Ie(l) + , d = Ie(c); + e.modifiersData[i] = { + referenceClippingOffsets: l, + popperEscapeOffsets: c, + isReferenceHidden: h, + hasPopperEscaped: d + }, + e.attributes.popper = Object.assign({}, e.attributes.popper, { + "data-popper-reference-hidden": h, + "data-popper-escaped": d + }) + } + } + , Pe = { + name: "offset", + enabled: !0, + phase: "main", + requires: ["popperOffsets"], + fn: function(t) { + var e = t.state + , i = t.options + , n = t.name + , s = i.offset + , o = void 0 === s ? [0, 0] : s + , r = xt.reduce((function(t, i) { + return t[i] = function(t, e, i) { + var n = qt(t) + , s = [_t, pt].indexOf(n) >= 0 ? -1 : 1 + , o = "function" == typeof i ? i(Object.assign({}, e, { + placement: t + })) : i + , r = o[0] + , a = o[1]; + return r = r || 0, + a = (a || 0) * s, + [_t, gt].indexOf(n) >= 0 ? { + x: a, + y: r + } : { + x: r, + y: a + } + }(i, e.rects, o), + t + } + ), {}) + , a = r[e.placement] + , l = a.x + , c = a.y; + null != e.modifiersData.popperOffsets && (e.modifiersData.popperOffsets.x += l, + e.modifiersData.popperOffsets.y += c), + e.modifiersData[n] = r + } + } + , je = { + name: "popperOffsets", + enabled: !0, + phase: "read", + fn: function(t) { + var e = t.state + , i = t.name; + e.modifiersData[i] = xe({ + reference: e.rects.reference, + element: e.rects.popper, + strategy: "absolute", + placement: e.placement + }) + }, + data: {} + } + , Me = { + name: "preventOverflow", + enabled: !0, + phase: "main", + fn: function(t) { + var e = t.state + , i = t.options + , n = t.name + , s = i.mainAxis + , o = void 0 === s || s + , r = i.altAxis + , a = void 0 !== r && r + , l = i.boundary + , c = i.rootBoundary + , h = i.altBoundary + , d = i.padding + , u = i.tether + , f = void 0 === u || u + , p = i.tetherOffset + , m = void 0 === p ? 0 : p + , g = ke(e, { + boundary: l, + rootBoundary: c, + padding: d, + altBoundary: h + }) + , _ = qt(e.placement) + , b = he(e.placement) + , v = !b + , y = oe(_) + , w = "x" === y ? "y" : "x" + , A = e.modifiersData.popperOffsets + , E = e.rects.reference + , T = e.rects.popper + , C = "function" == typeof m ? m(Object.assign({}, e.rects, { + placement: e.placement + })) : m + , O = "number" == typeof C ? { + mainAxis: C, + altAxis: C + } : Object.assign({ + mainAxis: 0, + altAxis: 0 + }, C) + , x = e.modifiersData.offset ? e.modifiersData.offset[e.placement] : null + , k = { + x: 0, + y: 0 + }; + if (A) { + if (o) { + var L, S = "y" === y ? pt : _t, D = "y" === y ? mt : gt, I = "y" === y ? "height" : "width", N = A[y], P = N + g[S], j = N - g[D], M = f ? -T[I] / 2 : 0, F = b === yt ? E[I] : T[I], H = b === yt ? -T[I] : -E[I], $ = e.elements.arrow, W = f && $ ? Gt($) : { + width: 0, + height: 0 + }, B = e.modifiersData["arrow#persistent"] ? e.modifiersData["arrow#persistent"].padding : { + top: 0, + right: 0, + bottom: 0, + left: 0 + }, z = B[S], R = B[D], q = re(0, E[I], W[I]), V = v ? E[I] / 2 - M - q - z - O.mainAxis : F - q - z - O.mainAxis, K = v ? -E[I] / 2 + M + q + R + O.mainAxis : H + q + R + O.mainAxis, Q = e.elements.arrow && se(e.elements.arrow), X = Q ? "y" === y ? Q.clientTop || 0 : Q.clientLeft || 0 : 0, Y = null != (L = null == x ? void 0 : x[y]) ? L : 0, U = N + K - Y, G = re(f ? Kt(P, N + V - Y - X) : P, N, f ? Vt(j, U) : j); + A[y] = G, + k[y] = G - N + } + if (a) { + var J, Z = "x" === y ? pt : _t, tt = "x" === y ? mt : gt, et = A[w], it = "y" === w ? "height" : "width", nt = et + g[Z], st = et - g[tt], ot = -1 !== [pt, _t].indexOf(_), rt = null != (J = null == x ? void 0 : x[w]) ? J : 0, at = ot ? nt : et - E[it] - T[it] - rt + O.altAxis, lt = ot ? et + E[it] + T[it] - rt - O.altAxis : st, ct = f && ot ? function(t, e, i) { + var n = re(t, e, i); + return n > i ? i : n + }(at, et, lt) : re(f ? at : nt, et, f ? lt : st); + A[w] = ct, + k[w] = ct - et + } + e.modifiersData[n] = k + } + }, + requiresIfExists: ["offset"] + }; + function Fe(t, e, i) { + void 0 === i && (i = !1); + var n, s, o = Bt(e), r = Bt(e) && function(t) { + var e = t.getBoundingClientRect() + , i = Qt(e.width) / t.offsetWidth || 1 + , n = Qt(e.height) / t.offsetHeight || 1; + return 1 !== i || 1 !== n + }(e), a = ee(e), l = Ut(t, r, i), c = { + scrollLeft: 0, + scrollTop: 0 + }, h = { + x: 0, + y: 0 + }; + return (o || !o && !i) && (("body" !== Ht(e) || Ae(a)) && (c = (n = e) !== $t(n) && Bt(n) ? { + scrollLeft: (s = n).scrollLeft, + scrollTop: s.scrollTop + } : ye(n)), + Bt(e) ? ((h = Ut(e, !0)).x += e.clientLeft, + h.y += e.clientTop) : a && (h.x = we(a))), + { + x: l.left + c.scrollLeft - h.x, + y: l.top + c.scrollTop - h.y, + width: l.width, + height: l.height + } + } + function He(t) { + var e = new Map + , i = new Set + , n = []; + function s(t) { + i.add(t.name), + [].concat(t.requires || [], t.requiresIfExists || []).forEach((function(t) { + if (!i.has(t)) { + var n = e.get(t); + n && s(n) + } + } + )), + n.push(t) + } + return t.forEach((function(t) { + e.set(t.name, t) + } + )), + t.forEach((function(t) { + i.has(t.name) || s(t) + } + )), + n + } + var $e = { + placement: "bottom", + modifiers: [], + strategy: "absolute" + }; + function We() { + for (var t = arguments.length, e = new Array(t), i = 0; i < t; i++) + e[i] = arguments[i]; + return !e.some((function(t) { + return !(t && "function" == typeof t.getBoundingClientRect) + } + )) + } + function Be(t) { + void 0 === t && (t = {}); + var e = t + , i = e.defaultModifiers + , n = void 0 === i ? [] : i + , s = e.defaultOptions + , o = void 0 === s ? $e : s; + return function(t, e, i) { + void 0 === i && (i = o); + var s, r, a = { + placement: "bottom", + orderedModifiers: [], + options: Object.assign({}, $e, o), + modifiersData: {}, + elements: { + reference: t, + popper: e + }, + attributes: {}, + styles: {} + }, l = [], c = !1, h = { + state: a, + setOptions: function(i) { + var s = "function" == typeof i ? i(a.options) : i; + d(), + a.options = Object.assign({}, o, a.options, s), + a.scrollParents = { + reference: Wt(t) ? Te(t) : t.contextElement ? Te(t.contextElement) : [], + popper: Te(e) + }; + var r, c, u = function(t) { + var e = He(t); + return Ft.reduce((function(t, i) { + return t.concat(e.filter((function(t) { + return t.phase === i + } + ))) + } + ), []) + }((r = [].concat(n, a.options.modifiers), + c = r.reduce((function(t, e) { + var i = t[e.name]; + return t[e.name] = i ? Object.assign({}, i, e, { + options: Object.assign({}, i.options, e.options), + data: Object.assign({}, i.data, e.data) + }) : e, + t + } + ), {}), + Object.keys(c).map((function(t) { + return c[t] + } + )))); + return a.orderedModifiers = u.filter((function(t) { + return t.enabled + } + )), + a.orderedModifiers.forEach((function(t) { + var e = t.name + , i = t.options + , n = void 0 === i ? {} : i + , s = t.effect; + if ("function" == typeof s) { + var o = s({ + state: a, + name: e, + instance: h, + options: n + }); + l.push(o || function() {} + ) + } + } + )), + h.update() + }, + forceUpdate: function() { + if (!c) { + var t = a.elements + , e = t.reference + , i = t.popper; + if (We(e, i)) { + a.rects = { + reference: Fe(e, se(i), "fixed" === a.options.strategy), + popper: Gt(i) + }, + a.reset = !1, + a.placement = a.options.placement, + a.orderedModifiers.forEach((function(t) { + return a.modifiersData[t.name] = Object.assign({}, t.data) + } + )); + for (var n = 0; n < a.orderedModifiers.length; n++) + if (!0 !== a.reset) { + var s = a.orderedModifiers[n] + , o = s.fn + , r = s.options + , l = void 0 === r ? {} : r + , d = s.name; + "function" == typeof o && (a = o({ + state: a, + options: l, + name: d, + instance: h + }) || a) + } else + a.reset = !1, + n = -1 + } + } + }, + update: (s = function() { + return new Promise((function(t) { + h.forceUpdate(), + t(a) + } + )) + } + , + function() { + return r || (r = new Promise((function(t) { + Promise.resolve().then((function() { + r = void 0, + t(s()) + } + )) + } + ))), + r + } + ), + destroy: function() { + d(), + c = !0 + } + }; + if (!We(t, e)) + return h; + function d() { + l.forEach((function(t) { + return t() + } + )), + l = [] + } + return h.setOptions(i).then((function(t) { + !c && i.onFirstUpdate && i.onFirstUpdate(t) + } + )), + h + } + } + var ze = Be() + , Re = Be({ + defaultModifiers: [me, je, fe, Rt] + }) + , qe = Be({ + defaultModifiers: [me, je, fe, Rt, Pe, Se, Me, ce, Ne] + }); + const Ve = Object.freeze(Object.defineProperty({ + __proto__: null, + popperGenerator: Be, + detectOverflow: ke, + createPopperBase: ze, + createPopper: qe, + createPopperLite: Re, + top: pt, + bottom: mt, + right: gt, + left: _t, + auto: bt, + basePlacements: vt, + start: yt, + end: wt, + clippingParents: At, + viewport: Et, + popper: Tt, + reference: Ct, + variationPlacements: Ot, + placements: xt, + beforeRead: kt, + read: Lt, + afterRead: St, + beforeMain: Dt, + main: It, + afterMain: Nt, + beforeWrite: Pt, + write: jt, + afterWrite: Mt, + modifierPhases: Ft, + applyStyles: Rt, + arrow: ce, + computeStyles: fe, + eventListeners: me, + flip: Se, + hide: Ne, + offset: Pe, + popperOffsets: je, + preventOverflow: Me + }, Symbol.toStringTag, { + value: "Module" + })) + , Ke = "dropdown" + , Qe = "ArrowUp" + , Xe = "ArrowDown" + , Ye = "click.bs.dropdown.data-api" + , Ue = "keydown.bs.dropdown.data-api" + , Ge = "show" + , Je = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)' + , Ze = `${Je}.show` + , ti = ".dropdown-menu" + , ei = u() ? "top-end" : "top-start" + , ii = u() ? "top-start" : "top-end" + , ni = u() ? "bottom-end" : "bottom-start" + , si = u() ? "bottom-start" : "bottom-end" + , oi = u() ? "left-start" : "right-start" + , ri = u() ? "right-start" : "left-start" + , ai = { + autoClose: !0, + boundary: "clippingParents", + display: "dynamic", + offset: [0, 2], + popperConfig: null, + reference: "toggle" + } + , li = { + autoClose: "(boolean|string)", + boundary: "(string|element)", + display: "string", + offset: "(array|string|function)", + popperConfig: "(null|object|function)", + reference: "(string|element|object)" + }; + class ci extends W { + constructor(t, e) { + super(t, e), + this._popper = null, + this._parent = this._element.parentNode, + this._menu = z.next(this._element, ti)[0] || z.prev(this._element, ti)[0] || z.findOne(ti, this._parent), + this._inNavbar = this._detectNavbar() + } + static get Default() { + return ai + } + static get DefaultType() { + return li + } + static get NAME() { + return Ke + } + toggle() { + return this._isShown() ? this.hide() : this.show() + } + show() { + if (r(this._element) || this._isShown()) + return; + const t = { + relatedTarget: this._element + }; + if (!I.trigger(this._element, "show.bs.dropdown", t).defaultPrevented) { + if (this._createPopper(), + "ontouchstart"in document.documentElement && !this._parent.closest(".navbar-nav")) + for (const t of [].concat(...document.body.children)) + I.on(t, "mouseover", l); + this._element.focus(), + this._element.setAttribute("aria-expanded", !0), + this._menu.classList.add(Ge), + this._element.classList.add(Ge), + I.trigger(this._element, "shown.bs.dropdown", t) + } + } + hide() { + if (r(this._element) || !this._isShown()) + return; + const t = { + relatedTarget: this._element + }; + this._completeHide(t) + } + dispose() { + this._popper && this._popper.destroy(), + super.dispose() + } + update() { + this._inNavbar = this._detectNavbar(), + this._popper && this._popper.update() + } + _completeHide(t) { + if (!I.trigger(this._element, "hide.bs.dropdown", t).defaultPrevented) { + if ("ontouchstart"in document.documentElement) + for (const t of [].concat(...document.body.children)) + I.off(t, "mouseover", l); + this._popper && this._popper.destroy(), + this._menu.classList.remove(Ge), + this._element.classList.remove(Ge), + this._element.setAttribute("aria-expanded", "false"), + H.removeDataAttribute(this._menu, "popper"), + I.trigger(this._element, "hidden.bs.dropdown", t) + } + } + _getConfig(t) { + if ("object" == typeof (t = super._getConfig(t)).reference && !n(t.reference) && "function" != typeof t.reference.getBoundingClientRect) + throw new TypeError(`${Ke.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`); + return t + } + _createPopper() { + if (void 0 === Ve) + throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)"); + let t = this._element; + "parent" === this._config.reference ? t = this._parent : n(this._config.reference) ? t = s(this._config.reference) : "object" == typeof this._config.reference && (t = this._config.reference); + const e = this._getPopperConfig(); + this._popper = qe(t, this._menu, e) + } + _isShown() { + return this._menu.classList.contains(Ge) + } + _getPlacement() { + const t = this._parent; + if (t.classList.contains("dropend")) + return oi; + if (t.classList.contains("dropstart")) + return ri; + if (t.classList.contains("dropup-center")) + return "top"; + if (t.classList.contains("dropdown-center")) + return "bottom"; + const e = "end" === getComputedStyle(this._menu).getPropertyValue("--bs-position").trim(); + return t.classList.contains("dropup") ? e ? ii : ei : e ? si : ni + } + _detectNavbar() { + return null !== this._element.closest(".navbar") + } + _getOffset() { + const {offset: t} = this._config; + return "string" == typeof t ? t.split(",").map((t => Number.parseInt(t, 10))) : "function" == typeof t ? e => t(e, this._element) : t + } + _getPopperConfig() { + const t = { + placement: this._getPlacement(), + modifiers: [{ + name: "preventOverflow", + options: { + boundary: this._config.boundary + } + }, { + name: "offset", + options: { + offset: this._getOffset() + } + }] + }; + return (this._inNavbar || "static" === this._config.display) && (H.setDataAttribute(this._menu, "popper", "static"), + t.modifiers = [{ + name: "applyStyles", + enabled: !1 + }]), + { + ...t, + ...p(this._config.popperConfig, [t]) + } + } + _selectMenuItem({key: t, target: e}) { + const i = z.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)", this._menu).filter((t => o(t))); + i.length && g(i, e, t === Xe, !i.includes(e)).focus() + } + static jQueryInterface(t) { + return this.each((function() { + const e = ci.getOrCreateInstance(this, t); + if ("string" == typeof t) { + if (void 0 === e[t]) + throw new TypeError(`No method named "${t}"`); + e[t]() + } + } + )) + } + static clearMenus(t) { + if (2 === t.button || "keyup" === t.type && "Tab" !== t.key) + return; + const e = z.find(Ze); + for (const i of e) { + const e = ci.getInstance(i); + if (!e || !1 === e._config.autoClose) + continue; + const n = t.composedPath() + , s = n.includes(e._menu); + if (n.includes(e._element) || "inside" === e._config.autoClose && !s || "outside" === e._config.autoClose && s) + continue; + if (e._menu.contains(t.target) && ("keyup" === t.type && "Tab" === t.key || /input|select|option|textarea|form/i.test(t.target.tagName))) + continue; + const o = { + relatedTarget: e._element + }; + "click" === t.type && (o.clickEvent = t), + e._completeHide(o) + } + } + static dataApiKeydownHandler(t) { + const e = /input|textarea/i.test(t.target.tagName) + , i = "Escape" === t.key + , n = [Qe, Xe].includes(t.key); + if (!n && !i) + return; + if (e && !i) + return; + t.preventDefault(); + const s = this.matches(Je) ? this : z.prev(this, Je)[0] || z.next(this, Je)[0] || z.findOne(Je, t.delegateTarget.parentNode) + , o = ci.getOrCreateInstance(s); + if (n) + return t.stopPropagation(), + o.show(), + void o._selectMenuItem(t); + o._isShown() && (t.stopPropagation(), + o.hide(), + s.focus()) + } + } + I.on(document, Ue, Je, ci.dataApiKeydownHandler), + I.on(document, Ue, ti, ci.dataApiKeydownHandler), + I.on(document, Ye, ci.clearMenus), + I.on(document, "keyup.bs.dropdown.data-api", ci.clearMenus), + I.on(document, Ye, Je, (function(t) { + t.preventDefault(), + ci.getOrCreateInstance(this).toggle() + } + )), + f(ci); + const hi = ".fixed-top, .fixed-bottom, .is-fixed, .sticky-top" + , di = ".sticky-top" + , ui = "padding-right" + , fi = "margin-right"; + class pi { + constructor() { + this._element = document.body + } + getWidth() { + const t = document.documentElement.clientWidth; + return Math.abs(window.innerWidth - t) + } + hide() { + const t = this.getWidth(); + this._disableOverFlow(), + this._setElementAttributes(this._element, ui, (e => e + t)), + this._setElementAttributes(hi, ui, (e => e + t)), + this._setElementAttributes(di, fi, (e => e - t)) + } + reset() { + this._resetElementAttributes(this._element, "overflow"), + this._resetElementAttributes(this._element, ui), + this._resetElementAttributes(hi, ui), + this._resetElementAttributes(di, fi) + } + isOverflowing() { + return this.getWidth() > 0 + } + _disableOverFlow() { + this._saveInitialAttribute(this._element, "overflow"), + this._element.style.overflow = "hidden" + } + _setElementAttributes(t, e, i) { + const n = this.getWidth(); + this._applyManipulationCallback(t, (t => { + if (t !== this._element && window.innerWidth > t.clientWidth + n) + return; + this._saveInitialAttribute(t, e); + const s = window.getComputedStyle(t).getPropertyValue(e); + t.style.setProperty(e, `${i(Number.parseFloat(s))}px`) + } + )) + } + _saveInitialAttribute(t, e) { + const i = t.style.getPropertyValue(e); + i && H.setDataAttribute(t, e, i) + } + _resetElementAttributes(t, e) { + this._applyManipulationCallback(t, (t => { + const i = H.getDataAttribute(t, e); + null !== i ? (H.removeDataAttribute(t, e), + t.style.setProperty(e, i)) : t.style.removeProperty(e) + } + )) + } + _applyManipulationCallback(t, e) { + if (n(t)) + e(t); + else + for (const i of z.find(t, this._element)) + e(i) + } + } + const mi = "show" + , gi = "mousedown.bs.backdrop" + , _i = { + className: "modal-backdrop", + clickCallback: null, + isAnimated: !1, + isVisible: !0, + rootElement: "body" + } + , bi = { + className: "string", + clickCallback: "(function|null)", + isAnimated: "boolean", + isVisible: "boolean", + rootElement: "(element|string)" + }; + class vi extends $ { + constructor(t) { + super(), + this._config = this._getConfig(t), + this._isAppended = !1, + this._element = null + } + static get Default() { + return _i + } + static get DefaultType() { + return bi + } + static get NAME() { + return "backdrop" + } + show(t) { + if (!this._config.isVisible) + return void p(t); + this._append(); + const e = this._getElement(); + this._config.isAnimated && c(e), + e.classList.add(mi), + this._emulateAnimation(( () => { + p(t) + } + )) + } + hide(t) { + this._config.isVisible ? (this._getElement().classList.remove(mi), + this._emulateAnimation(( () => { + this.dispose(), + p(t) + } + ))) : p(t) + } + dispose() { + this._isAppended && (I.off(this._element, gi), + this._element.remove(), + this._isAppended = !1) + } + _getElement() { + if (!this._element) { + const t = document.createElement("div"); + t.className = this._config.className, + this._config.isAnimated && t.classList.add("fade"), + this._element = t + } + return this._element + } + _configAfterMerge(t) { + return t.rootElement = s(t.rootElement), + t + } + _append() { + if (this._isAppended) + return; + const t = this._getElement(); + this._config.rootElement.append(t), + I.on(t, gi, ( () => { + p(this._config.clickCallback) + } + )), + this._isAppended = !0 + } + _emulateAnimation(t) { + m(t, this._getElement(), this._config.isAnimated) + } + } + const yi = ".bs.focustrap" + , wi = "backward" + , Ai = { + autofocus: !0, + trapElement: null + } + , Ei = { + autofocus: "boolean", + trapElement: "element" + }; + class Ti extends $ { + constructor(t) { + super(), + this._config = this._getConfig(t), + this._isActive = !1, + this._lastTabNavDirection = null + } + static get Default() { + return Ai + } + static get DefaultType() { + return Ei + } + static get NAME() { + return "focustrap" + } + activate() { + this._isActive || (this._config.autofocus && this._config.trapElement.focus(), + I.off(document, yi), + I.on(document, "focusin.bs.focustrap", (t => this._handleFocusin(t))), + I.on(document, "keydown.tab.bs.focustrap", (t => this._handleKeydown(t))), + this._isActive = !0) + } + deactivate() { + this._isActive && (this._isActive = !1, + I.off(document, yi)) + } + _handleFocusin(t) { + const {trapElement: e} = this._config; + if (t.target === document || t.target === e || e.contains(t.target)) + return; + const i = z.focusableChildren(e); + 0 === i.length ? e.focus() : this._lastTabNavDirection === wi ? i[i.length - 1].focus() : i[0].focus() + } + _handleKeydown(t) { + "Tab" === t.key && (this._lastTabNavDirection = t.shiftKey ? wi : "forward") + } + } + const Ci = "hidden.bs.modal" + , Oi = "show.bs.modal" + , xi = "modal-open" + , ki = "show" + , Li = "modal-static" + , Si = { + backdrop: !0, + focus: !0, + keyboard: !0 + } + , Di = { + backdrop: "(boolean|string)", + focus: "boolean", + keyboard: "boolean" + }; + class Ii extends W { + constructor(t, e) { + super(t, e), + this._dialog = z.findOne(".modal-dialog", this._element), + this._backdrop = this._initializeBackDrop(), + this._focustrap = this._initializeFocusTrap(), + this._isShown = !1, + this._isTransitioning = !1, + this._scrollBar = new pi, + this._addEventListeners() + } + static get Default() { + return Si + } + static get DefaultType() { + return Di + } + static get NAME() { + return "modal" + } + toggle(t) { + return this._isShown ? this.hide() : this.show(t) + } + show(t) { + this._isShown || this._isTransitioning || I.trigger(this._element, Oi, { + relatedTarget: t + }).defaultPrevented || (this._isShown = !0, + this._isTransitioning = !0, + this._scrollBar.hide(), + document.body.classList.add(xi), + this._adjustDialog(), + this._backdrop.show(( () => this._showElement(t)))) + } + hide() { + this._isShown && !this._isTransitioning && (I.trigger(this._element, "hide.bs.modal").defaultPrevented || (this._isShown = !1, + this._isTransitioning = !0, + this._focustrap.deactivate(), + this._element.classList.remove(ki), + this._queueCallback(( () => this._hideModal()), this._element, this._isAnimated()))) + } + dispose() { + for (const t of [window, this._dialog]) + I.off(t, ".bs.modal"); + this._backdrop.dispose(), + this._focustrap.deactivate(), + super.dispose() + } + handleUpdate() { + this._adjustDialog() + } + _initializeBackDrop() { + return new vi({ + isVisible: Boolean(this._config.backdrop), + isAnimated: this._isAnimated() + }) + } + _initializeFocusTrap() { + return new Ti({ + trapElement: this._element + }) + } + _showElement(t) { + 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 e = z.findOne(".modal-body", this._dialog); + e && (e.scrollTop = 0), + c(this._element), + this._element.classList.add(ki), + this._queueCallback(( () => { + this._config.focus && this._focustrap.activate(), + this._isTransitioning = !1, + I.trigger(this._element, "shown.bs.modal", { + relatedTarget: t + }) + } + ), this._dialog, this._isAnimated()) + } + _addEventListeners() { + I.on(this._element, "keydown.dismiss.bs.modal", (t => { + if ("Escape" === t.key) + return this._config.keyboard ? (t.preventDefault(), + void this.hide()) : void this._triggerBackdropTransition() + } + )), + I.on(window, "resize.bs.modal", ( () => { + this._isShown && !this._isTransitioning && this._adjustDialog() + } + )), + I.on(this._element, "mousedown.dismiss.bs.modal", (t => { + I.one(this._element, "click.dismiss.bs.modal", (e => { + this._element === t.target && this._element === e.target && ("static" !== this._config.backdrop ? 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(xi), + this._resetAdjustments(), + this._scrollBar.reset(), + I.trigger(this._element, Ci) + } + )) + } + _isAnimated() { + return this._element.classList.contains("fade") + } + _triggerBackdropTransition() { + if (I.trigger(this._element, "hidePrevented.bs.modal").defaultPrevented) + return; + const t = this._element.scrollHeight > document.documentElement.clientHeight + , e = this._element.style.overflowY; + "hidden" === e || this._element.classList.contains(Li) || (t || (this._element.style.overflowY = "hidden"), + this._element.classList.add(Li), + this._queueCallback(( () => { + this._element.classList.remove(Li), + this._queueCallback(( () => { + this._element.style.overflowY = e + } + ), this._dialog) + } + ), this._dialog), + this._element.focus()) + } + _adjustDialog() { + const t = this._element.scrollHeight > document.documentElement.clientHeight + , e = this._scrollBar.getWidth() + , i = e > 0; + if (i && !t) { + const t = u() ? "paddingLeft" : "paddingRight"; + this._element.style[t] = `${e}px` + } + if (!i && t) { + const t = u() ? "paddingRight" : "paddingLeft"; + this._element.style[t] = `${e}px` + } + } + _resetAdjustments() { + this._element.style.paddingLeft = "", + this._element.style.paddingRight = "" + } + static jQueryInterface(t, e) { + return this.each((function() { + const i = Ii.getOrCreateInstance(this, t); + if ("string" == typeof t) { + if (void 0 === i[t]) + throw new TypeError(`No method named "${t}"`); + i[t](e) + } + } + )) + } + } + I.on(document, "click.bs.modal.data-api", '[data-bs-toggle="modal"]', (function(t) { + const e = z.getElementFromSelector(this); + ["A", "AREA"].includes(this.tagName) && t.preventDefault(), + I.one(e, Oi, (t => { + t.defaultPrevented || I.one(e, Ci, ( () => { + o(this) && this.focus() + } + )) + } + )); + const i = z.findOne(".modal.show"); + i && Ii.getInstance(i).hide(), + Ii.getOrCreateInstance(e).toggle(this) + } + )), + R(Ii), + f(Ii); + const Ni = "show" + , Pi = "showing" + , ji = "hiding" + , Mi = ".offcanvas.show" + , Fi = "hidePrevented.bs.offcanvas" + , Hi = "hidden.bs.offcanvas" + , $i = { + backdrop: !0, + keyboard: !0, + scroll: !1 + } + , Wi = { + backdrop: "(boolean|string)", + keyboard: "boolean", + scroll: "boolean" + }; + class Bi extends W { + constructor(t, e) { + super(t, e), + this._isShown = !1, + this._backdrop = this._initializeBackDrop(), + this._focustrap = this._initializeFocusTrap(), + this._addEventListeners() + } + static get Default() { + return $i + } + static get DefaultType() { + return Wi + } + static get NAME() { + return "offcanvas" + } + toggle(t) { + return this._isShown ? this.hide() : this.show(t) + } + show(t) { + this._isShown || I.trigger(this._element, "show.bs.offcanvas", { + relatedTarget: t + }).defaultPrevented || (this._isShown = !0, + this._backdrop.show(), + this._config.scroll || (new pi).hide(), + this._element.setAttribute("aria-modal", !0), + this._element.setAttribute("role", "dialog"), + this._element.classList.add(Pi), + this._queueCallback(( () => { + this._config.scroll && !this._config.backdrop || this._focustrap.activate(), + this._element.classList.add(Ni), + this._element.classList.remove(Pi), + I.trigger(this._element, "shown.bs.offcanvas", { + relatedTarget: t + }) + } + ), this._element, !0)) + } + hide() { + this._isShown && (I.trigger(this._element, "hide.bs.offcanvas").defaultPrevented || (this._focustrap.deactivate(), + this._element.blur(), + this._isShown = !1, + this._element.classList.add(ji), + this._backdrop.hide(), + this._queueCallback(( () => { + this._element.classList.remove(Ni, ji), + this._element.removeAttribute("aria-modal"), + this._element.removeAttribute("role"), + this._config.scroll || (new pi).reset(), + I.trigger(this._element, Hi) + } + ), this._element, !0))) + } + dispose() { + this._backdrop.dispose(), + this._focustrap.deactivate(), + super.dispose() + } + _initializeBackDrop() { + const t = Boolean(this._config.backdrop); + return new vi({ + className: "offcanvas-backdrop", + isVisible: t, + isAnimated: !0, + rootElement: this._element.parentNode, + clickCallback: t ? () => { + "static" !== this._config.backdrop ? this.hide() : I.trigger(this._element, Fi) + } + : null + }) + } + _initializeFocusTrap() { + return new Ti({ + trapElement: this._element + }) + } + _addEventListeners() { + I.on(this._element, "keydown.dismiss.bs.offcanvas", (t => { + "Escape" === t.key && (this._config.keyboard ? this.hide() : I.trigger(this._element, Fi)) + } + )) + } + static jQueryInterface(t) { + return this.each((function() { + const e = Bi.getOrCreateInstance(this, t); + if ("string" == typeof t) { + if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) + throw new TypeError(`No method named "${t}"`); + e[t](this) + } + } + )) + } + } + I.on(document, "click.bs.offcanvas.data-api", '[data-bs-toggle="offcanvas"]', (function(t) { + const e = z.getElementFromSelector(this); + if (["A", "AREA"].includes(this.tagName) && t.preventDefault(), + r(this)) + return; + I.one(e, Hi, ( () => { + o(this) && this.focus() + } + )); + const i = z.findOne(Mi); + i && i !== e && Bi.getInstance(i).hide(), + Bi.getOrCreateInstance(e).toggle(this) + } + )), + I.on(window, "load.bs.offcanvas.data-api", ( () => { + for (const t of z.find(Mi)) + Bi.getOrCreateInstance(t).show() + } + )), + I.on(window, "resize.bs.offcanvas", ( () => { + for (const t of z.find("[aria-modal][class*=show][class*=offcanvas-]")) + "fixed" !== getComputedStyle(t).position && Bi.getOrCreateInstance(t).hide() + } + )), + R(Bi), + f(Bi); + const zi = new Set(["background", "cite", "href", "itemtype", "longdesc", "poster", "src", "xlink:href"]) + , Ri = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i + , qi = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i + , Vi = (t, e) => { + const i = t.nodeName.toLowerCase(); + return e.includes(i) ? !zi.has(i) || Boolean(Ri.test(t.nodeValue) || qi.test(t.nodeValue)) : e.filter((t => t instanceof RegExp)).some((t => t.test(i))) + } + , Ki = { + "*": ["class", "dir", "id", "lang", "role", /^aria-[\w-]*$/i], + a: ["target", "href", "title", "rel"], + area: [], + b: [], + br: [], + col: [], + code: [], + div: [], + 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: [] + } + , Qi = { + allowList: Ki, + content: {}, + extraClass: "", + html: !1, + sanitize: !0, + sanitizeFn: null, + template: "
      " + } + , Xi = { + allowList: "object", + content: "object", + extraClass: "(string|function)", + html: "boolean", + sanitize: "boolean", + sanitizeFn: "(null|function)", + template: "string" + } + , Yi = { + entry: "(string|element|function|null)", + selector: "(string|element)" + }; + class Ui extends $ { + constructor(t) { + super(), + this._config = this._getConfig(t) + } + static get Default() { + return Qi + } + static get DefaultType() { + return Xi + } + static get NAME() { + return "TemplateFactory" + } + getContent() { + return Object.values(this._config.content).map((t => this._resolvePossibleFunction(t))).filter(Boolean) + } + hasContent() { + return this.getContent().length > 0 + } + changeContent(t) { + return this._checkContent(t), + this._config.content = { + ...this._config.content, + ...t + }, + this + } + toHtml() { + const t = document.createElement("div"); + t.innerHTML = this._maybeSanitize(this._config.template); + for (const [e,i] of Object.entries(this._config.content)) + this._setContent(t, i, e); + const e = t.children[0] + , i = this._resolvePossibleFunction(this._config.extraClass); + return i && e.classList.add(...i.split(" ")), + e + } + _typeCheckConfig(t) { + super._typeCheckConfig(t), + this._checkContent(t.content) + } + _checkContent(t) { + for (const [e,i] of Object.entries(t)) + super._typeCheckConfig({ + selector: e, + entry: i + }, Yi) + } + _setContent(t, e, i) { + const o = z.findOne(i, t); + o && ((e = this._resolvePossibleFunction(e)) ? n(e) ? this._putElementInTemplate(s(e), o) : this._config.html ? o.innerHTML = this._maybeSanitize(e) : o.textContent = e : o.remove()) + } + _maybeSanitize(t) { + return this._config.sanitize ? function(t, e, i) { + if (!t.length) + return t; + if (i && "function" == typeof i) + return i(t); + const n = (new window.DOMParser).parseFromString(t, "text/html") + , s = [].concat(...n.body.querySelectorAll("*")); + for (const t of s) { + const i = t.nodeName.toLowerCase(); + if (!Object.keys(e).includes(i)) { + t.remove(); + continue + } + const n = [].concat(...t.attributes) + , s = [].concat(e["*"] || [], e[i] || []); + for (const e of n) + Vi(e, s) || t.removeAttribute(e.nodeName) + } + return n.body.innerHTML + }(t, this._config.allowList, this._config.sanitizeFn) : t + } + _resolvePossibleFunction(t) { + return p(t, [this]) + } + _putElementInTemplate(t, e) { + if (this._config.html) + return e.innerHTML = "", + void e.append(t); + e.textContent = t.textContent + } + } + const Gi = new Set(["sanitize", "allowList", "sanitizeFn"]) + , Ji = "fade" + , Zi = "show" + , tn = ".modal" + , en = "hide.bs.modal" + , nn = "hover" + , sn = "focus" + , on = { + AUTO: "auto", + TOP: "top", + RIGHT: u() ? "left" : "right", + BOTTOM: "bottom", + LEFT: u() ? "right" : "left" + } + , rn = { + allowList: Ki, + animation: !0, + boundary: "clippingParents", + container: !1, + customClass: "", + delay: 0, + fallbackPlacements: ["top", "right", "bottom", "left"], + html: !1, + offset: [0, 0], + placement: "top", + popperConfig: null, + sanitize: !0, + sanitizeFn: null, + selector: !1, + template: '', + title: "", + trigger: "hover focus" + } + , an = { + 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 ln extends W { + constructor(t, e) { + if (void 0 === Ve) + throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)"); + super(t, e), + 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 rn + } + static get DefaultType() { + return an + } + static get NAME() { + return "tooltip" + } + enable() { + this._isEnabled = !0 + } + disable() { + this._isEnabled = !1 + } + toggleEnabled() { + this._isEnabled = !this._isEnabled + } + toggle() { + this._isEnabled && (this._activeTrigger.click = !this._activeTrigger.click, + this._isShown() ? this._leave() : this._enter()) + } + dispose() { + clearTimeout(this._timeout), + I.off(this._element.closest(tn), en, 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 ("none" === this._element.style.display) + throw new Error("Please use show on visible elements"); + if (!this._isWithContent() || !this._isEnabled) + return; + const t = I.trigger(this._element, this.constructor.eventName("show")) + , e = (a(this._element) || this._element.ownerDocument.documentElement).contains(this._element); + if (t.defaultPrevented || !e) + return; + this._disposePopper(); + const i = this._getTipElement(); + this._element.setAttribute("aria-describedby", i.getAttribute("id")); + const {container: n} = this._config; + if (this._element.ownerDocument.documentElement.contains(this.tip) || (n.append(i), + I.trigger(this._element, this.constructor.eventName("inserted"))), + this._popper = this._createPopper(i), + i.classList.add(Zi), + "ontouchstart"in document.documentElement) + for (const t of [].concat(...document.body.children)) + I.on(t, "mouseover", l); + this._queueCallback(( () => { + I.trigger(this._element, this.constructor.eventName("shown")), + !1 === this._isHovered && this._leave(), + this._isHovered = !1 + } + ), this.tip, this._isAnimated()) + } + hide() { + if (this._isShown() && !I.trigger(this._element, this.constructor.eventName("hide")).defaultPrevented) { + if (this._getTipElement().classList.remove(Zi), + "ontouchstart"in document.documentElement) + for (const t of [].concat(...document.body.children)) + I.off(t, "mouseover", l); + this._activeTrigger.click = !1, + this._activeTrigger.focus = !1, + this._activeTrigger.hover = !1, + this._isHovered = null, + this._queueCallback(( () => { + this._isWithActiveTrigger() || (this._isHovered || this._disposePopper(), + this._element.removeAttribute("aria-describedby"), + I.trigger(this._element, this.constructor.eventName("hidden"))) + } + ), this.tip, this._isAnimated()) + } + } + update() { + this._popper && this._popper.update() + } + _isWithContent() { + return Boolean(this._getTitle()) + } + _getTipElement() { + return this.tip || (this.tip = this._createTipElement(this._newContent || this._getContentForTemplate())), + this.tip + } + _createTipElement(t) { + const e = this._getTemplateFactory(t).toHtml(); + if (!e) + return null; + e.classList.remove(Ji, Zi), + e.classList.add(`bs-${this.constructor.NAME}-auto`); + const i = (t => { + do { + t += Math.floor(1e6 * Math.random()) + } while (document.getElementById(t)); + return t + } + )(this.constructor.NAME).toString(); + return e.setAttribute("id", i), + this._isAnimated() && e.classList.add(Ji), + e + } + setContent(t) { + this._newContent = t, + this._isShown() && (this._disposePopper(), + this.show()) + } + _getTemplateFactory(t) { + return this._templateFactory ? this._templateFactory.changeContent(t) : this._templateFactory = new Ui({ + ...this._config, + content: t, + extraClass: this._resolvePossibleFunction(this._config.customClass) + }), + this._templateFactory + } + _getContentForTemplate() { + return { + ".tooltip-inner": this._getTitle() + } + } + _getTitle() { + return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute("data-bs-original-title") + } + _initializeOnDelegatedTarget(t) { + return this.constructor.getOrCreateInstance(t.delegateTarget, this._getDelegateConfig()) + } + _isAnimated() { + return this._config.animation || this.tip && this.tip.classList.contains(Ji) + } + _isShown() { + return this.tip && this.tip.classList.contains(Zi) + } + _createPopper(t) { + const e = p(this._config.placement, [this, t, this._element]) + , i = on[e.toUpperCase()]; + return qe(this._element, t, this._getPopperConfig(i)) + } + _getOffset() { + const {offset: t} = this._config; + return "string" == typeof t ? t.split(",").map((t => Number.parseInt(t, 10))) : "function" == typeof t ? e => t(e, this._element) : t + } + _resolvePossibleFunction(t) { + return p(t, [this._element]) + } + _getPopperConfig(t) { + const e = { + placement: t, + 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: t => { + this._getTipElement().setAttribute("data-popper-placement", t.state.placement) + } + }] + }; + return { + ...e, + ...p(this._config.popperConfig, [e]) + } + } + _setListeners() { + const t = this._config.trigger.split(" "); + for (const e of t) + if ("click" === e) + I.on(this._element, this.constructor.eventName("click"), this._config.selector, (t => { + this._initializeOnDelegatedTarget(t).toggle() + } + )); + else if ("manual" !== e) { + const t = e === nn ? this.constructor.eventName("mouseenter") : this.constructor.eventName("focusin") + , i = e === nn ? this.constructor.eventName("mouseleave") : this.constructor.eventName("focusout"); + I.on(this._element, t, this._config.selector, (t => { + const e = this._initializeOnDelegatedTarget(t); + e._activeTrigger["focusin" === t.type ? sn : nn] = !0, + e._enter() + } + )), + I.on(this._element, i, this._config.selector, (t => { + const e = this._initializeOnDelegatedTarget(t); + e._activeTrigger["focusout" === t.type ? sn : nn] = e._element.contains(t.relatedTarget), + e._leave() + } + )) + } + this._hideModalHandler = () => { + this._element && this.hide() + } + , + I.on(this._element.closest(tn), en, this._hideModalHandler) + } + _fixTitle() { + const t = this._element.getAttribute("title"); + t && (this._element.getAttribute("aria-label") || this._element.textContent.trim() || this._element.setAttribute("aria-label", t), + this._element.setAttribute("data-bs-original-title", t), + 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(t, e) { + clearTimeout(this._timeout), + this._timeout = setTimeout(t, e) + } + _isWithActiveTrigger() { + return Object.values(this._activeTrigger).includes(!0) + } + _getConfig(t) { + const e = H.getDataAttributes(this._element); + for (const t of Object.keys(e)) + Gi.has(t) && delete e[t]; + return t = { + ...e, + ..."object" == typeof t && t ? t : {} + }, + t = this._mergeConfigObj(t), + t = this._configAfterMerge(t), + this._typeCheckConfig(t), + t + } + _configAfterMerge(t) { + return t.container = !1 === t.container ? document.body : s(t.container), + "number" == typeof t.delay && (t.delay = { + show: t.delay, + hide: t.delay + }), + "number" == typeof t.title && (t.title = t.title.toString()), + "number" == typeof t.content && (t.content = t.content.toString()), + t + } + _getDelegateConfig() { + const t = {}; + for (const [e,i] of Object.entries(this._config)) + this.constructor.Default[e] !== i && (t[e] = i); + return t.selector = !1, + t.trigger = "manual", + t + } + _disposePopper() { + this._popper && (this._popper.destroy(), + this._popper = null), + this.tip && (this.tip.remove(), + this.tip = null) + } + static jQueryInterface(t) { + return this.each((function() { + const e = ln.getOrCreateInstance(this, t); + if ("string" == typeof t) { + if (void 0 === e[t]) + throw new TypeError(`No method named "${t}"`); + e[t]() + } + } + )) + } + } + f(ln); + const cn = { + ...ln.Default, + content: "", + offset: [0, 8], + placement: "right", + template: '', + trigger: "click" + } + , hn = { + ...ln.DefaultType, + content: "(null|string|element|function)" + }; + class dn extends ln { + static get Default() { + return cn + } + static get DefaultType() { + return hn + } + static get NAME() { + return "popover" + } + _isWithContent() { + return this._getTitle() || this._getContent() + } + _getContentForTemplate() { + return { + ".popover-header": this._getTitle(), + ".popover-body": this._getContent() + } + } + _getContent() { + return this._resolvePossibleFunction(this._config.content) + } + static jQueryInterface(t) { + return this.each((function() { + const e = dn.getOrCreateInstance(this, t); + if ("string" == typeof t) { + if (void 0 === e[t]) + throw new TypeError(`No method named "${t}"`); + e[t]() + } + } + )) + } + } + f(dn); + const un = "click.bs.scrollspy" + , fn = "active" + , pn = "[href]" + , mn = { + offset: null, + rootMargin: "0px 0px -25%", + smoothScroll: !1, + target: null, + threshold: [.1, .5, 1] + } + , gn = { + offset: "(number|null)", + rootMargin: "string", + smoothScroll: "boolean", + target: "element", + threshold: "array" + }; + class _n extends W { + constructor(t, e) { + super(t, e), + this._targetLinks = new Map, + this._observableSections = new Map, + this._rootElement = "visible" === getComputedStyle(this._element).overflowY ? null : this._element, + this._activeTarget = null, + this._observer = null, + this._previousScrollData = { + visibleEntryTop: 0, + parentScrollTop: 0 + }, + this.refresh() + } + static get Default() { + return mn + } + static get DefaultType() { + return gn + } + static get NAME() { + return "scrollspy" + } + refresh() { + this._initializeTargetsAndObservables(), + this._maybeEnableSmoothScroll(), + this._observer ? this._observer.disconnect() : this._observer = this._getNewObserver(); + for (const t of this._observableSections.values()) + this._observer.observe(t) + } + dispose() { + this._observer.disconnect(), + super.dispose() + } + _configAfterMerge(t) { + return t.target = s(t.target) || document.body, + t.rootMargin = t.offset ? `${t.offset}px 0px -30%` : t.rootMargin, + "string" == typeof t.threshold && (t.threshold = t.threshold.split(",").map((t => Number.parseFloat(t)))), + t + } + _maybeEnableSmoothScroll() { + this._config.smoothScroll && (I.off(this._config.target, un), + I.on(this._config.target, un, pn, (t => { + const e = this._observableSections.get(t.target.hash); + if (e) { + t.preventDefault(); + const i = this._rootElement || window + , n = e.offsetTop - this._element.offsetTop; + if (i.scrollTo) + return void i.scrollTo({ + top: n, + behavior: "smooth" + }); + i.scrollTop = n + } + } + ))) + } + _getNewObserver() { + const t = { + root: this._rootElement, + threshold: this._config.threshold, + rootMargin: this._config.rootMargin + }; + return new IntersectionObserver((t => this._observerCallback(t)),t) + } + _observerCallback(t) { + const e = t => this._targetLinks.get(`#${t.target.id}`) + , i = t => { + this._previousScrollData.visibleEntryTop = t.target.offsetTop, + this._process(e(t)) + } + , n = (this._rootElement || document.documentElement).scrollTop + , s = n >= this._previousScrollData.parentScrollTop; + this._previousScrollData.parentScrollTop = n; + for (const o of t) { + if (!o.isIntersecting) { + this._activeTarget = null, + this._clearActiveClass(e(o)); + continue + } + const t = o.target.offsetTop >= this._previousScrollData.visibleEntryTop; + if (s && t) { + if (i(o), + !n) + return + } else + s || t || i(o) + } + } + _initializeTargetsAndObservables() { + this._targetLinks = new Map, + this._observableSections = new Map; + const t = z.find(pn, this._config.target); + for (const e of t) { + if (!e.hash || r(e)) + continue; + const t = z.findOne(e.hash, this._element); + o(t) && (this._targetLinks.set(e.hash, e), + this._observableSections.set(e.hash, t)) + } + } + _process(t) { + this._activeTarget !== t && (this._clearActiveClass(this._config.target), + this._activeTarget = t, + t.classList.add(fn), + this._activateParents(t), + I.trigger(this._element, "activate.bs.scrollspy", { + relatedTarget: t + })) + } + _activateParents(t) { + if (t.classList.contains("dropdown-item")) + z.findOne(".dropdown-toggle", t.closest(".dropdown")).classList.add(fn); + else + for (const e of z.parents(t, ".nav, .list-group")) + for (const t of z.prev(e, ".nav-link, .nav-item > .nav-link, .list-group-item")) + t.classList.add(fn) + } + _clearActiveClass(t) { + t.classList.remove(fn); + const e = z.find("[href].active", t); + for (const t of e) + t.classList.remove(fn) + } + static jQueryInterface(t) { + return this.each((function() { + const e = _n.getOrCreateInstance(this, t); + if ("string" == typeof t) { + if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) + throw new TypeError(`No method named "${t}"`); + e[t]() + } + } + )) + } + } + I.on(window, "load.bs.scrollspy.data-api", ( () => { + for (const t of z.find('[data-bs-spy="scroll"]')) + _n.getOrCreateInstance(t) + } + )), + f(_n); + const bn = "ArrowLeft" + , vn = "ArrowRight" + , yn = "ArrowUp" + , wn = "ArrowDown" + , An = "active" + , En = "fade" + , Tn = "show" + , Cn = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]' + , On = `.nav-link:not(.dropdown-toggle), .list-group-item:not(.dropdown-toggle), [role="tab"]:not(.dropdown-toggle), ${Cn}`; + class xn extends W { + constructor(t) { + super(t), + this._parent = this._element.closest('.list-group, .nav, [role="tablist"]'), + this._parent && (this._setInitialAttributes(this._parent, this._getChildren()), + I.on(this._element, "keydown.bs.tab", (t => this._keydown(t)))) + } + static get NAME() { + return "tab" + } + show() { + const t = this._element; + if (this._elemIsActive(t)) + return; + const e = this._getActiveElem() + , i = e ? I.trigger(e, "hide.bs.tab", { + relatedTarget: t + }) : null; + I.trigger(t, "show.bs.tab", { + relatedTarget: e + }).defaultPrevented || i && i.defaultPrevented || (this._deactivate(e, t), + this._activate(t, e)) + } + _activate(t, e) { + t && (t.classList.add(An), + this._activate(z.getElementFromSelector(t)), + this._queueCallback(( () => { + "tab" === t.getAttribute("role") ? (t.removeAttribute("tabindex"), + t.setAttribute("aria-selected", !0), + this._toggleDropDown(t, !0), + I.trigger(t, "shown.bs.tab", { + relatedTarget: e + })) : t.classList.add(Tn) + } + ), t, t.classList.contains(En))) + } + _deactivate(t, e) { + t && (t.classList.remove(An), + t.blur(), + this._deactivate(z.getElementFromSelector(t)), + this._queueCallback(( () => { + "tab" === t.getAttribute("role") ? (t.setAttribute("aria-selected", !1), + t.setAttribute("tabindex", "-1"), + this._toggleDropDown(t, !1), + I.trigger(t, "hidden.bs.tab", { + relatedTarget: e + })) : t.classList.remove(Tn) + } + ), t, t.classList.contains(En))) + } + _keydown(t) { + if (![bn, vn, yn, wn].includes(t.key)) + return; + t.stopPropagation(), + t.preventDefault(); + const e = [vn, wn].includes(t.key) + , i = g(this._getChildren().filter((t => !r(t))), t.target, e, !0); + i && (i.focus({ + preventScroll: !0 + }), + xn.getOrCreateInstance(i).show()) + } + _getChildren() { + return z.find(On, this._parent) + } + _getActiveElem() { + return this._getChildren().find((t => this._elemIsActive(t))) || null + } + _setInitialAttributes(t, e) { + this._setAttributeIfNotExists(t, "role", "tablist"); + for (const t of e) + this._setInitialAttributesOnChild(t) + } + _setInitialAttributesOnChild(t) { + t = this._getInnerElement(t); + const e = this._elemIsActive(t) + , i = this._getOuterElement(t); + t.setAttribute("aria-selected", e), + i !== t && this._setAttributeIfNotExists(i, "role", "presentation"), + e || t.setAttribute("tabindex", "-1"), + this._setAttributeIfNotExists(t, "role", "tab"), + this._setInitialAttributesOnTargetPanel(t) + } + _setInitialAttributesOnTargetPanel(t) { + const e = z.getElementFromSelector(t); + e && (this._setAttributeIfNotExists(e, "role", "tabpanel"), + t.id && this._setAttributeIfNotExists(e, "aria-labelledby", `#${t.id}`)) + } + _toggleDropDown(t, e) { + const i = this._getOuterElement(t); + if (!i.classList.contains("dropdown")) + return; + const n = (t, n) => { + const s = z.findOne(t, i); + s && s.classList.toggle(n, e) + } + ; + n(".dropdown-toggle", An), + n(".dropdown-menu", Tn), + i.setAttribute("aria-expanded", e) + } + _setAttributeIfNotExists(t, e, i) { + t.hasAttribute(e) || t.setAttribute(e, i) + } + _elemIsActive(t) { + return t.classList.contains(An) + } + _getInnerElement(t) { + return t.matches(On) ? t : z.findOne(On, t) + } + _getOuterElement(t) { + return t.closest(".nav-item, .list-group-item") || t + } + static jQueryInterface(t) { + return this.each((function() { + const e = xn.getOrCreateInstance(this); + if ("string" == typeof t) { + if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) + throw new TypeError(`No method named "${t}"`); + e[t]() + } + } + )) + } + } + I.on(document, "click.bs.tab", Cn, (function(t) { + ["A", "AREA"].includes(this.tagName) && t.preventDefault(), + r(this) || xn.getOrCreateInstance(this).show() + } + )), + I.on(window, "load.bs.tab", ( () => { + for (const t of z.find('.active[data-bs-toggle="tab"], .active[data-bs-toggle="pill"], .active[data-bs-toggle="list"]')) + xn.getOrCreateInstance(t) + } + )), + f(xn); + const kn = "hide" + , Ln = "show" + , Sn = "showing" + , Dn = { + animation: "boolean", + autohide: "boolean", + delay: "number" + } + , In = { + animation: !0, + autohide: !0, + delay: 5e3 + }; + class Nn extends W { + constructor(t, e) { + super(t, e), + this._timeout = null, + this._hasMouseInteraction = !1, + this._hasKeyboardInteraction = !1, + this._setListeners() + } + static get Default() { + return In + } + static get DefaultType() { + return Dn + } + static get NAME() { + return "toast" + } + show() { + I.trigger(this._element, "show.bs.toast").defaultPrevented || (this._clearTimeout(), + this._config.animation && this._element.classList.add("fade"), + this._element.classList.remove(kn), + c(this._element), + this._element.classList.add(Ln, Sn), + this._queueCallback(( () => { + this._element.classList.remove(Sn), + I.trigger(this._element, "shown.bs.toast"), + this._maybeScheduleHide() + } + ), this._element, this._config.animation)) + } + hide() { + this.isShown() && (I.trigger(this._element, "hide.bs.toast").defaultPrevented || (this._element.classList.add(Sn), + this._queueCallback(( () => { + this._element.classList.add(kn), + this._element.classList.remove(Sn, Ln), + I.trigger(this._element, "hidden.bs.toast") + } + ), this._element, this._config.animation))) + } + dispose() { + this._clearTimeout(), + this.isShown() && this._element.classList.remove(Ln), + super.dispose() + } + isShown() { + return this._element.classList.contains(Ln) + } + _maybeScheduleHide() { + this._config.autohide && (this._hasMouseInteraction || this._hasKeyboardInteraction || (this._timeout = setTimeout(( () => { + this.hide() + } + ), this._config.delay))) + } + _onInteraction(t, e) { + switch (t.type) { + case "mouseover": + case "mouseout": + this._hasMouseInteraction = e; + break; + case "focusin": + case "focusout": + this._hasKeyboardInteraction = e + } + if (e) + return void this._clearTimeout(); + const i = t.relatedTarget; + this._element === i || this._element.contains(i) || this._maybeScheduleHide() + } + _setListeners() { + I.on(this._element, "mouseover.bs.toast", (t => this._onInteraction(t, !0))), + I.on(this._element, "mouseout.bs.toast", (t => this._onInteraction(t, !1))), + I.on(this._element, "focusin.bs.toast", (t => this._onInteraction(t, !0))), + I.on(this._element, "focusout.bs.toast", (t => this._onInteraction(t, !1))) + } + _clearTimeout() { + clearTimeout(this._timeout), + this._timeout = null + } + static jQueryInterface(t) { + return this.each((function() { + const e = Nn.getOrCreateInstance(this, t); + if ("string" == typeof t) { + if (void 0 === e[t]) + throw new TypeError(`No method named "${t}"`); + e[t](this) + } + } + )) + } + } + return R(Nn), + f(Nn), + { + Alert: q, + Button: K, + Carousel: rt, + Collapse: ft, + Dropdown: ci, + Modal: Ii, + Offcanvas: Bi, + Popover: dn, + ScrollSpy: _n, + Tab: xn, + Toast: Nn, + Tooltip: ln + } +} +)); +//# sourceMappingURL=bootstrap.bundle.min.js.map diff --git a/static/js/jquery-3.6.0.min.js b/static/js/jquery-3.6.0.min.js new file mode 100644 index 0000000..5168208 --- /dev/null +++ b/static/js/jquery-3.6.0.min.js @@ -0,0 +1,4232 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e, t) { + "use strict"; + "object" == typeof module && "object" == typeof module.exports ? module.exports = e.document ? t(e, !0) : function(e) { + if (!e.document) + throw new Error("jQuery requires a window with a document"); + return t(e) + } + : t(e) +}("undefined" != typeof window ? window : this, function(C, e) { + "use strict"; + var t = [] + , r = Object.getPrototypeOf + , s = t.slice + , g = t.flat ? function(e) { + return t.flat.call(e) + } + : function(e) { + return t.concat.apply([], e) + } + , u = t.push + , i = t.indexOf + , n = {} + , o = n.toString + , v = n.hasOwnProperty + , a = v.toString + , l = a.call(Object) + , y = {} + , m = function(e) { + return "function" == typeof e && "number" != typeof e.nodeType && "function" != typeof e.item + } + , x = function(e) { + return null != e && e === e.window + } + , E = C.document + , c = { + type: !0, + src: !0, + nonce: !0, + noModule: !0 + }; + function b(e, t, n) { + var r, i, o = (n = n || E).createElement("script"); + if (o.text = e, + t) + for (r in c) + (i = t[r] || t.getAttribute && t.getAttribute(r)) && o.setAttribute(r, i); + n.head.appendChild(o).parentNode.removeChild(o) + } + function w(e) { + return null == e ? e + "" : "object" == typeof e || "function" == typeof e ? n[o.call(e)] || "object" : typeof e + } + var f = "3.6.0" + , S = function(e, t) { + return new S.fn.init(e,t) + }; + function p(e) { + var t = !!e && "length"in e && e.length + , n = w(e); + return !m(e) && !x(e) && ("array" === n || 0 === t || "number" == typeof t && 0 < t && t - 1 in e) + } + S.fn = S.prototype = { + jquery: f, + constructor: S, + length: 0, + toArray: function() { + return s.call(this) + }, + get: function(e) { + return null == e ? s.call(this) : e < 0 ? this[e + this.length] : this[e] + }, + pushStack: function(e) { + var t = S.merge(this.constructor(), e); + return t.prevObject = this, + t + }, + each: function(e) { + return S.each(this, e) + }, + map: function(n) { + return this.pushStack(S.map(this, function(e, t) { + return n.call(e, t, e) + })) + }, + slice: function() { + return this.pushStack(s.apply(this, arguments)) + }, + first: function() { + return this.eq(0) + }, + last: function() { + return this.eq(-1) + }, + even: function() { + return this.pushStack(S.grep(this, function(e, t) { + return (t + 1) % 2 + })) + }, + odd: function() { + return this.pushStack(S.grep(this, function(e, t) { + return t % 2 + })) + }, + eq: function(e) { + var t = this.length + , n = +e + (e < 0 ? t : 0); + return this.pushStack(0 <= n && n < t ? [this[n]] : []) + }, + end: function() { + return this.prevObject || this.constructor() + }, + push: u, + sort: t.sort, + splice: t.splice + }, + S.extend = S.fn.extend = function() { + var e, t, n, r, i, o, a = arguments[0] || {}, s = 1, u = arguments.length, l = !1; + for ("boolean" == typeof a && (l = a, + a = arguments[s] || {}, + s++), + "object" == typeof a || m(a) || (a = {}), + s === u && (a = this, + s--); s < u; s++) + if (null != (e = arguments[s])) + for (t in e) + r = e[t], + "__proto__" !== t && a !== r && (l && r && (S.isPlainObject(r) || (i = Array.isArray(r))) ? (n = a[t], + o = i && !Array.isArray(n) ? [] : i || S.isPlainObject(n) ? n : {}, + i = !1, + a[t] = S.extend(l, o, r)) : void 0 !== r && (a[t] = r)); + return a + } + , + S.extend({ + expando: "jQuery" + (f + Math.random()).replace(/\D/g, ""), + isReady: !0, + error: function(e) { + throw new Error(e) + }, + noop: function() {}, + isPlainObject: function(e) { + var t, n; + return !(!e || "[object Object]" !== o.call(e)) && (!(t = r(e)) || "function" == typeof (n = v.call(t, "constructor") && t.constructor) && a.call(n) === l) + }, + isEmptyObject: function(e) { + var t; + for (t in e) + return !1; + return !0 + }, + globalEval: function(e, t, n) { + b(e, { + nonce: t && t.nonce + }, n) + }, + each: function(e, t) { + var n, r = 0; + if (p(e)) { + for (n = e.length; r < n; r++) + if (!1 === t.call(e[r], r, e[r])) + break + } else + for (r in e) + if (!1 === t.call(e[r], r, e[r])) + break; + return e + }, + makeArray: function(e, t) { + var n = t || []; + return null != e && (p(Object(e)) ? S.merge(n, "string" == typeof e ? [e] : e) : u.call(n, e)), + n + }, + inArray: function(e, t, n) { + return null == t ? -1 : i.call(t, e, n) + }, + merge: function(e, t) { + for (var n = +t.length, r = 0, i = e.length; r < n; r++) + e[i++] = t[r]; + return e.length = i, + e + }, + grep: function(e, t, n) { + for (var r = [], i = 0, o = e.length, a = !n; i < o; i++) + !t(e[i], i) !== a && r.push(e[i]); + return r + }, + map: function(e, t, n) { + var r, i, o = 0, a = []; + if (p(e)) + for (r = e.length; o < r; o++) + null != (i = t(e[o], o, n)) && a.push(i); + else + for (o in e) + null != (i = t(e[o], o, n)) && a.push(i); + return g(a) + }, + guid: 1, + support: y + }), + "function" == typeof Symbol && (S.fn[Symbol.iterator] = t[Symbol.iterator]), + S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "), function(e, t) { + n["[object " + t + "]"] = t.toLowerCase() + }); + var d = function(n) { + var e, d, b, o, i, h, f, g, w, u, l, T, C, a, E, v, s, c, y, S = "sizzle" + 1 * new Date, p = n.document, k = 0, r = 0, m = ue(), x = ue(), A = ue(), N = ue(), j = function(e, t) { + return e === t && (l = !0), + 0 + }, D = {}.hasOwnProperty, t = [], q = t.pop, L = t.push, H = t.push, O = t.slice, P = function(e, t) { + for (var n = 0, r = e.length; n < r; n++) + if (e[n] === t) + return n; + return -1 + }, R = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", M = "[\\x20\\t\\r\\n\\f]", I = "(?:\\\\[\\da-fA-F]{1,6}" + M + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", W = "\\[" + M + "*(" + I + ")(?:" + M + "*([*^$|!~]?=)" + M + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + I + "))|)" + M + "*\\]", F = ":(" + I + ")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|" + W + ")*)|.*)\\)|)", B = new RegExp(M + "+","g"), $ = new RegExp("^" + M + "+|((?:^|[^\\\\])(?:\\\\.)*)" + M + "+$","g"), _ = new RegExp("^" + M + "*," + M + "*"), z = new RegExp("^" + M + "*([>+~]|" + M + ")" + M + "*"), U = new RegExp(M + "|>"), X = new RegExp(F), V = new RegExp("^" + I + "$"), G = { + ID: new RegExp("^#(" + I + ")"), + CLASS: new RegExp("^\\.(" + I + ")"), + TAG: new RegExp("^(" + I + "|[*])"), + ATTR: new RegExp("^" + W), + PSEUDO: new RegExp("^" + F), + CHILD: new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + M + "*(even|odd|(([+-]|)(\\d*)n|)" + M + "*(?:([+-]|)" + M + "*(\\d+)|))" + M + "*\\)|)","i"), + bool: new RegExp("^(?:" + R + ")$","i"), + needsContext: new RegExp("^" + M + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + M + "*((?:-\\d)?\\d*)" + M + "*\\)|)(?=[^-]|$)","i") + }, Y = /HTML$/i, Q = /^(?:input|select|textarea|button)$/i, J = /^h\d$/i, K = /^[^{]+\{\s*\[native \w/, Z = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, ee = /[+~]/, te = new RegExp("\\\\[\\da-fA-F]{1,6}" + M + "?|\\\\([^\\r\\n\\f])","g"), ne = function(e, t) { + var n = "0x" + e.slice(1) - 65536; + return t || (n < 0 ? String.fromCharCode(n + 65536) : String.fromCharCode(n >> 10 | 55296, 1023 & n | 56320)) + }, re = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, ie = function(e, t) { + return t ? "\0" === e ? "\ufffd" : e.slice(0, -1) + "\\" + e.charCodeAt(e.length - 1).toString(16) + " " : "\\" + e + }, oe = function() { + T() + }, ae = be(function(e) { + return !0 === e.disabled && "fieldset" === e.nodeName.toLowerCase() + }, { + dir: "parentNode", + next: "legend" + }); + try { + H.apply(t = O.call(p.childNodes), p.childNodes), + t[p.childNodes.length].nodeType + } catch (e) { + H = { + apply: t.length ? function(e, t) { + L.apply(e, O.call(t)) + } + : function(e, t) { + var n = e.length + , r = 0; + while (e[n++] = t[r++]) + ; + e.length = n - 1 + } + } + } + function se(t, e, n, r) { + var i, o, a, s, u, l, c, f = e && e.ownerDocument, p = e ? e.nodeType : 9; + if (n = n || [], + "string" != typeof t || !t || 1 !== p && 9 !== p && 11 !== p) + return n; + if (!r && (T(e), + e = e || C, + E)) { + if (11 !== p && (u = Z.exec(t))) + if (i = u[1]) { + if (9 === p) { + if (!(a = e.getElementById(i))) + return n; + if (a.id === i) + return n.push(a), + n + } else if (f && (a = f.getElementById(i)) && y(e, a) && a.id === i) + return n.push(a), + n + } else { + if (u[2]) + return H.apply(n, e.getElementsByTagName(t)), + n; + if ((i = u[3]) && d.getElementsByClassName && e.getElementsByClassName) + return H.apply(n, e.getElementsByClassName(i)), + n + } + if (d.qsa && !N[t + " "] && (!v || !v.test(t)) && (1 !== p || "object" !== e.nodeName.toLowerCase())) { + if (c = t, + f = e, + 1 === p && (U.test(t) || z.test(t))) { + (f = ee.test(t) && ye(e.parentNode) || e) === e && d.scope || ((s = e.getAttribute("id")) ? s = s.replace(re, ie) : e.setAttribute("id", s = S)), + o = (l = h(t)).length; + while (o--) + l[o] = (s ? "#" + s : ":scope") + " " + xe(l[o]); + c = l.join(",") + } + try { + return H.apply(n, f.querySelectorAll(c)), + n + } catch (e) { + N(t, !0) + } finally { + s === S && e.removeAttribute("id") + } + } + } + return g(t.replace($, "$1"), e, n, r) + } + function ue() { + var r = []; + return function e(t, n) { + return r.push(t + " ") > b.cacheLength && delete e[r.shift()], + e[t + " "] = n + } + } + function le(e) { + return e[S] = !0, + e + } + function ce(e) { + var t = C.createElement("fieldset"); + try { + return !!e(t) + } catch (e) { + return !1 + } finally { + t.parentNode && t.parentNode.removeChild(t), + t = null + } + } + function fe(e, t) { + var n = e.split("|") + , r = n.length; + while (r--) + b.attrHandle[n[r]] = t + } + function pe(e, t) { + var n = t && e + , r = n && 1 === e.nodeType && 1 === t.nodeType && e.sourceIndex - t.sourceIndex; + if (r) + return r; + if (n) + while (n = n.nextSibling) + if (n === t) + return -1; + return e ? 1 : -1 + } + function de(t) { + return function(e) { + return "input" === e.nodeName.toLowerCase() && e.type === t + } + } + function he(n) { + return function(e) { + var t = e.nodeName.toLowerCase(); + return ("input" === t || "button" === t) && e.type === n + } + } + function ge(t) { + return function(e) { + return "form"in e ? e.parentNode && !1 === e.disabled ? "label"in e ? "label"in e.parentNode ? e.parentNode.disabled === t : e.disabled === t : e.isDisabled === t || e.isDisabled !== !t && ae(e) === t : e.disabled === t : "label"in e && e.disabled === t + } + } + function ve(a) { + return le(function(o) { + return o = +o, + le(function(e, t) { + var n, r = a([], e.length, o), i = r.length; + while (i--) + e[n = r[i]] && (e[n] = !(t[n] = e[n])) + }) + }) + } + function ye(e) { + return e && "undefined" != typeof e.getElementsByTagName && e + } + for (e in d = se.support = {}, + i = se.isXML = function(e) { + var t = e && e.namespaceURI + , n = e && (e.ownerDocument || e).documentElement; + return !Y.test(t || n && n.nodeName || "HTML") + } + , + T = se.setDocument = function(e) { + var t, n, r = e ? e.ownerDocument || e : p; + return r != C && 9 === r.nodeType && r.documentElement && (a = (C = r).documentElement, + E = !i(C), + p != C && (n = C.defaultView) && n.top !== n && (n.addEventListener ? n.addEventListener("unload", oe, !1) : n.attachEvent && n.attachEvent("onunload", oe)), + d.scope = ce(function(e) { + return a.appendChild(e).appendChild(C.createElement("div")), + "undefined" != typeof e.querySelectorAll && !e.querySelectorAll(":scope fieldset div").length + }), + d.attributes = ce(function(e) { + return e.className = "i", + !e.getAttribute("className") + }), + d.getElementsByTagName = ce(function(e) { + return e.appendChild(C.createComment("")), + !e.getElementsByTagName("*").length + }), + d.getElementsByClassName = K.test(C.getElementsByClassName), + d.getById = ce(function(e) { + return a.appendChild(e).id = S, + !C.getElementsByName || !C.getElementsByName(S).length + }), + d.getById ? (b.filter.ID = function(e) { + var t = e.replace(te, ne); + return function(e) { + return e.getAttribute("id") === t + } + } + , + b.find.ID = function(e, t) { + if ("undefined" != typeof t.getElementById && E) { + var n = t.getElementById(e); + return n ? [n] : [] + } + } + ) : (b.filter.ID = function(e) { + var n = e.replace(te, ne); + return function(e) { + var t = "undefined" != typeof e.getAttributeNode && e.getAttributeNode("id"); + return t && t.value === n + } + } + , + b.find.ID = function(e, t) { + if ("undefined" != typeof t.getElementById && E) { + var n, r, i, o = t.getElementById(e); + if (o) { + if ((n = o.getAttributeNode("id")) && n.value === e) + return [o]; + i = t.getElementsByName(e), + r = 0; + while (o = i[r++]) + if ((n = o.getAttributeNode("id")) && n.value === e) + return [o] + } + return [] + } + } + ), + b.find.TAG = d.getElementsByTagName ? function(e, t) { + return "undefined" != typeof t.getElementsByTagName ? t.getElementsByTagName(e) : d.qsa ? t.querySelectorAll(e) : void 0 + } + : function(e, t) { + var n, r = [], i = 0, o = t.getElementsByTagName(e); + if ("*" === e) { + while (n = o[i++]) + 1 === n.nodeType && r.push(n); + return r + } + return o + } + , + b.find.CLASS = d.getElementsByClassName && function(e, t) { + if ("undefined" != typeof t.getElementsByClassName && E) + return t.getElementsByClassName(e) + } + , + s = [], + v = [], + (d.qsa = K.test(C.querySelectorAll)) && (ce(function(e) { + var t; + a.appendChild(e).innerHTML = "", + e.querySelectorAll("[msallowcapture^='']").length && v.push("[*^$]=" + M + "*(?:''|\"\")"), + e.querySelectorAll("[selected]").length || v.push("\\[" + M + "*(?:value|" + R + ")"), + e.querySelectorAll("[id~=" + S + "-]").length || v.push("~="), + (t = C.createElement("input")).setAttribute("name", ""), + e.appendChild(t), + e.querySelectorAll("[name='']").length || v.push("\\[" + M + "*name" + M + "*=" + M + "*(?:''|\"\")"), + e.querySelectorAll(":checked").length || v.push(":checked"), + e.querySelectorAll("a#" + S + "+*").length || v.push(".#.+[+~]"), + e.querySelectorAll("\\\f"), + v.push("[\\r\\n\\f]") + }), + ce(function(e) { + e.innerHTML = ""; + var t = C.createElement("input"); + t.setAttribute("type", "hidden"), + e.appendChild(t).setAttribute("name", "D"), + e.querySelectorAll("[name=d]").length && v.push("name" + M + "*[*^$|!~]?="), + 2 !== e.querySelectorAll(":enabled").length && v.push(":enabled", ":disabled"), + a.appendChild(e).disabled = !0, + 2 !== e.querySelectorAll(":disabled").length && v.push(":enabled", ":disabled"), + e.querySelectorAll("*,:x"), + v.push(",.*:") + })), + (d.matchesSelector = K.test(c = a.matches || a.webkitMatchesSelector || a.mozMatchesSelector || a.oMatchesSelector || a.msMatchesSelector)) && ce(function(e) { + d.disconnectedMatch = c.call(e, "*"), + c.call(e, "[s!='']:x"), + s.push("!=", F) + }), + v = v.length && new RegExp(v.join("|")), + s = s.length && new RegExp(s.join("|")), + t = K.test(a.compareDocumentPosition), + y = t || K.test(a.contains) ? function(e, t) { + var n = 9 === e.nodeType ? e.documentElement : e + , r = t && t.parentNode; + return e === r || !(!r || 1 !== r.nodeType || !(n.contains ? n.contains(r) : e.compareDocumentPosition && 16 & e.compareDocumentPosition(r))) + } + : function(e, t) { + if (t) + while (t = t.parentNode) + if (t === e) + return !0; + return !1 + } + , + j = t ? function(e, t) { + if (e === t) + return l = !0, + 0; + var n = !e.compareDocumentPosition - !t.compareDocumentPosition; + return n || (1 & (n = (e.ownerDocument || e) == (t.ownerDocument || t) ? e.compareDocumentPosition(t) : 1) || !d.sortDetached && t.compareDocumentPosition(e) === n ? e == C || e.ownerDocument == p && y(p, e) ? -1 : t == C || t.ownerDocument == p && y(p, t) ? 1 : u ? P(u, e) - P(u, t) : 0 : 4 & n ? -1 : 1) + } + : function(e, t) { + if (e === t) + return l = !0, + 0; + var n, r = 0, i = e.parentNode, o = t.parentNode, a = [e], s = [t]; + if (!i || !o) + return e == C ? -1 : t == C ? 1 : i ? -1 : o ? 1 : u ? P(u, e) - P(u, t) : 0; + if (i === o) + return pe(e, t); + n = e; + while (n = n.parentNode) + a.unshift(n); + n = t; + while (n = n.parentNode) + s.unshift(n); + while (a[r] === s[r]) + r++; + return r ? pe(a[r], s[r]) : a[r] == p ? -1 : s[r] == p ? 1 : 0 + } + ), + C + } + , + se.matches = function(e, t) { + return se(e, null, null, t) + } + , + se.matchesSelector = function(e, t) { + if (T(e), + d.matchesSelector && E && !N[t + " "] && (!s || !s.test(t)) && (!v || !v.test(t))) + try { + var n = c.call(e, t); + if (n || d.disconnectedMatch || e.document && 11 !== e.document.nodeType) + return n + } catch (e) { + N(t, !0) + } + return 0 < se(t, C, null, [e]).length + } + , + se.contains = function(e, t) { + return (e.ownerDocument || e) != C && T(e), + y(e, t) + } + , + se.attr = function(e, t) { + (e.ownerDocument || e) != C && T(e); + var n = b.attrHandle[t.toLowerCase()] + , r = n && D.call(b.attrHandle, t.toLowerCase()) ? n(e, t, !E) : void 0; + return void 0 !== r ? r : d.attributes || !E ? e.getAttribute(t) : (r = e.getAttributeNode(t)) && r.specified ? r.value : null + } + , + se.escape = function(e) { + return (e + "").replace(re, ie) + } + , + se.error = function(e) { + throw new Error("Syntax error, unrecognized expression: " + e) + } + , + se.uniqueSort = function(e) { + var t, n = [], r = 0, i = 0; + if (l = !d.detectDuplicates, + u = !d.sortStable && e.slice(0), + e.sort(j), + l) { + while (t = e[i++]) + t === e[i] && (r = n.push(i)); + while (r--) + e.splice(n[r], 1) + } + return u = null, + e + } + , + o = se.getText = function(e) { + var t, n = "", r = 0, i = e.nodeType; + if (i) { + if (1 === i || 9 === i || 11 === i) { + if ("string" == typeof e.textContent) + return e.textContent; + for (e = e.firstChild; e; e = e.nextSibling) + n += o(e) + } else if (3 === i || 4 === i) + return e.nodeValue + } else + while (t = e[r++]) + n += o(t); + return n + } + , + (b = se.selectors = { + cacheLength: 50, + createPseudo: le, + match: G, + attrHandle: {}, + find: {}, + relative: { + ">": { + dir: "parentNode", + first: !0 + }, + " ": { + dir: "parentNode" + }, + "+": { + dir: "previousSibling", + first: !0 + }, + "~": { + dir: "previousSibling" + } + }, + preFilter: { + ATTR: function(e) { + return e[1] = e[1].replace(te, ne), + e[3] = (e[3] || e[4] || e[5] || "").replace(te, ne), + "~=" === e[2] && (e[3] = " " + e[3] + " "), + e.slice(0, 4) + }, + CHILD: function(e) { + return e[1] = e[1].toLowerCase(), + "nth" === e[1].slice(0, 3) ? (e[3] || se.error(e[0]), + e[4] = +(e[4] ? e[5] + (e[6] || 1) : 2 * ("even" === e[3] || "odd" === e[3])), + e[5] = +(e[7] + e[8] || "odd" === e[3])) : e[3] && se.error(e[0]), + e + }, + PSEUDO: function(e) { + var t, n = !e[6] && e[2]; + return G.CHILD.test(e[0]) ? null : (e[3] ? e[2] = e[4] || e[5] || "" : n && X.test(n) && (t = h(n, !0)) && (t = n.indexOf(")", n.length - t) - n.length) && (e[0] = e[0].slice(0, t), + e[2] = n.slice(0, t)), + e.slice(0, 3)) + } + }, + filter: { + TAG: function(e) { + var t = e.replace(te, ne).toLowerCase(); + return "*" === e ? function() { + return !0 + } + : function(e) { + return e.nodeName && e.nodeName.toLowerCase() === t + } + }, + CLASS: function(e) { + var t = m[e + " "]; + return t || (t = new RegExp("(^|" + M + ")" + e + "(" + M + "|$)")) && m(e, function(e) { + return t.test("string" == typeof e.className && e.className || "undefined" != typeof e.getAttribute && e.getAttribute("class") || "") + }) + }, + ATTR: function(n, r, i) { + return function(e) { + var t = se.attr(e, n); + return null == t ? "!=" === r : !r || (t += "", + "=" === r ? t === i : "!=" === r ? t !== i : "^=" === r ? i && 0 === t.indexOf(i) : "*=" === r ? i && -1 < t.indexOf(i) : "$=" === r ? i && t.slice(-i.length) === i : "~=" === r ? -1 < (" " + t.replace(B, " ") + " ").indexOf(i) : "|=" === r && (t === i || t.slice(0, i.length + 1) === i + "-")) + } + }, + CHILD: function(h, e, t, g, v) { + var y = "nth" !== h.slice(0, 3) + , m = "last" !== h.slice(-4) + , x = "of-type" === e; + return 1 === g && 0 === v ? function(e) { + return !!e.parentNode + } + : function(e, t, n) { + var r, i, o, a, s, u, l = y !== m ? "nextSibling" : "previousSibling", c = e.parentNode, f = x && e.nodeName.toLowerCase(), p = !n && !x, d = !1; + if (c) { + if (y) { + while (l) { + a = e; + while (a = a[l]) + if (x ? a.nodeName.toLowerCase() === f : 1 === a.nodeType) + return !1; + u = l = "only" === h && !u && "nextSibling" + } + return !0 + } + if (u = [m ? c.firstChild : c.lastChild], + m && p) { + d = (s = (r = (i = (o = (a = c)[S] || (a[S] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] || [])[0] === k && r[1]) && r[2], + a = s && c.childNodes[s]; + while (a = ++s && a && a[l] || (d = s = 0) || u.pop()) + if (1 === a.nodeType && ++d && a === e) { + i[h] = [k, s, d]; + break + } + } else if (p && (d = s = (r = (i = (o = (a = e)[S] || (a[S] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] || [])[0] === k && r[1]), + !1 === d) + while (a = ++s && a && a[l] || (d = s = 0) || u.pop()) + if ((x ? a.nodeName.toLowerCase() === f : 1 === a.nodeType) && ++d && (p && ((i = (o = a[S] || (a[S] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] = [k, d]), + a === e)) + break; + return (d -= v) === g || d % g == 0 && 0 <= d / g + } + } + }, + PSEUDO: function(e, o) { + var t, a = b.pseudos[e] || b.setFilters[e.toLowerCase()] || se.error("unsupported pseudo: " + e); + return a[S] ? a(o) : 1 < a.length ? (t = [e, e, "", o], + b.setFilters.hasOwnProperty(e.toLowerCase()) ? le(function(e, t) { + var n, r = a(e, o), i = r.length; + while (i--) + e[n = P(e, r[i])] = !(t[n] = r[i]) + }) : function(e) { + return a(e, 0, t) + } + ) : a + } + }, + pseudos: { + not: le(function(e) { + var r = [] + , i = [] + , s = f(e.replace($, "$1")); + return s[S] ? le(function(e, t, n, r) { + var i, o = s(e, null, r, []), a = e.length; + while (a--) + (i = o[a]) && (e[a] = !(t[a] = i)) + }) : function(e, t, n) { + return r[0] = e, + s(r, null, n, i), + r[0] = null, + !i.pop() + } + }), + has: le(function(t) { + return function(e) { + return 0 < se(t, e).length + } + }), + contains: le(function(t) { + return t = t.replace(te, ne), + function(e) { + return -1 < (e.textContent || o(e)).indexOf(t) + } + }), + lang: le(function(n) { + return V.test(n || "") || se.error("unsupported lang: " + n), + n = n.replace(te, ne).toLowerCase(), + function(e) { + var t; + do { + if (t = E ? e.lang : e.getAttribute("xml:lang") || e.getAttribute("lang")) + return (t = t.toLowerCase()) === n || 0 === t.indexOf(n + "-") + } while ((e = e.parentNode) && 1 === e.nodeType); + return !1 + } + }), + target: function(e) { + var t = n.location && n.location.hash; + return t && t.slice(1) === e.id + }, + root: function(e) { + return e === a + }, + focus: function(e) { + return e === C.activeElement && (!C.hasFocus || C.hasFocus()) && !!(e.type || e.href || ~e.tabIndex) + }, + enabled: ge(!1), + disabled: ge(!0), + checked: function(e) { + var t = e.nodeName.toLowerCase(); + return "input" === t && !!e.checked || "option" === t && !!e.selected + }, + selected: function(e) { + return e.parentNode && e.parentNode.selectedIndex, + !0 === e.selected + }, + empty: function(e) { + for (e = e.firstChild; e; e = e.nextSibling) + if (e.nodeType < 6) + return !1; + return !0 + }, + parent: function(e) { + return !b.pseudos.empty(e) + }, + header: function(e) { + return J.test(e.nodeName) + }, + input: function(e) { + return Q.test(e.nodeName) + }, + button: function(e) { + var t = e.nodeName.toLowerCase(); + return "input" === t && "button" === e.type || "button" === t + }, + text: function(e) { + var t; + return "input" === e.nodeName.toLowerCase() && "text" === e.type && (null == (t = e.getAttribute("type")) || "text" === t.toLowerCase()) + }, + first: ve(function() { + return [0] + }), + last: ve(function(e, t) { + return [t - 1] + }), + eq: ve(function(e, t, n) { + return [n < 0 ? n + t : n] + }), + even: ve(function(e, t) { + for (var n = 0; n < t; n += 2) + e.push(n); + return e + }), + odd: ve(function(e, t) { + for (var n = 1; n < t; n += 2) + e.push(n); + return e + }), + lt: ve(function(e, t, n) { + for (var r = n < 0 ? n + t : t < n ? t : n; 0 <= --r; ) + e.push(r); + return e + }), + gt: ve(function(e, t, n) { + for (var r = n < 0 ? n + t : n; ++r < t; ) + e.push(r); + return e + }) + } + }).pseudos.nth = b.pseudos.eq, + { + radio: !0, + checkbox: !0, + file: !0, + password: !0, + image: !0 + }) + b.pseudos[e] = de(e); + for (e in { + submit: !0, + reset: !0 + }) + b.pseudos[e] = he(e); + function me() {} + function xe(e) { + for (var t = 0, n = e.length, r = ""; t < n; t++) + r += e[t].value; + return r + } + function be(s, e, t) { + var u = e.dir + , l = e.next + , c = l || u + , f = t && "parentNode" === c + , p = r++; + return e.first ? function(e, t, n) { + while (e = e[u]) + if (1 === e.nodeType || f) + return s(e, t, n); + return !1 + } + : function(e, t, n) { + var r, i, o, a = [k, p]; + if (n) { + while (e = e[u]) + if ((1 === e.nodeType || f) && s(e, t, n)) + return !0 + } else + while (e = e[u]) + if (1 === e.nodeType || f) + if (i = (o = e[S] || (e[S] = {}))[e.uniqueID] || (o[e.uniqueID] = {}), + l && l === e.nodeName.toLowerCase()) + e = e[u] || e; + else { + if ((r = i[c]) && r[0] === k && r[1] === p) + return a[2] = r[2]; + if ((i[c] = a)[2] = s(e, t, n)) + return !0 + } + return !1 + } + } + function we(i) { + return 1 < i.length ? function(e, t, n) { + var r = i.length; + while (r--) + if (!i[r](e, t, n)) + return !1; + return !0 + } + : i[0] + } + function Te(e, t, n, r, i) { + for (var o, a = [], s = 0, u = e.length, l = null != t; s < u; s++) + (o = e[s]) && (n && !n(o, r, i) || (a.push(o), + l && t.push(s))); + return a + } + function Ce(d, h, g, v, y, e) { + return v && !v[S] && (v = Ce(v)), + y && !y[S] && (y = Ce(y, e)), + le(function(e, t, n, r) { + var i, o, a, s = [], u = [], l = t.length, c = e || function(e, t, n) { + for (var r = 0, i = t.length; r < i; r++) + se(e, t[r], n); + return n + }(h || "*", n.nodeType ? [n] : n, []), f = !d || !e && h ? c : Te(c, s, d, n, r), p = g ? y || (e ? d : l || v) ? [] : t : f; + if (g && g(f, p, n, r), + v) { + i = Te(p, u), + v(i, [], n, r), + o = i.length; + while (o--) + (a = i[o]) && (p[u[o]] = !(f[u[o]] = a)) + } + if (e) { + if (y || d) { + if (y) { + i = [], + o = p.length; + while (o--) + (a = p[o]) && i.push(f[o] = a); + y(null, p = [], i, r) + } + o = p.length; + while (o--) + (a = p[o]) && -1 < (i = y ? P(e, a) : s[o]) && (e[i] = !(t[i] = a)) + } + } else + p = Te(p === t ? p.splice(l, p.length) : p), + y ? y(null, t, p, r) : H.apply(t, p) + }) + } + function Ee(e) { + for (var i, t, n, r = e.length, o = b.relative[e[0].type], a = o || b.relative[" "], s = o ? 1 : 0, u = be(function(e) { + return e === i + }, a, !0), l = be(function(e) { + return -1 < P(i, e) + }, a, !0), c = [function(e, t, n) { + var r = !o && (n || t !== w) || ((i = t).nodeType ? u(e, t, n) : l(e, t, n)); + return i = null, + r + } + ]; s < r; s++) + if (t = b.relative[e[s].type]) + c = [be(we(c), t)]; + else { + if ((t = b.filter[e[s].type].apply(null, e[s].matches))[S]) { + for (n = ++s; n < r; n++) + if (b.relative[e[n].type]) + break; + return Ce(1 < s && we(c), 1 < s && xe(e.slice(0, s - 1).concat({ + value: " " === e[s - 2].type ? "*" : "" + })).replace($, "$1"), t, s < n && Ee(e.slice(s, n)), n < r && Ee(e = e.slice(n)), n < r && xe(e)) + } + c.push(t) + } + return we(c) + } + return me.prototype = b.filters = b.pseudos, + b.setFilters = new me, + h = se.tokenize = function(e, t) { + var n, r, i, o, a, s, u, l = x[e + " "]; + if (l) + return t ? 0 : l.slice(0); + a = e, + s = [], + u = b.preFilter; + while (a) { + for (o in n && !(r = _.exec(a)) || (r && (a = a.slice(r[0].length) || a), + s.push(i = [])), + n = !1, + (r = z.exec(a)) && (n = r.shift(), + i.push({ + value: n, + type: r[0].replace($, " ") + }), + a = a.slice(n.length)), + b.filter) + !(r = G[o].exec(a)) || u[o] && !(r = u[o](r)) || (n = r.shift(), + i.push({ + value: n, + type: o, + matches: r + }), + a = a.slice(n.length)); + if (!n) + break + } + return t ? a.length : a ? se.error(e) : x(e, s).slice(0) + } + , + f = se.compile = function(e, t) { + var n, v, y, m, x, r, i = [], o = [], a = A[e + " "]; + if (!a) { + t || (t = h(e)), + n = t.length; + while (n--) + (a = Ee(t[n]))[S] ? i.push(a) : o.push(a); + (a = A(e, (v = o, + m = 0 < (y = i).length, + x = 0 < v.length, + r = function(e, t, n, r, i) { + var o, a, s, u = 0, l = "0", c = e && [], f = [], p = w, d = e || x && b.find.TAG("*", i), h = k += null == p ? 1 : Math.random() || .1, g = d.length; + for (i && (w = t == C || t || i); l !== g && null != (o = d[l]); l++) { + if (x && o) { + a = 0, + t || o.ownerDocument == C || (T(o), + n = !E); + while (s = v[a++]) + if (s(o, t || C, n)) { + r.push(o); + break + } + i && (k = h) + } + m && ((o = !s && o) && u--, + e && c.push(o)) + } + if (u += l, + m && l !== u) { + a = 0; + while (s = y[a++]) + s(c, f, t, n); + if (e) { + if (0 < u) + while (l--) + c[l] || f[l] || (f[l] = q.call(r)); + f = Te(f) + } + H.apply(r, f), + i && !e && 0 < f.length && 1 < u + y.length && se.uniqueSort(r) + } + return i && (k = h, + w = p), + c + } + , + m ? le(r) : r))).selector = e + } + return a + } + , + g = se.select = function(e, t, n, r) { + var i, o, a, s, u, l = "function" == typeof e && e, c = !r && h(e = l.selector || e); + if (n = n || [], + 1 === c.length) { + if (2 < (o = c[0] = c[0].slice(0)).length && "ID" === (a = o[0]).type && 9 === t.nodeType && E && b.relative[o[1].type]) { + if (!(t = (b.find.ID(a.matches[0].replace(te, ne), t) || [])[0])) + return n; + l && (t = t.parentNode), + e = e.slice(o.shift().value.length) + } + i = G.needsContext.test(e) ? 0 : o.length; + while (i--) { + if (a = o[i], + b.relative[s = a.type]) + break; + if ((u = b.find[s]) && (r = u(a.matches[0].replace(te, ne), ee.test(o[0].type) && ye(t.parentNode) || t))) { + if (o.splice(i, 1), + !(e = r.length && xe(o))) + return H.apply(n, r), + n; + break + } + } + } + return (l || f(e, c))(r, t, !E, n, !t || ee.test(e) && ye(t.parentNode) || t), + n + } + , + d.sortStable = S.split("").sort(j).join("") === S, + d.detectDuplicates = !!l, + T(), + d.sortDetached = ce(function(e) { + return 1 & e.compareDocumentPosition(C.createElement("fieldset")) + }), + ce(function(e) { + return e.innerHTML = "", + "#" === e.firstChild.getAttribute("href") + }) || fe("type|href|height|width", function(e, t, n) { + if (!n) + return e.getAttribute(t, "type" === t.toLowerCase() ? 1 : 2) + }), + d.attributes && ce(function(e) { + return e.innerHTML = "", + e.firstChild.setAttribute("value", ""), + "" === e.firstChild.getAttribute("value") + }) || fe("value", function(e, t, n) { + if (!n && "input" === e.nodeName.toLowerCase()) + return e.defaultValue + }), + ce(function(e) { + return null == e.getAttribute("disabled") + }) || fe(R, function(e, t, n) { + var r; + if (!n) + return !0 === e[t] ? t.toLowerCase() : (r = e.getAttributeNode(t)) && r.specified ? r.value : null + }), + se + }(C); + S.find = d, + S.expr = d.selectors, + S.expr[":"] = S.expr.pseudos, + S.uniqueSort = S.unique = d.uniqueSort, + S.text = d.getText, + S.isXMLDoc = d.isXML, + S.contains = d.contains, + S.escapeSelector = d.escape; + var h = function(e, t, n) { + var r = [] + , i = void 0 !== n; + while ((e = e[t]) && 9 !== e.nodeType) + if (1 === e.nodeType) { + if (i && S(e).is(n)) + break; + r.push(e) + } + return r + } + , T = function(e, t) { + for (var n = []; e; e = e.nextSibling) + 1 === e.nodeType && e !== t && n.push(e); + return n + } + , k = S.expr.match.needsContext; + function A(e, t) { + return e.nodeName && e.nodeName.toLowerCase() === t.toLowerCase() + } + var N = /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i; + function j(e, n, r) { + return m(n) ? S.grep(e, function(e, t) { + return !!n.call(e, t, e) !== r + }) : n.nodeType ? S.grep(e, function(e) { + return e === n !== r + }) : "string" != typeof n ? S.grep(e, function(e) { + return -1 < i.call(n, e) !== r + }) : S.filter(n, e, r) + } + S.filter = function(e, t, n) { + var r = t[0]; + return n && (e = ":not(" + e + ")"), + 1 === t.length && 1 === r.nodeType ? S.find.matchesSelector(r, e) ? [r] : [] : S.find.matches(e, S.grep(t, function(e) { + return 1 === e.nodeType + })) + } + , + S.fn.extend({ + find: function(e) { + var t, n, r = this.length, i = this; + if ("string" != typeof e) + return this.pushStack(S(e).filter(function() { + for (t = 0; t < r; t++) + if (S.contains(i[t], this)) + return !0 + })); + for (n = this.pushStack([]), + t = 0; t < r; t++) + S.find(e, i[t], n); + return 1 < r ? S.uniqueSort(n) : n + }, + filter: function(e) { + return this.pushStack(j(this, e || [], !1)) + }, + not: function(e) { + return this.pushStack(j(this, e || [], !0)) + }, + is: function(e) { + return !!j(this, "string" == typeof e && k.test(e) ? S(e) : e || [], !1).length + } + }); + var D, q = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/; + (S.fn.init = function(e, t, n) { + var r, i; + if (!e) + return this; + if (n = n || D, + "string" == typeof e) { + if (!(r = "<" === e[0] && ">" === e[e.length - 1] && 3 <= e.length ? [null, e, null] : q.exec(e)) || !r[1] && t) + return !t || t.jquery ? (t || n).find(e) : this.constructor(t).find(e); + if (r[1]) { + if (t = t instanceof S ? t[0] : t, + S.merge(this, S.parseHTML(r[1], t && t.nodeType ? t.ownerDocument || t : E, !0)), + N.test(r[1]) && S.isPlainObject(t)) + for (r in t) + m(this[r]) ? this[r](t[r]) : this.attr(r, t[r]); + return this + } + return (i = E.getElementById(r[2])) && (this[0] = i, + this.length = 1), + this + } + return e.nodeType ? (this[0] = e, + this.length = 1, + this) : m(e) ? void 0 !== n.ready ? n.ready(e) : e(S) : S.makeArray(e, this) + } + ).prototype = S.fn, + D = S(E); + var L = /^(?:parents|prev(?:Until|All))/ + , H = { + children: !0, + contents: !0, + next: !0, + prev: !0 + }; + function O(e, t) { + while ((e = e[t]) && 1 !== e.nodeType) + ; + return e + } + S.fn.extend({ + has: function(e) { + var t = S(e, this) + , n = t.length; + return this.filter(function() { + for (var e = 0; e < n; e++) + if (S.contains(this, t[e])) + return !0 + }) + }, + closest: function(e, t) { + var n, r = 0, i = this.length, o = [], a = "string" != typeof e && S(e); + if (!k.test(e)) + for (; r < i; r++) + for (n = this[r]; n && n !== t; n = n.parentNode) + if (n.nodeType < 11 && (a ? -1 < a.index(n) : 1 === n.nodeType && S.find.matchesSelector(n, e))) { + o.push(n); + break + } + return this.pushStack(1 < o.length ? S.uniqueSort(o) : o) + }, + index: function(e) { + return e ? "string" == typeof e ? i.call(S(e), this[0]) : i.call(this, e.jquery ? e[0] : e) : this[0] && this[0].parentNode ? this.first().prevAll().length : -1 + }, + add: function(e, t) { + return this.pushStack(S.uniqueSort(S.merge(this.get(), S(e, t)))) + }, + addBack: function(e) { + return this.add(null == e ? this.prevObject : this.prevObject.filter(e)) + } + }), + S.each({ + parent: function(e) { + var t = e.parentNode; + return t && 11 !== t.nodeType ? t : null + }, + parents: function(e) { + return h(e, "parentNode") + }, + parentsUntil: function(e, t, n) { + return h(e, "parentNode", n) + }, + next: function(e) { + return O(e, "nextSibling") + }, + prev: function(e) { + return O(e, "previousSibling") + }, + nextAll: function(e) { + return h(e, "nextSibling") + }, + prevAll: function(e) { + return h(e, "previousSibling") + }, + nextUntil: function(e, t, n) { + return h(e, "nextSibling", n) + }, + prevUntil: function(e, t, n) { + return h(e, "previousSibling", n) + }, + siblings: function(e) { + return T((e.parentNode || {}).firstChild, e) + }, + children: function(e) { + return T(e.firstChild) + }, + contents: function(e) { + return null != e.contentDocument && r(e.contentDocument) ? e.contentDocument : (A(e, "template") && (e = e.content || e), + S.merge([], e.childNodes)) + } + }, function(r, i) { + S.fn[r] = function(e, t) { + var n = S.map(this, i, e); + return "Until" !== r.slice(-5) && (t = e), + t && "string" == typeof t && (n = S.filter(t, n)), + 1 < this.length && (H[r] || S.uniqueSort(n), + L.test(r) && n.reverse()), + this.pushStack(n) + } + }); + var P = /[^\x20\t\r\n\f]+/g; + function R(e) { + return e + } + function M(e) { + throw e + } + function I(e, t, n, r) { + var i; + try { + e && m(i = e.promise) ? i.call(e).done(t).fail(n) : e && m(i = e.then) ? i.call(e, t, n) : t.apply(void 0, [e].slice(r)) + } catch (e) { + n.apply(void 0, [e]) + } + } + S.Callbacks = function(r) { + var e, n; + r = "string" == typeof r ? (e = r, + n = {}, + S.each(e.match(P) || [], function(e, t) { + n[t] = !0 + }), + n) : S.extend({}, r); + var i, t, o, a, s = [], u = [], l = -1, c = function() { + for (a = a || r.once, + o = i = !0; u.length; l = -1) { + t = u.shift(); + while (++l < s.length) + !1 === s[l].apply(t[0], t[1]) && r.stopOnFalse && (l = s.length, + t = !1) + } + r.memory || (t = !1), + i = !1, + a && (s = t ? [] : "") + }, f = { + add: function() { + return s && (t && !i && (l = s.length - 1, + u.push(t)), + function n(e) { + S.each(e, function(e, t) { + m(t) ? r.unique && f.has(t) || s.push(t) : t && t.length && "string" !== w(t) && n(t) + }) + }(arguments), + t && !i && c()), + this + }, + remove: function() { + return S.each(arguments, function(e, t) { + var n; + while (-1 < (n = S.inArray(t, s, n))) + s.splice(n, 1), + n <= l && l-- + }), + this + }, + has: function(e) { + return e ? -1 < S.inArray(e, s) : 0 < s.length + }, + empty: function() { + return s && (s = []), + this + }, + disable: function() { + return a = u = [], + s = t = "", + this + }, + disabled: function() { + return !s + }, + lock: function() { + return a = u = [], + t || i || (s = t = ""), + this + }, + locked: function() { + return !!a + }, + fireWith: function(e, t) { + return a || (t = [e, (t = t || []).slice ? t.slice() : t], + u.push(t), + i || c()), + this + }, + fire: function() { + return f.fireWith(this, arguments), + this + }, + fired: function() { + return !!o + } + }; + return f + } + , + S.extend({ + Deferred: function(e) { + var o = [["notify", "progress", S.Callbacks("memory"), S.Callbacks("memory"), 2], ["resolve", "done", S.Callbacks("once memory"), S.Callbacks("once memory"), 0, "resolved"], ["reject", "fail", S.Callbacks("once memory"), S.Callbacks("once memory"), 1, "rejected"]] + , i = "pending" + , a = { + state: function() { + return i + }, + always: function() { + return s.done(arguments).fail(arguments), + this + }, + "catch": function(e) { + return a.then(null, e) + }, + pipe: function() { + var i = arguments; + return S.Deferred(function(r) { + S.each(o, function(e, t) { + var n = m(i[t[4]]) && i[t[4]]; + s[t[1]](function() { + var e = n && n.apply(this, arguments); + e && m(e.promise) ? e.promise().progress(r.notify).done(r.resolve).fail(r.reject) : r[t[0] + "With"](this, n ? [e] : arguments) + }) + }), + i = null + }).promise() + }, + then: function(t, n, r) { + var u = 0; + function l(i, o, a, s) { + return function() { + var n = this + , r = arguments + , e = function() { + var e, t; + if (!(i < u)) { + if ((e = a.apply(n, r)) === o.promise()) + throw new TypeError("Thenable self-resolution"); + t = e && ("object" == typeof e || "function" == typeof e) && e.then, + m(t) ? s ? t.call(e, l(u, o, R, s), l(u, o, M, s)) : (u++, + t.call(e, l(u, o, R, s), l(u, o, M, s), l(u, o, R, o.notifyWith))) : (a !== R && (n = void 0, + r = [e]), + (s || o.resolveWith)(n, r)) + } + } + , t = s ? e : function() { + try { + e() + } catch (e) { + S.Deferred.exceptionHook && S.Deferred.exceptionHook(e, t.stackTrace), + u <= i + 1 && (a !== M && (n = void 0, + r = [e]), + o.rejectWith(n, r)) + } + } + ; + i ? t() : (S.Deferred.getStackHook && (t.stackTrace = S.Deferred.getStackHook()), + C.setTimeout(t)) + } + } + return S.Deferred(function(e) { + o[0][3].add(l(0, e, m(r) ? r : R, e.notifyWith)), + o[1][3].add(l(0, e, m(t) ? t : R)), + o[2][3].add(l(0, e, m(n) ? n : M)) + }).promise() + }, + promise: function(e) { + return null != e ? S.extend(e, a) : a + } + } + , s = {}; + return S.each(o, function(e, t) { + var n = t[2] + , r = t[5]; + a[t[1]] = n.add, + r && n.add(function() { + i = r + }, o[3 - e][2].disable, o[3 - e][3].disable, o[0][2].lock, o[0][3].lock), + n.add(t[3].fire), + s[t[0]] = function() { + return s[t[0] + "With"](this === s ? void 0 : this, arguments), + this + } + , + s[t[0] + "With"] = n.fireWith + }), + a.promise(s), + e && e.call(s, s), + s + }, + when: function(e) { + var n = arguments.length + , t = n + , r = Array(t) + , i = s.call(arguments) + , o = S.Deferred() + , a = function(t) { + return function(e) { + r[t] = this, + i[t] = 1 < arguments.length ? s.call(arguments) : e, + --n || o.resolveWith(r, i) + } + }; + if (n <= 1 && (I(e, o.done(a(t)).resolve, o.reject, !n), + "pending" === o.state() || m(i[t] && i[t].then))) + return o.then(); + while (t--) + I(i[t], a(t), o.reject); + return o.promise() + } + }); + var W = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + S.Deferred.exceptionHook = function(e, t) { + C.console && C.console.warn && e && W.test(e.name) && C.console.warn("jQuery.Deferred exception: " + e.message, e.stack, t) + } + , + S.readyException = function(e) { + C.setTimeout(function() { + throw e + }) + } + ; + var F = S.Deferred(); + function B() { + E.removeEventListener("DOMContentLoaded", B), + C.removeEventListener("load", B), + S.ready() + } + S.fn.ready = function(e) { + return F.then(e)["catch"](function(e) { + S.readyException(e) + }), + this + } + , + S.extend({ + isReady: !1, + readyWait: 1, + ready: function(e) { + (!0 === e ? --S.readyWait : S.isReady) || (S.isReady = !0) !== e && 0 < --S.readyWait || F.resolveWith(E, [S]) + } + }), + S.ready.then = F.then, + "complete" === E.readyState || "loading" !== E.readyState && !E.documentElement.doScroll ? C.setTimeout(S.ready) : (E.addEventListener("DOMContentLoaded", B), + C.addEventListener("load", B)); + var $ = function(e, t, n, r, i, o, a) { + var s = 0 + , u = e.length + , l = null == n; + if ("object" === w(n)) + for (s in i = !0, + n) + $(e, t, s, n[s], !0, o, a); + else if (void 0 !== r && (i = !0, + m(r) || (a = !0), + l && (a ? (t.call(e, r), + t = null) : (l = t, + t = function(e, t, n) { + return l.call(S(e), n) + } + )), + t)) + for (; s < u; s++) + t(e[s], n, a ? r : r.call(e[s], s, t(e[s], n))); + return i ? e : l ? t.call(e) : u ? t(e[0], n) : o + } + , _ = /^-ms-/ + , z = /-([a-z])/g; + function U(e, t) { + return t.toUpperCase() + } + function X(e) { + return e.replace(_, "ms-").replace(z, U) + } + var V = function(e) { + return 1 === e.nodeType || 9 === e.nodeType || !+e.nodeType + }; + function G() { + this.expando = S.expando + G.uid++ + } + G.uid = 1, + G.prototype = { + cache: function(e) { + var t = e[this.expando]; + return t || (t = {}, + V(e) && (e.nodeType ? e[this.expando] = t : Object.defineProperty(e, this.expando, { + value: t, + configurable: !0 + }))), + t + }, + set: function(e, t, n) { + var r, i = this.cache(e); + if ("string" == typeof t) + i[X(t)] = n; + else + for (r in t) + i[X(r)] = t[r]; + return i + }, + get: function(e, t) { + return void 0 === t ? this.cache(e) : e[this.expando] && e[this.expando][X(t)] + }, + access: function(e, t, n) { + return void 0 === t || t && "string" == typeof t && void 0 === n ? this.get(e, t) : (this.set(e, t, n), + void 0 !== n ? n : t) + }, + remove: function(e, t) { + var n, r = e[this.expando]; + if (void 0 !== r) { + if (void 0 !== t) { + n = (t = Array.isArray(t) ? t.map(X) : (t = X(t))in r ? [t] : t.match(P) || []).length; + while (n--) + delete r[t[n]] + } + (void 0 === t || S.isEmptyObject(r)) && (e.nodeType ? e[this.expando] = void 0 : delete e[this.expando]) + } + }, + hasData: function(e) { + var t = e[this.expando]; + return void 0 !== t && !S.isEmptyObject(t) + } + }; + var Y = new G + , Q = new G + , J = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/ + , K = /[A-Z]/g; + function Z(e, t, n) { + var r, i; + if (void 0 === n && 1 === e.nodeType) + if (r = "data-" + t.replace(K, "-$&").toLowerCase(), + "string" == typeof (n = e.getAttribute(r))) { + try { + n = "true" === (i = n) || "false" !== i && ("null" === i ? null : i === +i + "" ? +i : J.test(i) ? JSON.parse(i) : i) + } catch (e) {} + Q.set(e, t, n) + } else + n = void 0; + return n + } + S.extend({ + hasData: function(e) { + return Q.hasData(e) || Y.hasData(e) + }, + data: function(e, t, n) { + return Q.access(e, t, n) + }, + removeData: function(e, t) { + Q.remove(e, t) + }, + _data: function(e, t, n) { + return Y.access(e, t, n) + }, + _removeData: function(e, t) { + Y.remove(e, t) + } + }), + S.fn.extend({ + data: function(n, e) { + var t, r, i, o = this[0], a = o && o.attributes; + if (void 0 === n) { + if (this.length && (i = Q.get(o), + 1 === o.nodeType && !Y.get(o, "hasDataAttrs"))) { + t = a.length; + while (t--) + a[t] && 0 === (r = a[t].name).indexOf("data-") && (r = X(r.slice(5)), + Z(o, r, i[r])); + Y.set(o, "hasDataAttrs", !0) + } + return i + } + return "object" == typeof n ? this.each(function() { + Q.set(this, n) + }) : $(this, function(e) { + var t; + if (o && void 0 === e) + return void 0 !== (t = Q.get(o, n)) ? t : void 0 !== (t = Z(o, n)) ? t : void 0; + this.each(function() { + Q.set(this, n, e) + }) + }, null, e, 1 < arguments.length, null, !0) + }, + removeData: function(e) { + return this.each(function() { + Q.remove(this, e) + }) + } + }), + S.extend({ + queue: function(e, t, n) { + var r; + if (e) + return t = (t || "fx") + "queue", + r = Y.get(e, t), + n && (!r || Array.isArray(n) ? r = Y.access(e, t, S.makeArray(n)) : r.push(n)), + r || [] + }, + dequeue: function(e, t) { + t = t || "fx"; + var n = S.queue(e, t) + , r = n.length + , i = n.shift() + , o = S._queueHooks(e, t); + "inprogress" === i && (i = n.shift(), + r--), + i && ("fx" === t && n.unshift("inprogress"), + delete o.stop, + i.call(e, function() { + S.dequeue(e, t) + }, o)), + !r && o && o.empty.fire() + }, + _queueHooks: function(e, t) { + var n = t + "queueHooks"; + return Y.get(e, n) || Y.access(e, n, { + empty: S.Callbacks("once memory").add(function() { + Y.remove(e, [t + "queue", n]) + }) + }) + } + }), + S.fn.extend({ + queue: function(t, n) { + var e = 2; + return "string" != typeof t && (n = t, + t = "fx", + e--), + arguments.length < e ? S.queue(this[0], t) : void 0 === n ? this : this.each(function() { + var e = S.queue(this, t, n); + S._queueHooks(this, t), + "fx" === t && "inprogress" !== e[0] && S.dequeue(this, t) + }) + }, + dequeue: function(e) { + return this.each(function() { + S.dequeue(this, e) + }) + }, + clearQueue: function(e) { + return this.queue(e || "fx", []) + }, + promise: function(e, t) { + var n, r = 1, i = S.Deferred(), o = this, a = this.length, s = function() { + --r || i.resolveWith(o, [o]) + }; + "string" != typeof e && (t = e, + e = void 0), + e = e || "fx"; + while (a--) + (n = Y.get(o[a], e + "queueHooks")) && n.empty && (r++, + n.empty.add(s)); + return s(), + i.promise(t) + } + }); + var ee = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source + , te = new RegExp("^(?:([+-])=|)(" + ee + ")([a-z%]*)$","i") + , ne = ["Top", "Right", "Bottom", "Left"] + , re = E.documentElement + , ie = function(e) { + return S.contains(e.ownerDocument, e) + } + , oe = { + composed: !0 + }; + re.getRootNode && (ie = function(e) { + return S.contains(e.ownerDocument, e) || e.getRootNode(oe) === e.ownerDocument + } + ); + var ae = function(e, t) { + return "none" === (e = t || e).style.display || "" === e.style.display && ie(e) && "none" === S.css(e, "display") + }; + function se(e, t, n, r) { + var i, o, a = 20, s = r ? function() { + return r.cur() + } + : function() { + return S.css(e, t, "") + } + , u = s(), l = n && n[3] || (S.cssNumber[t] ? "" : "px"), c = e.nodeType && (S.cssNumber[t] || "px" !== l && +u) && te.exec(S.css(e, t)); + if (c && c[3] !== l) { + u /= 2, + l = l || c[3], + c = +u || 1; + while (a--) + S.style(e, t, c + l), + (1 - o) * (1 - (o = s() / u || .5)) <= 0 && (a = 0), + c /= o; + c *= 2, + S.style(e, t, c + l), + n = n || [] + } + return n && (c = +c || +u || 0, + i = n[1] ? c + (n[1] + 1) * n[2] : +n[2], + r && (r.unit = l, + r.start = c, + r.end = i)), + i + } + var ue = {}; + function le(e, t) { + for (var n, r, i, o, a, s, u, l = [], c = 0, f = e.length; c < f; c++) + (r = e[c]).style && (n = r.style.display, + t ? ("none" === n && (l[c] = Y.get(r, "display") || null, + l[c] || (r.style.display = "")), + "" === r.style.display && ae(r) && (l[c] = (u = a = o = void 0, + a = (i = r).ownerDocument, + s = i.nodeName, + (u = ue[s]) || (o = a.body.appendChild(a.createElement(s)), + u = S.css(o, "display"), + o.parentNode.removeChild(o), + "none" === u && (u = "block"), + ue[s] = u)))) : "none" !== n && (l[c] = "none", + Y.set(r, "display", n))); + for (c = 0; c < f; c++) + null != l[c] && (e[c].style.display = l[c]); + return e + } + S.fn.extend({ + show: function() { + return le(this, !0) + }, + hide: function() { + return le(this) + }, + toggle: function(e) { + return "boolean" == typeof e ? e ? this.show() : this.hide() : this.each(function() { + ae(this) ? S(this).show() : S(this).hide() + }) + } + }); + var ce, fe, pe = /^(?:checkbox|radio)$/i, de = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i, he = /^$|^module$|\/(?:java|ecma)script/i; + ce = E.createDocumentFragment().appendChild(E.createElement("div")), + (fe = E.createElement("input")).setAttribute("type", "radio"), + fe.setAttribute("checked", "checked"), + fe.setAttribute("name", "t"), + ce.appendChild(fe), + y.checkClone = ce.cloneNode(!0).cloneNode(!0).lastChild.checked, + ce.innerHTML = "", + y.noCloneChecked = !!ce.cloneNode(!0).lastChild.defaultValue, + ce.innerHTML = "", + y.option = !!ce.lastChild; + var ge = { + thead: [1, "", "
      "], + col: [2, "", "
      "], + tr: [2, "", "
      "], + td: [3, "", "
      "], + _default: [0, "", ""] + }; + function ve(e, t) { + var n; + return n = "undefined" != typeof e.getElementsByTagName ? e.getElementsByTagName(t || "*") : "undefined" != typeof e.querySelectorAll ? e.querySelectorAll(t || "*") : [], + void 0 === t || t && A(e, t) ? S.merge([e], n) : n + } + function ye(e, t) { + for (var n = 0, r = e.length; n < r; n++) + Y.set(e[n], "globalEval", !t || Y.get(t[n], "globalEval")) + } + ge.tbody = ge.tfoot = ge.colgroup = ge.caption = ge.thead, + ge.th = ge.td, + y.option || (ge.optgroup = ge.option = [1, ""]); + var me = /<|&#?\w+;/; + function xe(e, t, n, r, i) { + for (var o, a, s, u, l, c, f = t.createDocumentFragment(), p = [], d = 0, h = e.length; d < h; d++) + if ((o = e[d]) || 0 === o) + if ("object" === w(o)) + S.merge(p, o.nodeType ? [o] : o); + else if (me.test(o)) { + a = a || f.appendChild(t.createElement("div")), + s = (de.exec(o) || ["", ""])[1].toLowerCase(), + u = ge[s] || ge._default, + a.innerHTML = u[1] + S.htmlPrefilter(o) + u[2], + c = u[0]; + while (c--) + a = a.lastChild; + S.merge(p, a.childNodes), + (a = f.firstChild).textContent = "" + } else + p.push(t.createTextNode(o)); + f.textContent = "", + d = 0; + while (o = p[d++]) + if (r && -1 < S.inArray(o, r)) + i && i.push(o); + else if (l = ie(o), + a = ve(f.appendChild(o), "script"), + l && ye(a), + n) { + c = 0; + while (o = a[c++]) + he.test(o.type || "") && n.push(o) + } + return f + } + var be = /^([^.]*)(?:\.(.+)|)/; + function we() { + return !0 + } + function Te() { + return !1 + } + function Ce(e, t) { + return e === function() { + try { + return E.activeElement + } catch (e) {} + }() == ("focus" === t) + } + function Ee(e, t, n, r, i, o) { + var a, s; + if ("object" == typeof t) { + for (s in "string" != typeof n && (r = r || n, + n = void 0), + t) + Ee(e, s, n, r, t[s], o); + return e + } + if (null == r && null == i ? (i = n, + r = n = void 0) : null == i && ("string" == typeof n ? (i = r, + r = void 0) : (i = r, + r = n, + n = void 0)), + !1 === i) + i = Te; + else if (!i) + return e; + return 1 === o && (a = i, + (i = function(e) { + return S().off(e), + a.apply(this, arguments) + } + ).guid = a.guid || (a.guid = S.guid++)), + e.each(function() { + S.event.add(this, t, i, r, n) + }) + } + function Se(e, i, o) { + o ? (Y.set(e, i, !1), + S.event.add(e, i, { + namespace: !1, + handler: function(e) { + var t, n, r = Y.get(this, i); + if (1 & e.isTrigger && this[i]) { + if (r.length) + (S.event.special[i] || {}).delegateType && e.stopPropagation(); + else if (r = s.call(arguments), + Y.set(this, i, r), + t = o(this, i), + this[i](), + r !== (n = Y.get(this, i)) || t ? Y.set(this, i, !1) : n = {}, + r !== n) + return e.stopImmediatePropagation(), + e.preventDefault(), + n && n.value + } else + r.length && (Y.set(this, i, { + value: S.event.trigger(S.extend(r[0], S.Event.prototype), r.slice(1), this) + }), + e.stopImmediatePropagation()) + } + })) : void 0 === Y.get(e, i) && S.event.add(e, i, we) + } + S.event = { + global: {}, + add: function(t, e, n, r, i) { + var o, a, s, u, l, c, f, p, d, h, g, v = Y.get(t); + if (V(t)) { + n.handler && (n = (o = n).handler, + i = o.selector), + i && S.find.matchesSelector(re, i), + n.guid || (n.guid = S.guid++), + (u = v.events) || (u = v.events = Object.create(null)), + (a = v.handle) || (a = v.handle = function(e) { + return "undefined" != typeof S && S.event.triggered !== e.type ? S.event.dispatch.apply(t, arguments) : void 0 + } + ), + l = (e = (e || "").match(P) || [""]).length; + while (l--) + d = g = (s = be.exec(e[l]) || [])[1], + h = (s[2] || "").split(".").sort(), + d && (f = S.event.special[d] || {}, + d = (i ? f.delegateType : f.bindType) || d, + f = S.event.special[d] || {}, + c = S.extend({ + type: d, + origType: g, + data: r, + handler: n, + guid: n.guid, + selector: i, + needsContext: i && S.expr.match.needsContext.test(i), + namespace: h.join(".") + }, o), + (p = u[d]) || ((p = u[d] = []).delegateCount = 0, + f.setup && !1 !== f.setup.call(t, r, h, a) || t.addEventListener && t.addEventListener(d, a)), + f.add && (f.add.call(t, c), + c.handler.guid || (c.handler.guid = n.guid)), + i ? p.splice(p.delegateCount++, 0, c) : p.push(c), + S.event.global[d] = !0) + } + }, + remove: function(e, t, n, r, i) { + var o, a, s, u, l, c, f, p, d, h, g, v = Y.hasData(e) && Y.get(e); + if (v && (u = v.events)) { + l = (t = (t || "").match(P) || [""]).length; + while (l--) + if (d = g = (s = be.exec(t[l]) || [])[1], + h = (s[2] || "").split(".").sort(), + d) { + f = S.event.special[d] || {}, + p = u[d = (r ? f.delegateType : f.bindType) || d] || [], + s = s[2] && new RegExp("(^|\\.)" + h.join("\\.(?:.*\\.|)") + "(\\.|$)"), + a = o = p.length; + while (o--) + c = p[o], + !i && g !== c.origType || n && n.guid !== c.guid || s && !s.test(c.namespace) || r && r !== c.selector && ("**" !== r || !c.selector) || (p.splice(o, 1), + c.selector && p.delegateCount--, + f.remove && f.remove.call(e, c)); + a && !p.length && (f.teardown && !1 !== f.teardown.call(e, h, v.handle) || S.removeEvent(e, d, v.handle), + delete u[d]) + } else + for (d in u) + S.event.remove(e, d + t[l], n, r, !0); + S.isEmptyObject(u) && Y.remove(e, "handle events") + } + }, + dispatch: function(e) { + var t, n, r, i, o, a, s = new Array(arguments.length), u = S.event.fix(e), l = (Y.get(this, "events") || Object.create(null))[u.type] || [], c = S.event.special[u.type] || {}; + for (s[0] = u, + t = 1; t < arguments.length; t++) + s[t] = arguments[t]; + if (u.delegateTarget = this, + !c.preDispatch || !1 !== c.preDispatch.call(this, u)) { + a = S.event.handlers.call(this, u, l), + t = 0; + while ((i = a[t++]) && !u.isPropagationStopped()) { + u.currentTarget = i.elem, + n = 0; + while ((o = i.handlers[n++]) && !u.isImmediatePropagationStopped()) + u.rnamespace && !1 !== o.namespace && !u.rnamespace.test(o.namespace) || (u.handleObj = o, + u.data = o.data, + void 0 !== (r = ((S.event.special[o.origType] || {}).handle || o.handler).apply(i.elem, s)) && !1 === (u.result = r) && (u.preventDefault(), + u.stopPropagation())) + } + return c.postDispatch && c.postDispatch.call(this, u), + u.result + } + }, + handlers: function(e, t) { + var n, r, i, o, a, s = [], u = t.delegateCount, l = e.target; + if (u && l.nodeType && !("click" === e.type && 1 <= e.button)) + for (; l !== this; l = l.parentNode || this) + if (1 === l.nodeType && ("click" !== e.type || !0 !== l.disabled)) { + for (o = [], + a = {}, + n = 0; n < u; n++) + void 0 === a[i = (r = t[n]).selector + " "] && (a[i] = r.needsContext ? -1 < S(i, this).index(l) : S.find(i, this, null, [l]).length), + a[i] && o.push(r); + o.length && s.push({ + elem: l, + handlers: o + }) + } + return l = this, + u < t.length && s.push({ + elem: l, + handlers: t.slice(u) + }), + s + }, + addProp: function(t, e) { + Object.defineProperty(S.Event.prototype, t, { + enumerable: !0, + configurable: !0, + get: m(e) ? function() { + if (this.originalEvent) + return e(this.originalEvent) + } + : function() { + if (this.originalEvent) + return this.originalEvent[t] + } + , + set: function(e) { + Object.defineProperty(this, t, { + enumerable: !0, + configurable: !0, + writable: !0, + value: e + }) + } + }) + }, + fix: function(e) { + return e[S.expando] ? e : new S.Event(e) + }, + special: { + load: { + noBubble: !0 + }, + click: { + setup: function(e) { + var t = this || e; + return pe.test(t.type) && t.click && A(t, "input") && Se(t, "click", we), + !1 + }, + trigger: function(e) { + var t = this || e; + return pe.test(t.type) && t.click && A(t, "input") && Se(t, "click"), + !0 + }, + _default: function(e) { + var t = e.target; + return pe.test(t.type) && t.click && A(t, "input") && Y.get(t, "click") || A(t, "a") + } + }, + beforeunload: { + postDispatch: function(e) { + void 0 !== e.result && e.originalEvent && (e.originalEvent.returnValue = e.result) + } + } + } + }, + S.removeEvent = function(e, t, n) { + e.removeEventListener && e.removeEventListener(t, n) + } + , + S.Event = function(e, t) { + if (!(this instanceof S.Event)) + return new S.Event(e,t); + e && e.type ? (this.originalEvent = e, + this.type = e.type, + this.isDefaultPrevented = e.defaultPrevented || void 0 === e.defaultPrevented && !1 === e.returnValue ? we : Te, + this.target = e.target && 3 === e.target.nodeType ? e.target.parentNode : e.target, + this.currentTarget = e.currentTarget, + this.relatedTarget = e.relatedTarget) : this.type = e, + t && S.extend(this, t), + this.timeStamp = e && e.timeStamp || Date.now(), + this[S.expando] = !0 + } + , + S.Event.prototype = { + constructor: S.Event, + isDefaultPrevented: Te, + isPropagationStopped: Te, + isImmediatePropagationStopped: Te, + isSimulated: !1, + preventDefault: function() { + var e = this.originalEvent; + this.isDefaultPrevented = we, + e && !this.isSimulated && e.preventDefault() + }, + stopPropagation: function() { + var e = this.originalEvent; + this.isPropagationStopped = we, + e && !this.isSimulated && e.stopPropagation() + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + this.isImmediatePropagationStopped = we, + e && !this.isSimulated && e.stopImmediatePropagation(), + this.stopPropagation() + } + }, + S.each({ + altKey: !0, + bubbles: !0, + cancelable: !0, + changedTouches: !0, + ctrlKey: !0, + detail: !0, + eventPhase: !0, + metaKey: !0, + pageX: !0, + pageY: !0, + shiftKey: !0, + view: !0, + "char": !0, + code: !0, + charCode: !0, + key: !0, + keyCode: !0, + button: !0, + buttons: !0, + clientX: !0, + clientY: !0, + offsetX: !0, + offsetY: !0, + pointerId: !0, + pointerType: !0, + screenX: !0, + screenY: !0, + targetTouches: !0, + toElement: !0, + touches: !0, + which: !0 + }, S.event.addProp), + S.each({ + focus: "focusin", + blur: "focusout" + }, function(e, t) { + S.event.special[e] = { + setup: function() { + return Se(this, e, Ce), + !1 + }, + trigger: function() { + return Se(this, e), + !0 + }, + _default: function() { + return !0 + }, + delegateType: t + } + }), + S.each({ + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" + }, function(e, i) { + S.event.special[e] = { + delegateType: i, + bindType: i, + handle: function(e) { + var t, n = e.relatedTarget, r = e.handleObj; + return n && (n === this || S.contains(this, n)) || (e.type = r.origType, + t = r.handler.apply(this, arguments), + e.type = i), + t + } + } + }), + S.fn.extend({ + on: function(e, t, n, r) { + return Ee(this, e, t, n, r) + }, + one: function(e, t, n, r) { + return Ee(this, e, t, n, r, 1) + }, + off: function(e, t, n) { + var r, i; + if (e && e.preventDefault && e.handleObj) + return r = e.handleObj, + S(e.delegateTarget).off(r.namespace ? r.origType + "." + r.namespace : r.origType, r.selector, r.handler), + this; + if ("object" == typeof e) { + for (i in e) + this.off(i, t, e[i]); + return this + } + return !1 !== t && "function" != typeof t || (n = t, + t = void 0), + !1 === n && (n = Te), + this.each(function() { + S.event.remove(this, e, n, t) + }) + } + }); + var ke = /\s*$/g; + function je(e, t) { + return A(e, "table") && A(11 !== t.nodeType ? t : t.firstChild, "tr") && S(e).children("tbody")[0] || e + } + function De(e) { + return e.type = (null !== e.getAttribute("type")) + "/" + e.type, + e + } + function qe(e) { + return "true/" === (e.type || "").slice(0, 5) ? e.type = e.type.slice(5) : e.removeAttribute("type"), + e + } + function Le(e, t) { + var n, r, i, o, a, s; + if (1 === t.nodeType) { + if (Y.hasData(e) && (s = Y.get(e).events)) + for (i in Y.remove(t, "handle events"), + s) + for (n = 0, + r = s[i].length; n < r; n++) + S.event.add(t, i, s[i][n]); + Q.hasData(e) && (o = Q.access(e), + a = S.extend({}, o), + Q.set(t, a)) + } + } + function He(n, r, i, o) { + r = g(r); + var e, t, a, s, u, l, c = 0, f = n.length, p = f - 1, d = r[0], h = m(d); + if (h || 1 < f && "string" == typeof d && !y.checkClone && Ae.test(d)) + return n.each(function(e) { + var t = n.eq(e); + h && (r[0] = d.call(this, e, t.html())), + He(t, r, i, o) + }); + if (f && (t = (e = xe(r, n[0].ownerDocument, !1, n, o)).firstChild, + 1 === e.childNodes.length && (e = t), + t || o)) { + for (s = (a = S.map(ve(e, "script"), De)).length; c < f; c++) + u = e, + c !== p && (u = S.clone(u, !0, !0), + s && S.merge(a, ve(u, "script"))), + i.call(n[c], u, c); + if (s) + for (l = a[a.length - 1].ownerDocument, + S.map(a, qe), + c = 0; c < s; c++) + u = a[c], + he.test(u.type || "") && !Y.access(u, "globalEval") && S.contains(l, u) && (u.src && "module" !== (u.type || "").toLowerCase() ? S._evalUrl && !u.noModule && S._evalUrl(u.src, { + nonce: u.nonce || u.getAttribute("nonce") + }, l) : b(u.textContent.replace(Ne, ""), u, l)) + } + return n + } + function Oe(e, t, n) { + for (var r, i = t ? S.filter(t, e) : e, o = 0; null != (r = i[o]); o++) + n || 1 !== r.nodeType || S.cleanData(ve(r)), + r.parentNode && (n && ie(r) && ye(ve(r, "script")), + r.parentNode.removeChild(r)); + return e + } + S.extend({ + htmlPrefilter: function(e) { + return e + }, + clone: function(e, t, n) { + var r, i, o, a, s, u, l, c = e.cloneNode(!0), f = ie(e); + if (!(y.noCloneChecked || 1 !== e.nodeType && 11 !== e.nodeType || S.isXMLDoc(e))) + for (a = ve(c), + r = 0, + i = (o = ve(e)).length; r < i; r++) + s = o[r], + u = a[r], + void 0, + "input" === (l = u.nodeName.toLowerCase()) && pe.test(s.type) ? u.checked = s.checked : "input" !== l && "textarea" !== l || (u.defaultValue = s.defaultValue); + if (t) + if (n) + for (o = o || ve(e), + a = a || ve(c), + r = 0, + i = o.length; r < i; r++) + Le(o[r], a[r]); + else + Le(e, c); + return 0 < (a = ve(c, "script")).length && ye(a, !f && ve(e, "script")), + c + }, + cleanData: function(e) { + for (var t, n, r, i = S.event.special, o = 0; void 0 !== (n = e[o]); o++) + if (V(n)) { + if (t = n[Y.expando]) { + if (t.events) + for (r in t.events) + i[r] ? S.event.remove(n, r) : S.removeEvent(n, r, t.handle); + n[Y.expando] = void 0 + } + n[Q.expando] && (n[Q.expando] = void 0) + } + } + }), + S.fn.extend({ + detach: function(e) { + return Oe(this, e, !0) + }, + remove: function(e) { + return Oe(this, e) + }, + text: function(e) { + return $(this, function(e) { + return void 0 === e ? S.text(this) : this.empty().each(function() { + 1 !== this.nodeType && 11 !== this.nodeType && 9 !== this.nodeType || (this.textContent = e) + }) + }, null, e, arguments.length) + }, + append: function() { + return He(this, arguments, function(e) { + 1 !== this.nodeType && 11 !== this.nodeType && 9 !== this.nodeType || je(this, e).appendChild(e) + }) + }, + prepend: function() { + return He(this, arguments, function(e) { + if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { + var t = je(this, e); + t.insertBefore(e, t.firstChild) + } + }) + }, + before: function() { + return He(this, arguments, function(e) { + this.parentNode && this.parentNode.insertBefore(e, this) + }) + }, + after: function() { + return He(this, arguments, function(e) { + this.parentNode && this.parentNode.insertBefore(e, this.nextSibling) + }) + }, + empty: function() { + for (var e, t = 0; null != (e = this[t]); t++) + 1 === e.nodeType && (S.cleanData(ve(e, !1)), + e.textContent = ""); + return this + }, + clone: function(e, t) { + return e = null != e && e, + t = null == t ? e : t, + this.map(function() { + return S.clone(this, e, t) + }) + }, + html: function(e) { + return $(this, function(e) { + var t = this[0] || {} + , n = 0 + , r = this.length; + if (void 0 === e && 1 === t.nodeType) + return t.innerHTML; + if ("string" == typeof e && !ke.test(e) && !ge[(de.exec(e) || ["", ""])[1].toLowerCase()]) { + e = S.htmlPrefilter(e); + try { + for (; n < r; n++) + 1 === (t = this[n] || {}).nodeType && (S.cleanData(ve(t, !1)), + t.innerHTML = e); + t = 0 + } catch (e) {} + } + t && this.empty().append(e) + }, null, e, arguments.length) + }, + replaceWith: function() { + var n = []; + return He(this, arguments, function(e) { + var t = this.parentNode; + S.inArray(this, n) < 0 && (S.cleanData(ve(this)), + t && t.replaceChild(e, this)) + }, n) + } + }), + S.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" + }, function(e, a) { + S.fn[e] = function(e) { + for (var t, n = [], r = S(e), i = r.length - 1, o = 0; o <= i; o++) + t = o === i ? this : this.clone(!0), + S(r[o])[a](t), + u.apply(n, t.get()); + return this.pushStack(n) + } + }); + var Pe = new RegExp("^(" + ee + ")(?!px)[a-z%]+$","i") + , Re = function(e) { + var t = e.ownerDocument.defaultView; + return t && t.opener || (t = C), + t.getComputedStyle(e) + } + , Me = function(e, t, n) { + var r, i, o = {}; + for (i in t) + o[i] = e.style[i], + e.style[i] = t[i]; + for (i in r = n.call(e), + t) + e.style[i] = o[i]; + return r + } + , Ie = new RegExp(ne.join("|"),"i"); + function We(e, t, n) { + var r, i, o, a, s = e.style; + return (n = n || Re(e)) && ("" !== (a = n.getPropertyValue(t) || n[t]) || ie(e) || (a = S.style(e, t)), + !y.pixelBoxStyles() && Pe.test(a) && Ie.test(t) && (r = s.width, + i = s.minWidth, + o = s.maxWidth, + s.minWidth = s.maxWidth = s.width = a, + a = n.width, + s.width = r, + s.minWidth = i, + s.maxWidth = o)), + void 0 !== a ? a + "" : a + } + function Fe(e, t) { + return { + get: function() { + if (!e()) + return (this.get = t).apply(this, arguments); + delete this.get + } + } + } + !function() { + function e() { + if (l) { + u.style.cssText = "position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0", + l.style.cssText = "position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%", + re.appendChild(u).appendChild(l); + var e = C.getComputedStyle(l); + n = "1%" !== e.top, + s = 12 === t(e.marginLeft), + l.style.right = "60%", + o = 36 === t(e.right), + r = 36 === t(e.width), + l.style.position = "absolute", + i = 12 === t(l.offsetWidth / 3), + re.removeChild(u), + l = null + } + } + function t(e) { + return Math.round(parseFloat(e)) + } + var n, r, i, o, a, s, u = E.createElement("div"), l = E.createElement("div"); + l.style && (l.style.backgroundClip = "content-box", + l.cloneNode(!0).style.backgroundClip = "", + y.clearCloneStyle = "content-box" === l.style.backgroundClip, + S.extend(y, { + boxSizingReliable: function() { + return e(), + r + }, + pixelBoxStyles: function() { + return e(), + o + }, + pixelPosition: function() { + return e(), + n + }, + reliableMarginLeft: function() { + return e(), + s + }, + scrollboxSize: function() { + return e(), + i + }, + reliableTrDimensions: function() { + var e, t, n, r; + return null == a && (e = E.createElement("table"), + t = E.createElement("tr"), + n = E.createElement("div"), + e.style.cssText = "position:absolute;left:-11111px;border-collapse:separate", + t.style.cssText = "border:1px solid", + t.style.height = "1px", + n.style.height = "9px", + n.style.display = "block", + re.appendChild(e).appendChild(t).appendChild(n), + r = C.getComputedStyle(t), + a = parseInt(r.height, 10) + parseInt(r.borderTopWidth, 10) + parseInt(r.borderBottomWidth, 10) === t.offsetHeight, + re.removeChild(e)), + a + } + })) + }(); + var Be = ["Webkit", "Moz", "ms"] + , $e = E.createElement("div").style + , _e = {}; + function ze(e) { + var t = S.cssProps[e] || _e[e]; + return t || (e in $e ? e : _e[e] = function(e) { + var t = e[0].toUpperCase() + e.slice(1) + , n = Be.length; + while (n--) + if ((e = Be[n] + t)in $e) + return e + }(e) || e) + } + var Ue = /^(none|table(?!-c[ea]).+)/ + , Xe = /^--/ + , Ve = { + position: "absolute", + visibility: "hidden", + display: "block" + } + , Ge = { + letterSpacing: "0", + fontWeight: "400" + }; + function Ye(e, t, n) { + var r = te.exec(t); + return r ? Math.max(0, r[2] - (n || 0)) + (r[3] || "px") : t + } + function Qe(e, t, n, r, i, o) { + var a = "width" === t ? 1 : 0 + , s = 0 + , u = 0; + if (n === (r ? "border" : "content")) + return 0; + for (; a < 4; a += 2) + "margin" === n && (u += S.css(e, n + ne[a], !0, i)), + r ? ("content" === n && (u -= S.css(e, "padding" + ne[a], !0, i)), + "margin" !== n && (u -= S.css(e, "border" + ne[a] + "Width", !0, i))) : (u += S.css(e, "padding" + ne[a], !0, i), + "padding" !== n ? u += S.css(e, "border" + ne[a] + "Width", !0, i) : s += S.css(e, "border" + ne[a] + "Width", !0, i)); + return !r && 0 <= o && (u += Math.max(0, Math.ceil(e["offset" + t[0].toUpperCase() + t.slice(1)] - o - u - s - .5)) || 0), + u + } + function Je(e, t, n) { + var r = Re(e) + , i = (!y.boxSizingReliable() || n) && "border-box" === S.css(e, "boxSizing", !1, r) + , o = i + , a = We(e, t, r) + , s = "offset" + t[0].toUpperCase() + t.slice(1); + if (Pe.test(a)) { + if (!n) + return a; + a = "auto" + } + return (!y.boxSizingReliable() && i || !y.reliableTrDimensions() && A(e, "tr") || "auto" === a || !parseFloat(a) && "inline" === S.css(e, "display", !1, r)) && e.getClientRects().length && (i = "border-box" === S.css(e, "boxSizing", !1, r), + (o = s in e) && (a = e[s])), + (a = parseFloat(a) || 0) + Qe(e, t, n || (i ? "border" : "content"), o, r, a) + "px" + } + function Ke(e, t, n, r, i) { + return new Ke.prototype.init(e,t,n,r,i) + } + S.extend({ + cssHooks: { + opacity: { + get: function(e, t) { + if (t) { + var n = We(e, "opacity"); + return "" === n ? "1" : n + } + } + } + }, + cssNumber: { + animationIterationCount: !0, + columnCount: !0, + fillOpacity: !0, + flexGrow: !0, + flexShrink: !0, + fontWeight: !0, + gridArea: !0, + gridColumn: !0, + gridColumnEnd: !0, + gridColumnStart: !0, + gridRow: !0, + gridRowEnd: !0, + gridRowStart: !0, + lineHeight: !0, + opacity: !0, + order: !0, + orphans: !0, + widows: !0, + zIndex: !0, + zoom: !0 + }, + cssProps: {}, + style: function(e, t, n, r) { + if (e && 3 !== e.nodeType && 8 !== e.nodeType && e.style) { + var i, o, a, s = X(t), u = Xe.test(t), l = e.style; + if (u || (t = ze(s)), + a = S.cssHooks[t] || S.cssHooks[s], + void 0 === n) + return a && "get"in a && void 0 !== (i = a.get(e, !1, r)) ? i : l[t]; + "string" === (o = typeof n) && (i = te.exec(n)) && i[1] && (n = se(e, t, i), + o = "number"), + null != n && n == n && ("number" !== o || u || (n += i && i[3] || (S.cssNumber[s] ? "" : "px")), + y.clearCloneStyle || "" !== n || 0 !== t.indexOf("background") || (l[t] = "inherit"), + a && "set"in a && void 0 === (n = a.set(e, n, r)) || (u ? l.setProperty(t, n) : l[t] = n)) + } + }, + css: function(e, t, n, r) { + var i, o, a, s = X(t); + return Xe.test(t) || (t = ze(s)), + (a = S.cssHooks[t] || S.cssHooks[s]) && "get"in a && (i = a.get(e, !0, n)), + void 0 === i && (i = We(e, t, r)), + "normal" === i && t in Ge && (i = Ge[t]), + "" === n || n ? (o = parseFloat(i), + !0 === n || isFinite(o) ? o || 0 : i) : i + } + }), + S.each(["height", "width"], function(e, u) { + S.cssHooks[u] = { + get: function(e, t, n) { + if (t) + return !Ue.test(S.css(e, "display")) || e.getClientRects().length && e.getBoundingClientRect().width ? Je(e, u, n) : Me(e, Ve, function() { + return Je(e, u, n) + }) + }, + set: function(e, t, n) { + var r, i = Re(e), o = !y.scrollboxSize() && "absolute" === i.position, a = (o || n) && "border-box" === S.css(e, "boxSizing", !1, i), s = n ? Qe(e, u, n, a, i) : 0; + return a && o && (s -= Math.ceil(e["offset" + u[0].toUpperCase() + u.slice(1)] - parseFloat(i[u]) - Qe(e, u, "border", !1, i) - .5)), + s && (r = te.exec(t)) && "px" !== (r[3] || "px") && (e.style[u] = t, + t = S.css(e, u)), + Ye(0, t, s) + } + } + }), + S.cssHooks.marginLeft = Fe(y.reliableMarginLeft, function(e, t) { + if (t) + return (parseFloat(We(e, "marginLeft")) || e.getBoundingClientRect().left - Me(e, { + marginLeft: 0 + }, function() { + return e.getBoundingClientRect().left + })) + "px" + }), + S.each({ + margin: "", + padding: "", + border: "Width" + }, function(i, o) { + S.cssHooks[i + o] = { + expand: function(e) { + for (var t = 0, n = {}, r = "string" == typeof e ? e.split(" ") : [e]; t < 4; t++) + n[i + ne[t] + o] = r[t] || r[t - 2] || r[0]; + return n + } + }, + "margin" !== i && (S.cssHooks[i + o].set = Ye) + }), + S.fn.extend({ + css: function(e, t) { + return $(this, function(e, t, n) { + var r, i, o = {}, a = 0; + if (Array.isArray(t)) { + for (r = Re(e), + i = t.length; a < i; a++) + o[t[a]] = S.css(e, t[a], !1, r); + return o + } + return void 0 !== n ? S.style(e, t, n) : S.css(e, t) + }, e, t, 1 < arguments.length) + } + }), + ((S.Tween = Ke).prototype = { + constructor: Ke, + init: function(e, t, n, r, i, o) { + this.elem = e, + this.prop = n, + this.easing = i || S.easing._default, + this.options = t, + this.start = this.now = this.cur(), + this.end = r, + this.unit = o || (S.cssNumber[n] ? "" : "px") + }, + cur: function() { + var e = Ke.propHooks[this.prop]; + return e && e.get ? e.get(this) : Ke.propHooks._default.get(this) + }, + run: function(e) { + var t, n = Ke.propHooks[this.prop]; + return this.options.duration ? this.pos = t = S.easing[this.easing](e, this.options.duration * e, 0, 1, this.options.duration) : this.pos = t = e, + this.now = (this.end - this.start) * t + this.start, + this.options.step && this.options.step.call(this.elem, this.now, this), + n && n.set ? n.set(this) : Ke.propHooks._default.set(this), + this + } + }).init.prototype = Ke.prototype, + (Ke.propHooks = { + _default: { + get: function(e) { + var t; + return 1 !== e.elem.nodeType || null != e.elem[e.prop] && null == e.elem.style[e.prop] ? e.elem[e.prop] : (t = S.css(e.elem, e.prop, "")) && "auto" !== t ? t : 0 + }, + set: function(e) { + S.fx.step[e.prop] ? S.fx.step[e.prop](e) : 1 !== e.elem.nodeType || !S.cssHooks[e.prop] && null == e.elem.style[ze(e.prop)] ? e.elem[e.prop] = e.now : S.style(e.elem, e.prop, e.now + e.unit) + } + } + }).scrollTop = Ke.propHooks.scrollLeft = { + set: function(e) { + e.elem.nodeType && e.elem.parentNode && (e.elem[e.prop] = e.now) + } + }, + S.easing = { + linear: function(e) { + return e + }, + swing: function(e) { + return .5 - Math.cos(e * Math.PI) / 2 + }, + _default: "swing" + }, + S.fx = Ke.prototype.init, + S.fx.step = {}; + var Ze, et, tt, nt, rt = /^(?:toggle|show|hide)$/, it = /queueHooks$/; + function ot() { + et && (!1 === E.hidden && C.requestAnimationFrame ? C.requestAnimationFrame(ot) : C.setTimeout(ot, S.fx.interval), + S.fx.tick()) + } + function at() { + return C.setTimeout(function() { + Ze = void 0 + }), + Ze = Date.now() + } + function st(e, t) { + var n, r = 0, i = { + height: e + }; + for (t = t ? 1 : 0; r < 4; r += 2 - t) + i["margin" + (n = ne[r])] = i["padding" + n] = e; + return t && (i.opacity = i.width = e), + i + } + function ut(e, t, n) { + for (var r, i = (lt.tweeners[t] || []).concat(lt.tweeners["*"]), o = 0, a = i.length; o < a; o++) + if (r = i[o].call(n, t, e)) + return r + } + function lt(o, e, t) { + var n, a, r = 0, i = lt.prefilters.length, s = S.Deferred().always(function() { + delete u.elem + }), u = function() { + if (a) + return !1; + for (var e = Ze || at(), t = Math.max(0, l.startTime + l.duration - e), n = 1 - (t / l.duration || 0), r = 0, i = l.tweens.length; r < i; r++) + l.tweens[r].run(n); + return s.notifyWith(o, [l, n, t]), + n < 1 && i ? t : (i || s.notifyWith(o, [l, 1, 0]), + s.resolveWith(o, [l]), + !1) + }, l = s.promise({ + elem: o, + props: S.extend({}, e), + opts: S.extend(!0, { + specialEasing: {}, + easing: S.easing._default + }, t), + originalProperties: e, + originalOptions: t, + startTime: Ze || at(), + duration: t.duration, + tweens: [], + createTween: function(e, t) { + var n = S.Tween(o, l.opts, e, t, l.opts.specialEasing[e] || l.opts.easing); + return l.tweens.push(n), + n + }, + stop: function(e) { + var t = 0 + , n = e ? l.tweens.length : 0; + if (a) + return this; + for (a = !0; t < n; t++) + l.tweens[t].run(1); + return e ? (s.notifyWith(o, [l, 1, 0]), + s.resolveWith(o, [l, e])) : s.rejectWith(o, [l, e]), + this + } + }), c = l.props; + for (!function(e, t) { + var n, r, i, o, a; + for (n in e) + if (i = t[r = X(n)], + o = e[n], + Array.isArray(o) && (i = o[1], + o = e[n] = o[0]), + n !== r && (e[r] = o, + delete e[n]), + (a = S.cssHooks[r]) && "expand"in a) + for (n in o = a.expand(o), + delete e[r], + o) + n in e || (e[n] = o[n], + t[n] = i); + else + t[r] = i + }(c, l.opts.specialEasing); r < i; r++) + if (n = lt.prefilters[r].call(l, o, c, l.opts)) + return m(n.stop) && (S._queueHooks(l.elem, l.opts.queue).stop = n.stop.bind(n)), + n; + return S.map(c, ut, l), + m(l.opts.start) && l.opts.start.call(o, l), + l.progress(l.opts.progress).done(l.opts.done, l.opts.complete).fail(l.opts.fail).always(l.opts.always), + S.fx.timer(S.extend(u, { + elem: o, + anim: l, + queue: l.opts.queue + })), + l + } + S.Animation = S.extend(lt, { + tweeners: { + "*": [function(e, t) { + var n = this.createTween(e, t); + return se(n.elem, e, te.exec(t), n), + n + } + ] + }, + tweener: function(e, t) { + m(e) ? (t = e, + e = ["*"]) : e = e.match(P); + for (var n, r = 0, i = e.length; r < i; r++) + n = e[r], + lt.tweeners[n] = lt.tweeners[n] || [], + lt.tweeners[n].unshift(t) + }, + prefilters: [function(e, t, n) { + var r, i, o, a, s, u, l, c, f = "width"in t || "height"in t, p = this, d = {}, h = e.style, g = e.nodeType && ae(e), v = Y.get(e, "fxshow"); + for (r in n.queue || (null == (a = S._queueHooks(e, "fx")).unqueued && (a.unqueued = 0, + s = a.empty.fire, + a.empty.fire = function() { + a.unqueued || s() + } + ), + a.unqueued++, + p.always(function() { + p.always(function() { + a.unqueued--, + S.queue(e, "fx").length || a.empty.fire() + }) + })), + t) + if (i = t[r], + rt.test(i)) { + if (delete t[r], + o = o || "toggle" === i, + i === (g ? "hide" : "show")) { + if ("show" !== i || !v || void 0 === v[r]) + continue; + g = !0 + } + d[r] = v && v[r] || S.style(e, r) + } + if ((u = !S.isEmptyObject(t)) || !S.isEmptyObject(d)) + for (r in f && 1 === e.nodeType && (n.overflow = [h.overflow, h.overflowX, h.overflowY], + null == (l = v && v.display) && (l = Y.get(e, "display")), + "none" === (c = S.css(e, "display")) && (l ? c = l : (le([e], !0), + l = e.style.display || l, + c = S.css(e, "display"), + le([e]))), + ("inline" === c || "inline-block" === c && null != l) && "none" === S.css(e, "float") && (u || (p.done(function() { + h.display = l + }), + null == l && (c = h.display, + l = "none" === c ? "" : c)), + h.display = "inline-block")), + n.overflow && (h.overflow = "hidden", + p.always(function() { + h.overflow = n.overflow[0], + h.overflowX = n.overflow[1], + h.overflowY = n.overflow[2] + })), + u = !1, + d) + u || (v ? "hidden"in v && (g = v.hidden) : v = Y.access(e, "fxshow", { + display: l + }), + o && (v.hidden = !g), + g && le([e], !0), + p.done(function() { + for (r in g || le([e]), + Y.remove(e, "fxshow"), + d) + S.style(e, r, d[r]) + })), + u = ut(g ? v[r] : 0, r, p), + r in v || (v[r] = u.start, + g && (u.end = u.start, + u.start = 0)) + } + ], + prefilter: function(e, t) { + t ? lt.prefilters.unshift(e) : lt.prefilters.push(e) + } + }), + S.speed = function(e, t, n) { + var r = e && "object" == typeof e ? S.extend({}, e) : { + complete: n || !n && t || m(e) && e, + duration: e, + easing: n && t || t && !m(t) && t + }; + return S.fx.off ? r.duration = 0 : "number" != typeof r.duration && (r.duration in S.fx.speeds ? r.duration = S.fx.speeds[r.duration] : r.duration = S.fx.speeds._default), + null != r.queue && !0 !== r.queue || (r.queue = "fx"), + r.old = r.complete, + r.complete = function() { + m(r.old) && r.old.call(this), + r.queue && S.dequeue(this, r.queue) + } + , + r + } + , + S.fn.extend({ + fadeTo: function(e, t, n, r) { + return this.filter(ae).css("opacity", 0).show().end().animate({ + opacity: t + }, e, n, r) + }, + animate: function(t, e, n, r) { + var i = S.isEmptyObject(t) + , o = S.speed(e, n, r) + , a = function() { + var e = lt(this, S.extend({}, t), o); + (i || Y.get(this, "finish")) && e.stop(!0) + }; + return a.finish = a, + i || !1 === o.queue ? this.each(a) : this.queue(o.queue, a) + }, + stop: function(i, e, o) { + var a = function(e) { + var t = e.stop; + delete e.stop, + t(o) + }; + return "string" != typeof i && (o = e, + e = i, + i = void 0), + e && this.queue(i || "fx", []), + this.each(function() { + var e = !0 + , t = null != i && i + "queueHooks" + , n = S.timers + , r = Y.get(this); + if (t) + r[t] && r[t].stop && a(r[t]); + else + for (t in r) + r[t] && r[t].stop && it.test(t) && a(r[t]); + for (t = n.length; t--; ) + n[t].elem !== this || null != i && n[t].queue !== i || (n[t].anim.stop(o), + e = !1, + n.splice(t, 1)); + !e && o || S.dequeue(this, i) + }) + }, + finish: function(a) { + return !1 !== a && (a = a || "fx"), + this.each(function() { + var e, t = Y.get(this), n = t[a + "queue"], r = t[a + "queueHooks"], i = S.timers, o = n ? n.length : 0; + for (t.finish = !0, + S.queue(this, a, []), + r && r.stop && r.stop.call(this, !0), + e = i.length; e--; ) + i[e].elem === this && i[e].queue === a && (i[e].anim.stop(!0), + i.splice(e, 1)); + for (e = 0; e < o; e++) + n[e] && n[e].finish && n[e].finish.call(this); + delete t.finish + }) + } + }), + S.each(["toggle", "show", "hide"], function(e, r) { + var i = S.fn[r]; + S.fn[r] = function(e, t, n) { + return null == e || "boolean" == typeof e ? i.apply(this, arguments) : this.animate(st(r, !0), e, t, n) + } + }), + S.each({ + slideDown: st("show"), + slideUp: st("hide"), + slideToggle: st("toggle"), + fadeIn: { + opacity: "show" + }, + fadeOut: { + opacity: "hide" + }, + fadeToggle: { + opacity: "toggle" + } + }, function(e, r) { + S.fn[e] = function(e, t, n) { + return this.animate(r, e, t, n) + } + }), + S.timers = [], + S.fx.tick = function() { + var e, t = 0, n = S.timers; + for (Ze = Date.now(); t < n.length; t++) + (e = n[t])() || n[t] !== e || n.splice(t--, 1); + n.length || S.fx.stop(), + Ze = void 0 + } + , + S.fx.timer = function(e) { + S.timers.push(e), + S.fx.start() + } + , + S.fx.interval = 13, + S.fx.start = function() { + et || (et = !0, + ot()) + } + , + S.fx.stop = function() { + et = null + } + , + S.fx.speeds = { + slow: 600, + fast: 200, + _default: 400 + }, + S.fn.delay = function(r, e) { + return r = S.fx && S.fx.speeds[r] || r, + e = e || "fx", + this.queue(e, function(e, t) { + var n = C.setTimeout(e, r); + t.stop = function() { + C.clearTimeout(n) + } + }) + } + , + tt = E.createElement("input"), + nt = E.createElement("select").appendChild(E.createElement("option")), + tt.type = "checkbox", + y.checkOn = "" !== tt.value, + y.optSelected = nt.selected, + (tt = E.createElement("input")).value = "t", + tt.type = "radio", + y.radioValue = "t" === tt.value; + var ct, ft = S.expr.attrHandle; + S.fn.extend({ + attr: function(e, t) { + return $(this, S.attr, e, t, 1 < arguments.length) + }, + removeAttr: function(e) { + return this.each(function() { + S.removeAttr(this, e) + }) + } + }), + S.extend({ + attr: function(e, t, n) { + var r, i, o = e.nodeType; + if (3 !== o && 8 !== o && 2 !== o) + return "undefined" == typeof e.getAttribute ? S.prop(e, t, n) : (1 === o && S.isXMLDoc(e) || (i = S.attrHooks[t.toLowerCase()] || (S.expr.match.bool.test(t) ? ct : void 0)), + void 0 !== n ? null === n ? void S.removeAttr(e, t) : i && "set"in i && void 0 !== (r = i.set(e, n, t)) ? r : (e.setAttribute(t, n + ""), + n) : i && "get"in i && null !== (r = i.get(e, t)) ? r : null == (r = S.find.attr(e, t)) ? void 0 : r) + }, + attrHooks: { + type: { + set: function(e, t) { + if (!y.radioValue && "radio" === t && A(e, "input")) { + var n = e.value; + return e.setAttribute("type", t), + n && (e.value = n), + t + } + } + } + }, + removeAttr: function(e, t) { + var n, r = 0, i = t && t.match(P); + if (i && 1 === e.nodeType) + while (n = i[r++]) + e.removeAttribute(n) + } + }), + ct = { + set: function(e, t, n) { + return !1 === t ? S.removeAttr(e, n) : e.setAttribute(n, n), + n + } + }, + S.each(S.expr.match.bool.source.match(/\w+/g), function(e, t) { + var a = ft[t] || S.find.attr; + ft[t] = function(e, t, n) { + var r, i, o = t.toLowerCase(); + return n || (i = ft[o], + ft[o] = r, + r = null != a(e, t, n) ? o : null, + ft[o] = i), + r + } + }); + var pt = /^(?:input|select|textarea|button)$/i + , dt = /^(?:a|area)$/i; + function ht(e) { + return (e.match(P) || []).join(" ") + } + function gt(e) { + return e.getAttribute && e.getAttribute("class") || "" + } + function vt(e) { + return Array.isArray(e) ? e : "string" == typeof e && e.match(P) || [] + } + S.fn.extend({ + prop: function(e, t) { + return $(this, S.prop, e, t, 1 < arguments.length) + }, + removeProp: function(e) { + return this.each(function() { + delete this[S.propFix[e] || e] + }) + } + }), + S.extend({ + prop: function(e, t, n) { + var r, i, o = e.nodeType; + if (3 !== o && 8 !== o && 2 !== o) + return 1 === o && S.isXMLDoc(e) || (t = S.propFix[t] || t, + i = S.propHooks[t]), + void 0 !== n ? i && "set"in i && void 0 !== (r = i.set(e, n, t)) ? r : e[t] = n : i && "get"in i && null !== (r = i.get(e, t)) ? r : e[t] + }, + propHooks: { + tabIndex: { + get: function(e) { + var t = S.find.attr(e, "tabindex"); + return t ? parseInt(t, 10) : pt.test(e.nodeName) || dt.test(e.nodeName) && e.href ? 0 : -1 + } + } + }, + propFix: { + "for": "htmlFor", + "class": "className" + } + }), + y.optSelected || (S.propHooks.selected = { + get: function(e) { + var t = e.parentNode; + return t && t.parentNode && t.parentNode.selectedIndex, + null + }, + set: function(e) { + var t = e.parentNode; + t && (t.selectedIndex, + t.parentNode && t.parentNode.selectedIndex) + } + }), + S.each(["tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable"], function() { + S.propFix[this.toLowerCase()] = this + }), + S.fn.extend({ + addClass: function(t) { + var e, n, r, i, o, a, s, u = 0; + if (m(t)) + return this.each(function(e) { + S(this).addClass(t.call(this, e, gt(this))) + }); + if ((e = vt(t)).length) + while (n = this[u++]) + if (i = gt(n), + r = 1 === n.nodeType && " " + ht(i) + " ") { + a = 0; + while (o = e[a++]) + r.indexOf(" " + o + " ") < 0 && (r += o + " "); + i !== (s = ht(r)) && n.setAttribute("class", s) + } + return this + }, + removeClass: function(t) { + var e, n, r, i, o, a, s, u = 0; + if (m(t)) + return this.each(function(e) { + S(this).removeClass(t.call(this, e, gt(this))) + }); + if (!arguments.length) + return this.attr("class", ""); + if ((e = vt(t)).length) + while (n = this[u++]) + if (i = gt(n), + r = 1 === n.nodeType && " " + ht(i) + " ") { + a = 0; + while (o = e[a++]) + while (-1 < r.indexOf(" " + o + " ")) + r = r.replace(" " + o + " ", " "); + i !== (s = ht(r)) && n.setAttribute("class", s) + } + return this + }, + toggleClass: function(i, t) { + var o = typeof i + , a = "string" === o || Array.isArray(i); + return "boolean" == typeof t && a ? t ? this.addClass(i) : this.removeClass(i) : m(i) ? this.each(function(e) { + S(this).toggleClass(i.call(this, e, gt(this), t), t) + }) : this.each(function() { + var e, t, n, r; + if (a) { + t = 0, + n = S(this), + r = vt(i); + while (e = r[t++]) + n.hasClass(e) ? n.removeClass(e) : n.addClass(e) + } else + void 0 !== i && "boolean" !== o || ((e = gt(this)) && Y.set(this, "__className__", e), + this.setAttribute && this.setAttribute("class", e || !1 === i ? "" : Y.get(this, "__className__") || "")) + }) + }, + hasClass: function(e) { + var t, n, r = 0; + t = " " + e + " "; + while (n = this[r++]) + if (1 === n.nodeType && -1 < (" " + ht(gt(n)) + " ").indexOf(t)) + return !0; + return !1 + } + }); + var yt = /\r/g; + S.fn.extend({ + val: function(n) { + var r, e, i, t = this[0]; + return arguments.length ? (i = m(n), + this.each(function(e) { + var t; + 1 === this.nodeType && (null == (t = i ? n.call(this, e, S(this).val()) : n) ? t = "" : "number" == typeof t ? t += "" : Array.isArray(t) && (t = S.map(t, function(e) { + return null == e ? "" : e + "" + })), + (r = S.valHooks[this.type] || S.valHooks[this.nodeName.toLowerCase()]) && "set"in r && void 0 !== r.set(this, t, "value") || (this.value = t)) + })) : t ? (r = S.valHooks[t.type] || S.valHooks[t.nodeName.toLowerCase()]) && "get"in r && void 0 !== (e = r.get(t, "value")) ? e : "string" == typeof (e = t.value) ? e.replace(yt, "") : null == e ? "" : e : void 0 + } + }), + S.extend({ + valHooks: { + option: { + get: function(e) { + var t = S.find.attr(e, "value"); + return null != t ? t : ht(S.text(e)) + } + }, + select: { + get: function(e) { + var t, n, r, i = e.options, o = e.selectedIndex, a = "select-one" === e.type, s = a ? null : [], u = a ? o + 1 : i.length; + for (r = o < 0 ? u : a ? o : 0; r < u; r++) + if (((n = i[r]).selected || r === o) && !n.disabled && (!n.parentNode.disabled || !A(n.parentNode, "optgroup"))) { + if (t = S(n).val(), + a) + return t; + s.push(t) + } + return s + }, + set: function(e, t) { + var n, r, i = e.options, o = S.makeArray(t), a = i.length; + while (a--) + ((r = i[a]).selected = -1 < S.inArray(S.valHooks.option.get(r), o)) && (n = !0); + return n || (e.selectedIndex = -1), + o + } + } + } + }), + S.each(["radio", "checkbox"], function() { + S.valHooks[this] = { + set: function(e, t) { + if (Array.isArray(t)) + return e.checked = -1 < S.inArray(S(e).val(), t) + } + }, + y.checkOn || (S.valHooks[this].get = function(e) { + return null === e.getAttribute("value") ? "on" : e.value + } + ) + }), + y.focusin = "onfocusin"in C; + var mt = /^(?:focusinfocus|focusoutblur)$/ + , xt = function(e) { + e.stopPropagation() + }; + S.extend(S.event, { + trigger: function(e, t, n, r) { + var i, o, a, s, u, l, c, f, p = [n || E], d = v.call(e, "type") ? e.type : e, h = v.call(e, "namespace") ? e.namespace.split(".") : []; + if (o = f = a = n = n || E, + 3 !== n.nodeType && 8 !== n.nodeType && !mt.test(d + S.event.triggered) && (-1 < d.indexOf(".") && (d = (h = d.split(".")).shift(), + h.sort()), + u = d.indexOf(":") < 0 && "on" + d, + (e = e[S.expando] ? e : new S.Event(d,"object" == typeof e && e)).isTrigger = r ? 2 : 3, + e.namespace = h.join("."), + e.rnamespace = e.namespace ? new RegExp("(^|\\.)" + h.join("\\.(?:.*\\.|)") + "(\\.|$)") : null, + e.result = void 0, + e.target || (e.target = n), + t = null == t ? [e] : S.makeArray(t, [e]), + c = S.event.special[d] || {}, + r || !c.trigger || !1 !== c.trigger.apply(n, t))) { + if (!r && !c.noBubble && !x(n)) { + for (s = c.delegateType || d, + mt.test(s + d) || (o = o.parentNode); o; o = o.parentNode) + p.push(o), + a = o; + a === (n.ownerDocument || E) && p.push(a.defaultView || a.parentWindow || C) + } + i = 0; + while ((o = p[i++]) && !e.isPropagationStopped()) + f = o, + e.type = 1 < i ? s : c.bindType || d, + (l = (Y.get(o, "events") || Object.create(null))[e.type] && Y.get(o, "handle")) && l.apply(o, t), + (l = u && o[u]) && l.apply && V(o) && (e.result = l.apply(o, t), + !1 === e.result && e.preventDefault()); + return e.type = d, + r || e.isDefaultPrevented() || c._default && !1 !== c._default.apply(p.pop(), t) || !V(n) || u && m(n[d]) && !x(n) && ((a = n[u]) && (n[u] = null), + S.event.triggered = d, + e.isPropagationStopped() && f.addEventListener(d, xt), + n[d](), + e.isPropagationStopped() && f.removeEventListener(d, xt), + S.event.triggered = void 0, + a && (n[u] = a)), + e.result + } + }, + simulate: function(e, t, n) { + var r = S.extend(new S.Event, n, { + type: e, + isSimulated: !0 + }); + S.event.trigger(r, null, t) + } + }), + S.fn.extend({ + trigger: function(e, t) { + return this.each(function() { + S.event.trigger(e, t, this) + }) + }, + triggerHandler: function(e, t) { + var n = this[0]; + if (n) + return S.event.trigger(e, t, n, !0) + } + }), + y.focusin || S.each({ + focus: "focusin", + blur: "focusout" + }, function(n, r) { + var i = function(e) { + S.event.simulate(r, e.target, S.event.fix(e)) + }; + S.event.special[r] = { + setup: function() { + var e = this.ownerDocument || this.document || this + , t = Y.access(e, r); + t || e.addEventListener(n, i, !0), + Y.access(e, r, (t || 0) + 1) + }, + teardown: function() { + var e = this.ownerDocument || this.document || this + , t = Y.access(e, r) - 1; + t ? Y.access(e, r, t) : (e.removeEventListener(n, i, !0), + Y.remove(e, r)) + } + } + }); + var bt = C.location + , wt = { + guid: Date.now() + } + , Tt = /\?/; + S.parseXML = function(e) { + var t, n; + if (!e || "string" != typeof e) + return null; + try { + t = (new C.DOMParser).parseFromString(e, "text/xml") + } catch (e) {} + return n = t && t.getElementsByTagName("parsererror")[0], + t && !n || S.error("Invalid XML: " + (n ? S.map(n.childNodes, function(e) { + return e.textContent + }).join("\n") : e)), + t + } + ; + var Ct = /\[\]$/ + , Et = /\r?\n/g + , St = /^(?:submit|button|image|reset|file)$/i + , kt = /^(?:input|select|textarea|keygen)/i; + function At(n, e, r, i) { + var t; + if (Array.isArray(e)) + S.each(e, function(e, t) { + r || Ct.test(n) ? i(n, t) : At(n + "[" + ("object" == typeof t && null != t ? e : "") + "]", t, r, i) + }); + else if (r || "object" !== w(e)) + i(n, e); + else + for (t in e) + At(n + "[" + t + "]", e[t], r, i) + } + S.param = function(e, t) { + var n, r = [], i = function(e, t) { + var n = m(t) ? t() : t; + r[r.length] = encodeURIComponent(e) + "=" + encodeURIComponent(null == n ? "" : n) + }; + if (null == e) + return ""; + if (Array.isArray(e) || e.jquery && !S.isPlainObject(e)) + S.each(e, function() { + i(this.name, this.value) + }); + else + for (n in e) + At(n, e[n], t, i); + return r.join("&") + } + , + S.fn.extend({ + serialize: function() { + return S.param(this.serializeArray()) + }, + serializeArray: function() { + return this.map(function() { + var e = S.prop(this, "elements"); + return e ? S.makeArray(e) : this + }).filter(function() { + var e = this.type; + return this.name && !S(this).is(":disabled") && kt.test(this.nodeName) && !St.test(e) && (this.checked || !pe.test(e)) + }).map(function(e, t) { + var n = S(this).val(); + return null == n ? null : Array.isArray(n) ? S.map(n, function(e) { + return { + name: t.name, + value: e.replace(Et, "\r\n") + } + }) : { + name: t.name, + value: n.replace(Et, "\r\n") + } + }).get() + } + }); + var Nt = /%20/g + , jt = /#.*$/ + , Dt = /([?&])_=[^&]*/ + , qt = /^(.*?):[ \t]*([^\r\n]*)$/gm + , Lt = /^(?:GET|HEAD)$/ + , Ht = /^\/\// + , Ot = {} + , Pt = {} + , Rt = "*/".concat("*") + , Mt = E.createElement("a"); + function It(o) { + return function(e, t) { + "string" != typeof e && (t = e, + e = "*"); + var n, r = 0, i = e.toLowerCase().match(P) || []; + if (m(t)) + while (n = i[r++]) + "+" === n[0] ? (n = n.slice(1) || "*", + (o[n] = o[n] || []).unshift(t)) : (o[n] = o[n] || []).push(t) + } + } + function Wt(t, i, o, a) { + var s = {} + , u = t === Pt; + function l(e) { + var r; + return s[e] = !0, + S.each(t[e] || [], function(e, t) { + var n = t(i, o, a); + return "string" != typeof n || u || s[n] ? u ? !(r = n) : void 0 : (i.dataTypes.unshift(n), + l(n), + !1) + }), + r + } + return l(i.dataTypes[0]) || !s["*"] && l("*") + } + function Ft(e, t) { + var n, r, i = S.ajaxSettings.flatOptions || {}; + for (n in t) + void 0 !== t[n] && ((i[n] ? e : r || (r = {}))[n] = t[n]); + return r && S.extend(!0, e, r), + e + } + Mt.href = bt.href, + S.extend({ + active: 0, + lastModified: {}, + etag: {}, + ajaxSettings: { + url: bt.href, + type: "GET", + isLocal: /^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(bt.protocol), + global: !0, + processData: !0, + async: !0, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + accepts: { + "*": Rt, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + converters: { + "* text": String, + "text html": !0, + "text json": JSON.parse, + "text xml": S.parseXML + }, + flatOptions: { + url: !0, + context: !0 + } + }, + ajaxSetup: function(e, t) { + return t ? Ft(Ft(e, S.ajaxSettings), t) : Ft(S.ajaxSettings, e) + }, + ajaxPrefilter: It(Ot), + ajaxTransport: It(Pt), + ajax: function(e, t) { + "object" == typeof e && (t = e, + e = void 0), + t = t || {}; + var c, f, p, n, d, r, h, g, i, o, v = S.ajaxSetup({}, t), y = v.context || v, m = v.context && (y.nodeType || y.jquery) ? S(y) : S.event, x = S.Deferred(), b = S.Callbacks("once memory"), w = v.statusCode || {}, a = {}, s = {}, u = "canceled", T = { + readyState: 0, + getResponseHeader: function(e) { + var t; + if (h) { + if (!n) { + n = {}; + while (t = qt.exec(p)) + n[t[1].toLowerCase() + " "] = (n[t[1].toLowerCase() + " "] || []).concat(t[2]) + } + t = n[e.toLowerCase() + " "] + } + return null == t ? null : t.join(", ") + }, + getAllResponseHeaders: function() { + return h ? p : null + }, + setRequestHeader: function(e, t) { + return null == h && (e = s[e.toLowerCase()] = s[e.toLowerCase()] || e, + a[e] = t), + this + }, + overrideMimeType: function(e) { + return null == h && (v.mimeType = e), + this + }, + statusCode: function(e) { + var t; + if (e) + if (h) + T.always(e[T.status]); + else + for (t in e) + w[t] = [w[t], e[t]]; + return this + }, + abort: function(e) { + var t = e || u; + return c && c.abort(t), + l(0, t), + this + } + }; + if (x.promise(T), + v.url = ((e || v.url || bt.href) + "").replace(Ht, bt.protocol + "//"), + v.type = t.method || t.type || v.method || v.type, + v.dataTypes = (v.dataType || "*").toLowerCase().match(P) || [""], + null == v.crossDomain) { + r = E.createElement("a"); + try { + r.href = v.url, + r.href = r.href, + v.crossDomain = Mt.protocol + "//" + Mt.host != r.protocol + "//" + r.host + } catch (e) { + v.crossDomain = !0 + } + } + if (v.data && v.processData && "string" != typeof v.data && (v.data = S.param(v.data, v.traditional)), + Wt(Ot, v, t, T), + h) + return T; + for (i in (g = S.event && v.global) && 0 == S.active++ && S.event.trigger("ajaxStart"), + v.type = v.type.toUpperCase(), + v.hasContent = !Lt.test(v.type), + f = v.url.replace(jt, ""), + v.hasContent ? v.data && v.processData && 0 === (v.contentType || "").indexOf("application/x-www-form-urlencoded") && (v.data = v.data.replace(Nt, "+")) : (o = v.url.slice(f.length), + v.data && (v.processData || "string" == typeof v.data) && (f += (Tt.test(f) ? "&" : "?") + v.data, + delete v.data), + !1 === v.cache && (f = f.replace(Dt, "$1"), + o = (Tt.test(f) ? "&" : "?") + "_=" + wt.guid++ + o), + v.url = f + o), + v.ifModified && (S.lastModified[f] && T.setRequestHeader("If-Modified-Since", S.lastModified[f]), + S.etag[f] && T.setRequestHeader("If-None-Match", S.etag[f])), + (v.data && v.hasContent && !1 !== v.contentType || t.contentType) && T.setRequestHeader("Content-Type", v.contentType), + T.setRequestHeader("Accept", v.dataTypes[0] && v.accepts[v.dataTypes[0]] ? v.accepts[v.dataTypes[0]] + ("*" !== v.dataTypes[0] ? ", " + Rt + "; q=0.01" : "") : v.accepts["*"]), + v.headers) + T.setRequestHeader(i, v.headers[i]); + if (v.beforeSend && (!1 === v.beforeSend.call(y, T, v) || h)) + return T.abort(); + if (u = "abort", + b.add(v.complete), + T.done(v.success), + T.fail(v.error), + c = Wt(Pt, v, t, T)) { + if (T.readyState = 1, + g && m.trigger("ajaxSend", [T, v]), + h) + return T; + v.async && 0 < v.timeout && (d = C.setTimeout(function() { + T.abort("timeout") + }, v.timeout)); + try { + h = !1, + c.send(a, l) + } catch (e) { + if (h) + throw e; + l(-1, e) + } + } else + l(-1, "No Transport"); + function l(e, t, n, r) { + var i, o, a, s, u, l = t; + h || (h = !0, + d && C.clearTimeout(d), + c = void 0, + p = r || "", + T.readyState = 0 < e ? 4 : 0, + i = 200 <= e && e < 300 || 304 === e, + n && (s = function(e, t, n) { + var r, i, o, a, s = e.contents, u = e.dataTypes; + while ("*" === u[0]) + u.shift(), + void 0 === r && (r = e.mimeType || t.getResponseHeader("Content-Type")); + if (r) + for (i in s) + if (s[i] && s[i].test(r)) { + u.unshift(i); + break + } + if (u[0]in n) + o = u[0]; + else { + for (i in n) { + if (!u[0] || e.converters[i + " " + u[0]]) { + o = i; + break + } + a || (a = i) + } + o = o || a + } + if (o) + return o !== u[0] && u.unshift(o), + n[o] + }(v, T, n)), + !i && -1 < S.inArray("script", v.dataTypes) && S.inArray("json", v.dataTypes) < 0 && (v.converters["text script"] = function() {} + ), + s = function(e, t, n, r) { + var i, o, a, s, u, l = {}, c = e.dataTypes.slice(); + if (c[1]) + for (a in e.converters) + l[a.toLowerCase()] = e.converters[a]; + o = c.shift(); + while (o) + if (e.responseFields[o] && (n[e.responseFields[o]] = t), + !u && r && e.dataFilter && (t = e.dataFilter(t, e.dataType)), + u = o, + o = c.shift()) + if ("*" === o) + o = u; + else if ("*" !== u && u !== o) { + if (!(a = l[u + " " + o] || l["* " + o])) + for (i in l) + if ((s = i.split(" "))[1] === o && (a = l[u + " " + s[0]] || l["* " + s[0]])) { + !0 === a ? a = l[i] : !0 !== l[i] && (o = s[0], + c.unshift(s[1])); + break + } + if (!0 !== a) + if (a && e["throws"]) + t = a(t); + else + try { + t = a(t) + } catch (e) { + return { + state: "parsererror", + error: a ? e : "No conversion from " + u + " to " + o + } + } + } + return { + state: "success", + data: t + } + }(v, s, T, i), + i ? (v.ifModified && ((u = T.getResponseHeader("Last-Modified")) && (S.lastModified[f] = u), + (u = T.getResponseHeader("etag")) && (S.etag[f] = u)), + 204 === e || "HEAD" === v.type ? l = "nocontent" : 304 === e ? l = "notmodified" : (l = s.state, + o = s.data, + i = !(a = s.error))) : (a = l, + !e && l || (l = "error", + e < 0 && (e = 0))), + T.status = e, + T.statusText = (t || l) + "", + i ? x.resolveWith(y, [o, l, T]) : x.rejectWith(y, [T, l, a]), + T.statusCode(w), + w = void 0, + g && m.trigger(i ? "ajaxSuccess" : "ajaxError", [T, v, i ? o : a]), + b.fireWith(y, [T, l]), + g && (m.trigger("ajaxComplete", [T, v]), + --S.active || S.event.trigger("ajaxStop"))) + } + return T + }, + getJSON: function(e, t, n) { + return S.get(e, t, n, "json") + }, + getScript: function(e, t) { + return S.get(e, void 0, t, "script") + } + }), + S.each(["get", "post"], function(e, i) { + S[i] = function(e, t, n, r) { + return m(t) && (r = r || n, + n = t, + t = void 0), + S.ajax(S.extend({ + url: e, + type: i, + dataType: r, + data: t, + success: n + }, S.isPlainObject(e) && e)) + } + }), + S.ajaxPrefilter(function(e) { + var t; + for (t in e.headers) + "content-type" === t.toLowerCase() && (e.contentType = e.headers[t] || "") + }), + S._evalUrl = function(e, t, n) { + return S.ajax({ + url: e, + type: "GET", + dataType: "script", + cache: !0, + async: !1, + global: !1, + converters: { + "text script": function() {} + }, + dataFilter: function(e) { + S.globalEval(e, t, n) + } + }) + } + , + S.fn.extend({ + wrapAll: function(e) { + var t; + return this[0] && (m(e) && (e = e.call(this[0])), + t = S(e, this[0].ownerDocument).eq(0).clone(!0), + this[0].parentNode && t.insertBefore(this[0]), + t.map(function() { + var e = this; + while (e.firstElementChild) + e = e.firstElementChild; + return e + }).append(this)), + this + }, + wrapInner: function(n) { + return m(n) ? this.each(function(e) { + S(this).wrapInner(n.call(this, e)) + }) : this.each(function() { + var e = S(this) + , t = e.contents(); + t.length ? t.wrapAll(n) : e.append(n) + }) + }, + wrap: function(t) { + var n = m(t); + return this.each(function(e) { + S(this).wrapAll(n ? t.call(this, e) : t) + }) + }, + unwrap: function(e) { + return this.parent(e).not("body").each(function() { + S(this).replaceWith(this.childNodes) + }), + this + } + }), + S.expr.pseudos.hidden = function(e) { + return !S.expr.pseudos.visible(e) + } + , + S.expr.pseudos.visible = function(e) { + return !!(e.offsetWidth || e.offsetHeight || e.getClientRects().length) + } + , + S.ajaxSettings.xhr = function() { + try { + return new C.XMLHttpRequest + } catch (e) {} + } + ; + var Bt = { + 0: 200, + 1223: 204 + } + , $t = S.ajaxSettings.xhr(); + y.cors = !!$t && "withCredentials"in $t, + y.ajax = $t = !!$t, + S.ajaxTransport(function(i) { + var o, a; + if (y.cors || $t && !i.crossDomain) + return { + send: function(e, t) { + var n, r = i.xhr(); + if (r.open(i.type, i.url, i.async, i.username, i.password), + i.xhrFields) + for (n in i.xhrFields) + r[n] = i.xhrFields[n]; + for (n in i.mimeType && r.overrideMimeType && r.overrideMimeType(i.mimeType), + i.crossDomain || e["X-Requested-With"] || (e["X-Requested-With"] = "XMLHttpRequest"), + e) + r.setRequestHeader(n, e[n]); + o = function(e) { + return function() { + o && (o = a = r.onload = r.onerror = r.onabort = r.ontimeout = r.onreadystatechange = null, + "abort" === e ? r.abort() : "error" === e ? "number" != typeof r.status ? t(0, "error") : t(r.status, r.statusText) : t(Bt[r.status] || r.status, r.statusText, "text" !== (r.responseType || "text") || "string" != typeof r.responseText ? { + binary: r.response + } : { + text: r.responseText + }, r.getAllResponseHeaders())) + } + } + , + r.onload = o(), + a = r.onerror = r.ontimeout = o("error"), + void 0 !== r.onabort ? r.onabort = a : r.onreadystatechange = function() { + 4 === r.readyState && C.setTimeout(function() { + o && a() + }) + } + , + o = o("abort"); + try { + r.send(i.hasContent && i.data || null) + } catch (e) { + if (o) + throw e + } + }, + abort: function() { + o && o() + } + } + }), + S.ajaxPrefilter(function(e) { + e.crossDomain && (e.contents.script = !1) + }), + S.ajaxSetup({ + accepts: { + script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function(e) { + return S.globalEval(e), + e + } + } + }), + S.ajaxPrefilter("script", function(e) { + void 0 === e.cache && (e.cache = !1), + e.crossDomain && (e.type = "GET") + }), + S.ajaxTransport("script", function(n) { + var r, i; + if (n.crossDomain || n.scriptAttrs) + return { + send: function(e, t) { + r = S("